How to retrieve all matched rules from PackCC?

68 views Asked by At

I'm working on a small parser with PackCC and am having a bit of trouble knowing what to do when a rule is matched n times, where n is unknown at compile time. Essentially, I use C actions to create an abstract syntax tree for a given rule, then add its children if any exist. This works when the number of children is determined at compile time.

Consider the following rule:

application <- '(' e:expr* ')' { $$ = ??? }
             / '{' e:expr* '}' {}
             / '[' e:expr* ']' {}

This should match function applications, e.g., (+ 5 4 3 2). The issue is that I don't know how to retrieve the ith expression. Using the $n prefixes is, again, limited to knowing how many matches there are at compile time. What's the solution?

1

There are 1 answers

0
rici On

I'm pretty sure that you can't. If you use e:expr* in a rule, the rule will match any number of consecutive exprs and set e to the value of the last one. You can capture the entire match with $0 (or by using angle brackets and fighting with PackCC's odd concept of numbering captures), but that just gives you a string, which pretty undoes the entire parse (except for knowing that it was successful).

As far as I can see, the only real utility of * and + repetition operators in PackCC is building token matchers. The EBNF operators are fine if you just want the entire matching character string, and not of much use in any other case.

Since PackCC does not provide a built-in mechanism for creating lists of things, you have to do that yourself, and that basically means that you will end up with something like:

expr     -> '(' _ el:exprlist ')'  { $$ = el; }
          / a:atom                 { $$ = a; } 
exprlist -> e:expr _ el:exprlist   { $$ = cons(e, el); }
          /                        { $$ = &nullobj; }
_        -> [ \t\n]*