statement = b:block { b; } | e:expression SEMI { e; } expression = p:primary ( DOT i:id ASSIGN e:expression # { $$ = newSetProp(p, i, e) } | LBRAK i:expression RBRAK ASSIGN e:expression { SetArray.new(object: p, index: i, value: e); } ) | i:id ASSIGN e:expression { SetVar.new(name: i, value: e); } | pf:postfix { pf; } postfix = p:primary ( DOT i:id a:args !ASSIGN !LBRACE { p = Invoke.new(self: p, method: i, arguments: a); } | DOT i:id !ASSIGN { p = GetProp.new(object: p, key: i); } | a:args !ASSIGN !LBRACE { p = Call.new(function: p, arguments: a); } ) * { p; } args = LPAREN a:mklist ( ( k:id COLON e:expression { a[k] = e; } | e:expression { a.push(e); } ) ( COMMA ( k:id COLON e:expression { a[k] = e; } | e:expression { a.push(e); } ) ) * ) ? RPAREN { a; } mklist = { Object.new(); } primary = nil | number | var | subExpr subExpr = LPAREN e:expression RPAREN { e; } block = LBRACE b:mklist ( e:statement { b.push(e); } ) * RBRACE { Block.new(body: b); } nil = NIL { nil; } number = "-" n:unsign { Unyop.new(operation: __opNeg).push(n) } | "+" n:number { n } | n:unsign { n } unsign = < DIGIT+ > - { yytext.asInteger(10); } var = i:id { GetVar.new(name: i); } id = < LETTER ALNUM* > - { intern(yytext); } DIGIT = [0-9] LETTER = [A-Za-z_] ALNUM = LETTER | DIGIT NIL = "nil" !ALNUM - SEMI = ";" - COMMA = "," - LPAREN = "(" - RPAREN = ")" - LBRAK = "[" - RBRAK = "]" - LBRACE = "{" - RBRACE = "}" - COLON = ":" ![:] - ASSIGN = "=" ![=] - DOT = "." ![.] - - = ( space | comment )* space = ' ' | '\t' | end-of-line comment = '//' ( !end-of-line . )* end-of-line end-of-line = '\r\n' | '\n' | '\r' end-of-file = !.