Btw, why did you choose the name Owl?
Btw, why did you choose the name Owl?
The restriction is that any recursion in the grammar has to be inside explicit begin and end tokens. For example, you can't write a rule like
stmt = 'if' expr 'then' stmt* | expr
because `stmt` refers to itself directly, but stmt = [ 'if' expr 'then' stmt* 'end' ] | expr
is OK -- the [ and ] symbols indicate explicit recursion using 'if' and 'end' as the begin and end tokens.[1]> Btw, why did you choose the name Owl?
I wanted a bird name, and Owl was short and easy to type!
. . .
[1] Though in this case, the language is still visibly pushdown, since you can expand it manually to:
stmt = (('if' expr 'then')+ expr*)+ | expr
This is because the grammar only has right recursion. Middle recursion (like you get if you add an 'else' clause) can't be expanded like this, so explicit recursion is necessary to parse languages which use it.To automate this expansion process (and re-association into a sensible parse tree), Owl also has syntax for operators with precedence. Here's an example: https://ianh.github.io/owl/try/#expr
yes: S -> <a> S </a> | e
no: S -> <a></a> S | e
I've seen these called "tree grammars". Perhaps it's identical with "visibly pushdown grammars"? I skimmed the wiki link (from your readme.md), but it requires further study. I think it would be great if your readme.md included a brief idea, along the lines of what your comment here.I'm interested that you have this too, but it seems to have the same problems I found: https://news.ycombinator.com/item?id=17650770
It would be very exciting if you have found a way around this!
expr = number (('*' | '+') number)*
You can replace number by (number | [ '(' expr ')' ]) to add support for parentheses as well.My solution was to add special syntax which makes rules like this automatically:
expr = number : num
.operators infix left '*' : times
.operators infix left '+' : plus
While the parse tree is built, the operators and operands are rearranged into the expected parse tree using https://en.wikipedia.org/wiki/Shunting-yard_algorithm. Here's an interactive example with some more operators: https://ianh.github.io/owl/try/#exprNice, a language can be recognized, even if a different parse tree.
I vaguely recall the shunting yard algorithm... am I right in characterising your solution as a second level of parsing? It's not "pure", but from a practical point of view, it's no worse than back-references in PCRE. The practical issue is just of ui usability.
print 2*3 + 4