What is the grammar of expressions that are permitted within AngularDart mustaches {{...}} and other directives?
Here is an EBNF grammar for AngularDart expressions, in the same notation used in the Dart Programming Language Specification. These expressions can appear as arguments to Angular directives. While the grammar allows, e.g., a semicolon-separated list of expressions, assignments and conditionals, these will not be accepted by all directives---e.g., ng-click supports multiple expressions possibly with assignments, whereas the mustache directive {{...}} expects a single expression.
expressions: expression (';' expressions)?
expression:
literal
| id args? # variable or function
| expression '.' id args? # member
| expression '|' id filterArg* # filter
| expression '[' expression ']'
| preOp expression
| expression binOp expression
| expression '?' expression ':' expression
| expression '=' expression # assignment
args: '(' expressionList? ')'
filterArg: ':' expression
expressionList: expression (',' expression)?
literal:
'null'
| stringLiteral
| numberLiteral
| boolLiteral
| '[' expressionList? ']'
| '{' (keyValuePair (',' keyValuePair)? )? '}'
keyValuePair:
expression ':' expression
The preOp and binOp are mainly those supported by Dart (though I will have to crosscheck that). There is a more nicely formatted version of the above here (I could not get the MD to cooperate).
Related
So in all cases of AST examples, there are productions of the following kind:
expr -> expr "+" expr;
expr -> expr "-" expr;
And in this case it's easy to create a new node like this:
expr: expr "+" expr {newNode("+",$1,$3);}
;
Now my grammar has the following implementation:
assignment:IDENTIFIER '=' expression ';'
;
expression:term expression_1
;
expression_1: '+' term expression_1 |
'-' term expression_1 |
;
term: factor term_1
;
term_1: '*' factor term_1 |
'/' factor term_1 |
;
factor: IDENTIFIER |
'(' expression ')' |
NUM | FNUM | STRING
;
Here, while making a new node, how do I take the first operand(which is in a previous production), and feed that into a newNode function which will have the operator and the second operand(both of these are together in a different production)?
I am reading a compiler tutorial here www.buildyourownlisp.com. It uses a parser combinator called mpc. What I have at the moment will parse polish notation, but I'm trying to work out how to use standard notation with it. I just can't seem to how to do it.
The rules of the parser are as follows:
. Any character is required.
a The character a is required.
[abcdef] Any character in the set abcdef is required.
[a-f] Any character in the range a to f is required.
a? The character a is optional.
a* Zero or more of the character a are required.
a+ One or more of the character a are required.
^ The start of input is required.
$ The end of input is required.
"ab" The string ab is required.
'a' The character a is required.
'a' 'b' First 'a' is required, then 'b' is required.
'a' | 'b' Either 'a' is required, or 'b' is required.
'a'* Zero or more 'a' are required.
'a'+ One or more 'a' are required.
<abba> The rule called abba is required.
The polish notation is written like this:
" \
number: /-?[0-9]+/'.'?/[0-9]+/ ; \
operator: '+' | '-' | '*' | '/' | '%' | \"add\" | \"sub\" | \"mul\" | \"div\" ; \
expr: <number> | '(' <operator> <expr>+ ')' ; \
dlispy: /^/ <operator> <expr>+ /$/ ;",
I've managed to make it accept decimal numbers by adding '.'?/[0-9]+/, but i can't work out how to restructure it to accept standard notation eg 2*(3+2) instead of *2 (+ 3 2). I know that I'll have to rewrite the expr and the dlispy rules, but I'm new to regex and BNF. Hope you can help, thanks
Written as yacc rules, that would be:
expr : '(' expr ')
| expr operator expr
| number
;
How to enable a start condition at the beginning of a rule and disable it at the end ? I have to ignore whitespace with some bison rules only.
How to ignore whitespace inside nested brackets.
define_directive:
DEFINE '(' class_name ')'{ ... }
;
I'm trying to write a parser for this sample code with some more rules.
#/*
* #Template Family
* #Description sample script template for Mate Programming language
* (multi-line comment)
*/
#namespace(sample)
#require(String fatherName)
#require(String motherName)
#require(Array childrenNames)
#define(Family : Template) #// end of header anything can go in body section below (comment)
Family Description
==================
Father's Name: #(fatherName)
Mother's Name: #(motherName)
Number of child: #(childrenNamesCount,0) #// valuation operator is null safe (comment)
List of children's names
------------------------
#foreach(childName:childrenNames)
> #(childName)
#empty
> there is no child name to display.
#end
##(varName) #// this should not be interpreted because escaped with # (comment)
Lexer and parser partially implemented. My problem is how to deal with whitespace inside statement keywords like #foreach, #require.
Whitespaces should be ignored for these.
desired sample output
Family Description
==================
Father's Name: Mira
Mother's Name: James
Number of child: 0
List of children's names
------------------------
> there is no child name to display.
##(varName)
bison file content
command:
fileword
| valuation
| alternative
| loop
| command_directive
;
fileword:
tokenword { scriptlangy_echo(yytext,"fileword.tokenword"); }
| MAGICESC { scriptlangy_echo("#","fileword.MAGICESC"); }
;
tokenword:
IDENTIFIER | NUMBER | STRING_LITERAL | WHITESPACE
| INC_OP | DEC_OP | AND_OP | OR_OP | LE_OP | GE_OP | EQ_OP | NE_OP | L_OP | G_OP
| ';' | ',' | ':' | '=' | ']' | '.' | '&' | '[' | '!' | '~' | '-' | '+' | '*' | '/' | '%' | '^' | '|' | ')' | '}' | '?' | '{' | '('
;
valuation:
'#' '(' expression ')' {
fprintf(yyout, "<val>");
}
| '#' '(' expression ',' default_value ')' {
fprintf(yyout, "<val>");
}
;
loop:
for_loop
| foreach_loop
| while_loop
;
while_loop:
WHILE '(' expression ')' end_block
| WHILE '(' expression ')' commands end_block
;
for_loop:
FOR '(' expression_statement expression_statement expression')' end_block
| FOR '(' expression_statement expression_statement expression')' commands end_block
;
foreach_loop:
foreach_block end_block
| foreach_block empty_block end_block
;
foreach_block:
FOREACH '(' IDENTIFIER ')'
| FOREACH '(' IDENTIFIER ':' expression')' commands
;
The key part of your question seems to be this:
I have to ignore whitespace with some bison rules only. How to ignore
whitespace inside nested brackets.
As I remarked in comments, your implementation idea of somehow doing this by having your parser rules manipulate scanner start conditions is pretty much a non-starter. Forget about that.
Since evidently your scanner does not, in general, ignore whitespace, it must emit tokens that represent whitespace, or perhaps tokens that represent something else plus whitespace (ugly). If it emits whitespace tokens then the thing to do is simply to account for them in your grammar rules. This is completely possible. In fact, you can build a parser for any context-free language on top of a scanner that just returns every character as its own token. The scanner / parser dichotomy is a functional and conceptual convenience, not a necessity.
For example, then, suppose we want to be able to parse numeric array literals, formed as a nonempty, comma-delimited list of decimal numbers enclosed in curly braces, with optional whitespace around commas and inside the braces. Suppose further that we have these terminal symbols to work with:
OPEN // open brace
CLOSE // close brace
NUM // maximal sequence of one or more decimal digits
COMMA // a comma
WS // a maximal run of whitespace
We might then write these rules:
array: array_start array_elements CLOSE;
array_start: OPEN
| OPEN WS
;
array_elements: array_element
| array_elements array_separator array_element
;
array_element: NUM
| NUM WS
;
array_separator: COMMA
| COMMA WS
;
There are, of course, many other ways to set up the details, but, generally speaking, this is how you handle whitespace with parser rules: not by ignoring it, but by accepting it.
I'm trying to use MPC to define a grammar for a language called Wittgen (https://esolangs.org/wiki/Wittgen)
I defined the following grammar:
mpc_parser_t* Variable = mpc_new("variable");
mpc_parser_t* Assign_Operator = mpc_new("assign");
mpc_parser_t* Remind_Operator = mpc_new("remind");
mpc_parser_t* Expr = mpc_new("expr");
mpc_parser_t* Envinronment = mpc_new("envinronment");
mpca_lang(MPCA_LANG_DEFAULT,
" variable : /[a-zA-Z0-9]+/ ;"
" assign : '=' ;"
" remind : '#' ;"
" expr : <variable> | <remind> <variable> '}' | <variable> <assign> <expr>+ '}' ;"
" envinronment : /^/<expr>+/$/ ;",
Variable, Assign_Operator, Remind_Operator, Expr, Envinronment);
when I try to input a variable or a remind operator (like "foo247" or "#foo247}") it parses it correctly,
but when I try to parse an assignment ("foo247=foo}"), it returns me just
WITTGEN> foo357=foo}
<stdin>:1:7: error: expected one of 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ', one or more of one of 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ', '#' or end of input at '='
I can't find the error, I'm sure something is wrong defined in the grammar, but I can't find any clue in the official documentation or in the examples
I'm not an expert on mpc and I may be wrong, in fact I'm having my own problems with it at the moment, but I don't think it supports left recursion. So since expr is contained within the expr rule it causes an error.
Edit* I was able to solve my issue by moving part of my expansion over. So the equivalent for yours would be to move variable all the way to the right so it tries to parse using the other two expansions first. I can't say for sure if that's causing your issue, but it could be worth a shot.
I had my question answered from the author of mpc here:
I simply changed the part of rule definition from
" expr : <variable> | <remind> <variable> '}' | <variable> <assign> <expr>+ '}' ;"
to:
" expr : <remind> <variable> '}' | <variable> <assign> <expr>+ '}' | <variable>;"
it was happening because there's no backtracking in mpc, so the evaluation rule order is important
I have the following rule in my bison file :
affectation: VAR '=' expr ';'
| VAR PLUSEQ expr ';'
| VAR MINUSEQ expr ';'
;
I would like the parser to display the variable name and its content every time an affectation is done. For that, I use the action {printf("%s:%s\n",$1, $3);}. However, as there are 3 forms of affectation, is there a way to apply this action to all the components without writting :
affectation: VAR '=' expr ';'
{printf("%s:%s\n",$1, $3);}
| VAR PLUSEQ expr ';'
{printf("%s:%s\n",$1, $3);}
| VAR MINUSEQ expr ';'
{printf("%s:%s\n",$1, $3);}
;
Basically, the answer is no. In most use cases, the three productions would have different semantics, so it would be normal for their to be three different actions, although they might share code. (As always, refactoring the shared code can reduce the need for duplication.)
If the three rules were really semantically identical, you could collect the different operators into a prefix rule:
aff_pfx: VAR '=' | VAR PLUSEQ | VAR MINUSEQ
affectation: aff_pfx expr ';' { handle($1, $2); }
That relies on the default action copying $$ = $1 in all the productions for aff_pfx, so it is not fully general. Also, it completely erases any distinction between the three syntaxes, which seems unlikely to be correct.
If you are just trying to produce a trace of the parse,take a look at bison's built-in debugging features.