October 19, 2006
Kristian wrote:
>
> Well, couldn't one use arrays to define actions? For example:
>
>     r = make_parser("real_number[0] (',' real_number[1])*");
>
>     array[] = {&firstAction,   //[0]
>                &generalAction  //[1]
>                };
>     r.attach(array);
>
>
> You could also give string ids for actions:
>
>     r = make_parser("real_number[myaction] (',' real_number[real])*");
>
>     array[] = {"myaction", &firstAction,
>                "real", &generalAction
>                };
>     r.attach(array);

I actually did something similar to this when creating a generic PEG parser. (http://en.wikipedia.org/wiki/Parsing_Expression_Grammar)
I opted to use the square brackets to denote semantic groups. Each semantic group has an associated delegate, which performs an action
on the nodes in the group and returns a replacement node for the parse tree.

The following is part of my calculator test that parses and evaluates an expression.

 auto c = new RuleSet();

 // Number.create creates a number object from a string.
 c.addRegex("Number", 	
    "\s*(([\+\-])*([0-9]+)(\.([0-9]*))?(([eE])([\+\-]*)([0-9]+))?)\s*",
    &Number.create);
 c.addRegex("Identifier", r"\s*([a-zA-Z_]\w*)\s*");


 c.addRule("Statement", "Assignment / Expression");
 c.addRule("Assignment", r"[Identifier '=' Expression]",
      // assign value to variable
      delegate Node(Node[] n) {
	 // All this casting feels a bit clunky!
         char[] s = (cast(RegexNode)n[0]).match[1];
         vars[s] = (cast(Number)n[2]).eval();
         return new Number(vars[s]);
      });

 c.addRule("Expression", "[Term (('+' / '-') Term)*]",
      // perform addition and subtraction
      delegate Node(Node[] n) {
	   ...
      });

 c.addRule("Term", "[Factor (('*' / '/') Factor)*]",
      // perform multiplication and division
      delegate Node(Node[] n) {
	 ...
      });


 c.addRule("Factor", "Number / [Identifier] / ['(' Expression ')']",
      // Get value of identifier
      delegate Node(Node[] n) {
       ...
      },
      // 2 is a shortcut for returning 2nd node in semantic group.
      // The expression itself in this case.
      2);

 auto p = new Parser(c);


Its all runtime as my templating abilities arent up to the task.  A compile time version will be fun though!
1 2 3
Next ›   Last »