module VCParserSupp /*** VCParserSupp Author: Tomohiro Oda and Paul Chisholm Version: 0.01 License: the MIT License
Copyright (c) 2016 Tomohiro Oda, Paul Chisholm and Software Research Associates, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
***/ importsfrom VCParser values
digit renamed digit
lowerAlphabet renamed lowerAlphabet
upperAlphabet renamed upperAlphabet
alphabet renamed alphabet types PARSER renamed PARSER
SOURCE renamed SOURCE
PARSED renamed PARSED
TREE renamed TREE ERRORrenamedERROR
LABEL renamed LABEL functions label renamed label
either renamed either
concat renamed concat
iterate renamed iterate
takeChar renamed takeChar, fromSeqall, from Numeric all, fromCharall exportsvalues lowerAlphanum, upperAlphanum, alphanum, octal, hex: PARSER functions takeNumeric : [nat1] * [nat1] -> PARSER
takeFixedNumeric : nat1 -> PARSER
takeBoundedString: seq1ofchar * PARSER * nat * nat -> PARSER
takeUpto : seq1ofchar * [PARSER] +> PARSER
takeUptoOneOf : seqofseq1ofchar * [seq1ofchar] * [PARSER] +> PARSER
getContent : LABEL * TREE +> seqofchar
getContentNat : LABEL * TREE +> nat
getTrees : LABEL * TREE +> seqof TREE
getTree : LABEL * TREE +> TREE
isEmpty : TREE +> bool
prune : PARSED -> PARSED
pruneTree : TREE -> TREE
format : PARSED -> seqofchar
formatTree : TREE * nat -> seqofchar
definitions
values
TABSIZE = 2;
-- Recognise a lower case alphanumeric character.
lowerAlphanum =
label("lowerAlphanum", either([lowerAlphabet, digit]));
-- Recognise an upper case alphanumeric character.
upperAlphanum =
label("upperAlphanum", either([upperAlphabet, digit]));
-- Recognise an alphanumeric character.
alphanum =
label("alphabet", either([alphabet, digit]));
-- Recognise an octal digit.
octal =
label( "octal",
either([takeChar("01234567"(index)) | index inset {1, ..., 8}]));
-- Recognise a hexadecimal digit.
hex =
label( "hex",
either([takeChar("0123456789ABCDEFabcdef"(index)) | index inset {1, ..., 22}]));
functions
-- Recognise a numeric value optionally specifying the minimum and maximum digits.
takeNumeric: [nat1] * [nat1] -> PARSER
takeNumeric(m, n) == let m1 = if m = nilthen 1 else m in concat(iterate(digit, m1, n)) pre m <> niland n <> nil => m <= n;
-- Recognise a string optionally specifying a minimum and maximum length. -- While the parser argument can be arbitrary, the intent is it recognises a single character.
takeBoundedString: seq1ofchar * PARSER * nat * nat -> PARSER
takeBoundedString(lbl, parser, min, max) == label(lbl, concat(iterate(parser, min, max))) pre min <= max;
-- Recognise characters in the source till a specified token is reached. -- If an optional parser is specified, use it to parse the recognised string.
takeUpto: seq1ofchar * [PARSER] +> PARSER
takeUpto(word, parser) == lambda source : SOURCE & casesSeq`indexOfSeqOpt[char](word, source): nil -> mk_PARSED(mk_ERROR(word ^ " not found"), source),
index -> let recognised = [ source(i) | i inset {1,...,index-1} ],
remainder = [ source(i) | i inset {index,...,len source} ] in if parser = nil then mk_PARSED(mk_TREE(nil, recognised), remainder) elselet mk_PARSED(tree, rest) = parser(recognised) in cases tree:
mk_ERROR(-) -> mk_PARSED(mk_ERROR("unrecognised"), source),
mk_TREE(-,-) -> ifChar`isWhiteSpaces(rest) then mk_PARSED(tree, remainder) else mk_PARSED(mk_ERROR("excess"), rest^remainder) end end;
-- Recognise characters in the source till one of a specified sequence of tokens is reached. -- If no such token is found, and an optional terminator is provided, recognise characters up to the terminator. -- If a sequence is recognised and an optional parser is specified, use it to parse the recognised string.
takeUptoOneOf: seqofseq1ofchar * [seq1ofchar] * [PARSER] +> PARSER
takeUptoOneOf(tokens, term, parser) == lambda source : SOURCE & cases tokens:
[] -> if term = nil then mk_PARSED(mk_ERROR("not found"), source) else takeUpto(term, parser)(source),
[tok]^rest -> let mk_PARSED(tree, source1) = takeUpto(tok, parser)(source) in cases tree:
mk_ERROR(-) -> takeUptoOneOf(rest, term, parser)(source),
mk_TREE(-,-) -> mk_PARSED(tree, source1) end end;
/* Convenience functions for extracting items from a parse tree.
*/
-- Get the character content.
getContent: LABEL * TREE +> seqofchar
getContent(lbl, mk_TREE(tlabel,content)) == content pre (lbl = nilor lbl = tlabel) and is_(content, seqofchar);
-- Get the character content as a natural number.
getContentNat: LABEL * TREE +> nat
getContentNat(lbl, tree) == Numeric`decodeNat(getContent(lbl,tree)) pre pre_getContent(lbl, tree) andChar`isDigits(tree.contents);
-- Get the sequence of sub trees.
getTrees: LABEL * TREE +> seqof TREE
getTrees(lbl, mk_TREE(tlabel,content)) == content pre (lbl = nilor lbl = tlabel) and is_(content, seqof TREE);
-- Get the only sub tree.
getTree: LABEL * TREE +> TREE
getTree(lbl, tree) == tree.contents(1) pre pre_getTrees(lbl, tree) andlen tree.contents = 1;
-- Is a tree empty (has not label or content)?
isEmpty : TREE +> bool
isEmpty(mk_TREE(tlabel,content)) == tlabel = niland content = [];
/* Convenience functions for flattening out parse trees: - remove empty sub trees; - lift sub components up where a nil label is encountered.
*/
-- Filter out empty subtrees from a parse result.
prune : PARSED -> PARSED
prune(mk_PARSED(parsed, remaining)) == if
is_ERROR(parsed) then
mk_PARSED(parsed, remaining) else
mk_PARSED(pruneTree(liftTree(parsed)), remaining);
-- Filter out empty subtrees from a tree.
pruneTree : TREE -> TREE
pruneTree(mk_TREE(lbl, contents)) == if
is_(contents, seqofchar) then
mk_TREE(lbl, contents) else
mk_TREE(lbl, pruneTrees(contents));
-- Prune a sequence of trees.
pruneTrees : seqof TREE -> seqof TREE
pruneTrees(trees) == [ pruneTree(trees(i)) | i insetinds trees & not isEmpty(pruneTree(trees(i))) ];
-- Lift subtrees with a nil label up a level.
liftTree : TREE -> TREE
liftTree(mk_TREE(lbl,contents)) == if is_(contents, seqofchar) then mk_TREE(lbl,contents) elselet lifted = liftTrees(contents) inif lbl = nilandlen lifted = 1 then lifted(1) else mk_TREE(lbl,lifted);
-- Lift a sequence of subtrees.
liftTrees : seqof TREE -> seqof TREE
liftTrees(trees) == conc [ liftTreeSeq(trees(i)) | i insetinds trees ];
-- Auxiliary function for lifting subtrees. -- Produces a sequence of trees in case the top level tree has a nil label.
liftTreeSeq : TREE -> seqof TREE
liftTreeSeq(mk_TREE(lbl,contents)) == if is_(contents, seqofchar) then [mk_TREE(lbl,contents)] elselet lifted = liftTrees(contents) inif lbl = nil then lifted else [mk_TREE(lbl,lifted)];
/* Convenience functions for creating a pretty printed text version of a parse tree.
*/
-- Format a parse result as text.
format : PARSED -> seqofchar
format(mk_PARSED(parsed, remaining)) ==
formatTreeOrError(parsed) ^ "Remaining: [" ^ remaining ^ "]";
-- Format a parse tree or parse error as text.
formatTreeOrError : TREE| ERROR -> seqofchar
formatTreeOrError(treeOrError) == if
is_ERROR(treeOrError) then "Error: " ^ treeOrError.message ^ "\n" else "Parse Tree:\n" ^ formatTree(treeOrError, TABSIZE);
-- Format a parse tree as text.
formatTree : TREE * nat -> seqofchar
formatTree(mk_TREE(lbl, contents), n) == let lblstr = if lbl = nilthen""else lbl in indent(n) ^ "'" ^ lblstr ^ "'\n" ^ formatContent(contents, n + TABSIZE);
-- Format as text the parse tree content (text or sequence of subtrees).
formatContent : (seqof TREE | seqofchar) * nat -> seqofchar
formatContent(tt, n) == if
is_(tt, seqofchar) then
indent(n) ^ "[" ^ tt ^ "]\n" else conc [formatTree(tt(i), n) | i insetinds tt];
-- Create a sequence of spaces.
indent : nat +> seqofchar
indent(n) == [' ' | i inset {1, ..., n}];
end VCParserSupp
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.