Example #1
0
        public void setup()
        {
            scanner = new ScanStrings("hello, world");

            matching_parser = Substitute.For<IMatchingParser>();
            complex_parser = Substitute.For<IParser>();

            matching_parser.TryMatch(scanner).ReturnsForAnyArgs(new ParserMatch(null, scanner, 0, 0));
            complex_parser.Parse(scanner).ReturnsForAnyArgs(new ParserMatch(null, scanner, 0, 0));

            subject = new Recursion();
        }
Example #2
0
        /// <summary>
        /// Create a self-recursive parser structure
        /// </summary>
        public static BNF Recursive(Func<BNF, BNF> ParserTreeFunction)
        {
            // The way this works involves a lot of bad-practice and hidden typecasts.
            var hold = new Recursion();

            var src = ParserTreeFunction(hold);
            hold.Source = src.Result();

            return hold;
        }
Example #3
0
 /// <summary>
 /// Create a simple Recursion parser.
 /// Input to the function is a holding parser, output is the parser to hold.
 /// (i.e. they end up being the same parser)
 /// </summary>
 public static IParser Over(Func<IParser, IParser> func)
 {
     var hold = new Recursion();
     hold.Source = func(hold);
     return hold;
 }
Example #4
0
        //  http://pascal-central.com/images/pascalposter.jpg
        IParser Pascal()
        {
            // The BNF syntax isn't really up to this -- the precedence rules are all wrong!
            // makes for a really fragile parser.

            var _empty_ = new BNF(new EmptyMatch());

            var _type = new Recursion();
            var _fieldList = new Recursion();
            var _block = new Recursion();
            var _statement = new Recursion();
            var _variable = new Recursion();
            var _expression = new Recursion();
            var _factor = new Recursion();

            BNF identifier = "#[_a-zA-Z][_a-zA-Z0-9]*";
            BNF pascalString = "#'([^']|'')*'"; // Pascal uses two single-quotes to mark a single quote.
            BNF plusOrMinus = "#[\\-+]";

            BNF set = "set";
            BNF of = "of";
            BNF array = "array";
            BNF record = "record";
            BNF not = "not";
            BNF and = "and";
            BNF div = "div";
            BNF mod = "mod";
            BNF end = "end";
            BNF to = "to";
            BNF downto = "downto";
            BNF begin = "begin";
            BNF file = "file";
            BNF exit = "exit";
            BNF VAR = "var";
            BNF Else = "else";

            BNF identifierList = identifier % ',';
            BNF parameters = '(' > identifierList > ')';
            BNF unsignedInteger = "#\\d+";
            BNF label = "label" > ( unsignedInteger % ',' ) > ';';

            BNF unsignedNumber = unsignedInteger > !("." > unsignedInteger) > !('e' > (!plusOrMinus) > unsignedInteger);
            BNF unsignedConstant = pascalString | "nil" | unsignedNumber | identifier;
            BNF constant = (unsignedConstant) | ( plusOrMinus > (identifier | unsignedNumber));
            BNF constantBlock = "const" > +(identifier > '=' > constant > ';');

            BNF arrayRange = '[' > !(( _expression > !((BNF)".." > _expression)) % ',' ) > ']';
            BNF factor =
                  (unsignedConstant)
                | (_variable)
                | (identifier > !('(' > ((BNF)_expression % ',') > ')'))
                | ((BNF)'(' > _expression > ')')
                | (not > _factor)
                | arrayRange;
            BNF term = factor % (and | div | mod | "/" | "*");

            BNF inequality = ((BNF)"<" | "<=" | "=" | "<>" | ">=" | ">" | "in");
            BNF simpleExpression = !(plusOrMinus) > ((term % "or") % plusOrMinus);
            BNF expression = simpleExpression > !(inequality > simpleExpression);

            BNF innerVariable = ('[' > (expression % ',') > ']') | ('.' > identifier);
            BNF variable = identifier > (innerVariable | ('^' > innerVariable));

            BNF ifBlock = "if" > expression > "then" > _statement > !(Else > _statement);
            BNF forBlock = "for" > identifier > ":=" > expression > (to | downto) > expression > "do" > _statement;
            BNF caseBlock = "case" > expression > "of" > (( (constant % ',') > ':' > _statement ) % ';') > end;
            BNF statement =
                 !(unsignedInteger > ':')
                | _empty_
                | ("begin" > ((BNF)_statement % ';') > "end")
                | (identifier > !( '(' > (expression % ',') > ')'))
                | (variable > ":=" > expression)
                | ifBlock
                | ("repeat" > ((BNF)_statement % ';') > "until" > expression)
                | ("while" > expression > "do" > _statement)
                | forBlock
                | caseBlock
                | ("with" > (variable % ',') > "do" > _statement)
                | ("goto" > unsignedInteger)
                | (exit > '(' > (identifier | "program") > ')');

            BNF statementBlock = begin > (statement % ';') > end;

            BNF constantFieldList = (constant % ',') > ':' > '(' > _fieldList > ')';
            BNF caseStatement = "case" > !(identifier > ':') > identifier > of > (constantFieldList < ';');
            BNF fieldList = caseStatement | ( -(identifierList > ':' > _type) % ';');

            BNF simpleType = identifier | parameters | (constant > ".." > constant);
            BNF complexType =
                  (set > of > simpleType)
                | (array > '[' > (simpleType % ',') > ']' > of > _type)
                | (record > fieldList > end)
                | (file > !(of > _type));
            BNF type = simpleType | ('^'>identifier) | (!((BNF)"packed") > complexType);

            BNF singleParameter = (!VAR) > identifierList > ':' > identifier;
            BNF parameterList = !('(' > (singleParameter % ';') > ')');
            BNF procedure = "procedure" > identifier > parameterList > ';' > _block > ';';
            BNF function = "function" > identifier > parameterList > ':' > identifier > ';'> _block > ';';

            BNF varBlock = "var" > +(identifierList > ':' > _type > ';');

            BNF typeBlock = "type" > +(identifier > '=' > type > ';');
            BNF block = !(label | constantBlock | typeBlock | varBlock | procedure | function) > statementBlock;
            BNF program = "program" > identifier > (!parameters) > ';' > block > '.';

            _type.Source = type.Result();
            _fieldList.Source = fieldList.Result();
            _block.Source = block.Result();
            _statement.Source = statement.Result();
            _variable.Source = variable.Result();
            _expression.Source = expression.Result();
            _factor.Source = expression.Result();

            return program.Result();
        }