ometa LivelyJSParserDraft <: Parser { whereAreYou -> { var charsBefore = 120, charsAfter = 120, src = this._originalInput.arr, startIndex = Math.max(0, this.pos() - charsBefore), stopIndex = Math.min(src.length, this.pos() + charsAfter), msg = src.substring(startIndex, this.pos()) + '<--I am here-->' + src.substring(this.pos(), stopIndex); msg += '\nRules: ' + this._ruleStack; msg += '\nStack: ' + this.stack; alert(msg); true }, fromTo :x :y = seq(x) (~seq(y) char)* seq(y), fromToWithout :x :y = seq(x) (~seq(y) char)*, space = ^space | fromToWithout('//', '\n') | fromTo('//', #end) | fromTo('/*', '*/'), nameFirst = letter | '$' | '_', nameRest = nameFirst | digit, iName = firstAndRest(#nameFirst, #nameRest):r -> r.join(''), isKeyword :x = ?LivelyJSParser._isKeyword(x), name = pos:p1 iName:n ~isKeyword(n) pos:p2 -> [#name, [p1, p2], n], keyword = pos:p1 iName:k isKeyword(k) pos:p2 -> [k, [p1, p2], k], hexDigit = char:x {this.hexDigits.indexOf(x.toLowerCase())}:v ?(v >= 0) -> v, hexLit = hexLit:n hexDigit:d -> (n * 16 + d) | hexDigit, number = pos:p1 ( ``0x'' hexLit:n pos:p2 -> [#number, [p1, p2], n] | '.' digit+:fs pos:p2 -> [#number, [p1, p2], parseFloat('.' + fs.join(''))] | digit+:ws ('.' digit+ | empty -> []):fs ('e' ('+' | '-' | empty -> ''):sig digit+ | empty -> []):exp pos:p2 -> [#number, [p1, p2], parseFloat(ws.join('') + '.' + fs.join('') + 'e' + sig + exp.join(''))]), escapeChar = '\\' char:c -> unescape('\\' + c), str = pos:p1 ( seq('"""') (escapeChar | ~seq('"""') char)*:cs seq('"""') pos:p2 -> [#string, [p1, p2], cs.join('')] | '\'' (escapeChar | ~'\'' char)*:cs '\'' pos:p2 -> [#string, [p1, p2], cs.join('')] | '"' (escapeChar | ~'"' char)*:cs '"' pos:p2 -> [#string, [p1, p2], cs.join('')] | ('#' | '`') iName:n pos:p2 -> [#string, [p1, p2], n]), special = pos:p1 ( '(' | ')' | '{' | '}' | '[' | ']' | ',' | ';' | '?' | ':' | ``!=='' | ``!='' | ``==='' | ``=='' | ``='' | ``>>>'' | ``>>='' | ``>='' | ``>>'' | '>' | ``<<='' | ``<='' | ``<<'' | '<' | ``++'' | ``+='' | '+' | ``--'' | ``-='' | '-' | ``*='' | '*' | '~' | ``/='' | '/' | ``%='' | '%' | ``&&='' | ``&&'' | ``||='' | ``||'' | '.' | '!' | '&' | '|' | '^'):s pos:p2 -> [s, [p1, p2], s], tok = spaces (name | keyword | number | str | special), toks = token*:ts spaces end -> ts, token :tt = tok:t ?(t[0] == tt) -> { t[2] }, // we return t[2] not t[1] because t[1] is the pos spacesNoNl = (~'\n' space)*, expr = pos:p1 exprPart:f "," expr:s pos:p2 -> [#begin, [p1, p2], f, s] | exprPart, exprPart = pos:p1 ternaryExpr:e ( "?" exprPart:t ":" exprPart:f pos:p2 -> [#condExpr, [p1, p2], e, t, f] | "=" exprPart:rhs pos:p2 -> [#set, [p1, p2], e, rhs] | "+=" exprPart:rhs pos:p2 -> [#mset, [p1, p2], e, "+", rhs] | "-=" exprPart:rhs pos:p2 -> [#mset, [p1, p2], e, "-", rhs] | "*=" exprPart:rhs pos:p2 -> [#mset, [p1, p2], e, "*", rhs] | "/=" exprPart:rhs pos:p2 -> [#mset, [p1, p2], e, "/", rhs] | "%=" exprPart:rhs pos:p2 -> [#mset, [p1, p2], e, "%", rhs] | "&=" exprPart:rhs pos:p2 -> [#mset, [p1, p2], e, "&", rhs] | "&&=" exprPart:rhs pos:p2 -> [#mset, [p1, p2], e, "&&", rhs] | "|=" exprPart:rhs pos:p2 -> [#mset, [p1, p2], e, "|", rhs] | "||=" exprPart:rhs pos:p2 -> [#mset, [p1, p2], e, "||", rhs] | "^=" exprPart:rhs pos:p2 -> [#mset, [p1, p2], e, "^", rhs] | ">>=" exprPart:rhs pos:p2 -> [#mset, [p1, p2], e, ">>", rhs] | "<<=" exprPart:rhs pos:p2 -> [#mset, [p1, p2], e, "<<", rhs] | ">>>=" exprPart:rhs pos:p2 -> [#mset, [p1, p2], e, ">>>", rhs] | empty -> e ), ternaryExpr = pos:p1 orExpr:e ( "?" orExpr:t ":" orExpr:f pos:p2 -> [#condExpr, [p1, p2], e, t, f] | empty -> e ), orExpr = pos:p1 orExpr:x "||" andExpr:y pos:p2 -> [#binop, [p1, p2], "||", x, y] | andExpr, andExpr = pos:p1 andExpr:x "&&" bitOrExpr:y pos:p2 -> [#binop, [p1, p2], "&&", x, y] | bitOrExpr, bitOrExpr = pos:p1 bitXorExpr:x "|" bitOrExpr:y pos:p2 -> [#binop, [p1, p2], "|", x, y] | bitXorExpr, bitXorExpr = pos:p1 bitAndExpr:x "^" bitXorExpr:y pos:p2 -> [#binop, [p1, p2], "^", x, y] | bitAndExpr, bitAndExpr = pos:p1 eqExpr:x "&" bitAndExpr:y pos:p2 -> [#binop, [p1, p2], "&", x, y] | eqExpr, eqExpr = pos:p1 eqExpr:x ("==" | "!=" | "===" | "!=="):op relExpr:y pos:p2 -> [#binop, [p1, p2], op, x, y] | relExpr, relExpr = pos:p1 relExpr:x (">" | ">=" | "<" | "<=" | "instanceof" | "in"):op shiftExpr:y pos:p2 -> [#binop, [p1, p2], op, x, y] | shiftExpr, shiftExpr = pos:p1 shiftExpr:x (">>" | "<<" | ">>>"):op addExpr:y pos:p2 -> [#binop, [p1, p2], op, x, y] | addExpr, addExpr = pos:p1 addExpr:x ("+" | "-"):op mulExpr:y pos:p2 -> [#binop, [p1, p2], op, x, y] | mulExpr, mulExpr = pos:p1 mulExpr:x ("*" | "\/" | "%"):op unary:y pos:p2 -> [#binop, [p1, p2], op, x, y] | unary, unary = pos:p1 ("-" postfix:p pos:p2 -> [#unop, [p1, p2], "-", p] | "+" postfix:p pos:p2 -> [#unop, [p1, p2], "+", p] | "++" postfix:p pos:p2 -> [#preop, [p1, p2], "++", p] | "--" postfix:p pos:p2 -> [#preop, [p1, p2], "--", p] | "!" unary:p pos:p2 -> [#unop, [p1, p2], "!", p] | "~" unary:p pos:p2 -> [#unop, [p1, p2], "~", p] | "void" unary:p pos:p2 -> [#unop, [p1, p2], "void", p] | "delete" unary:p pos:p2 -> [#unop, [p1, p2], "delete", p] | "typeof" unary:p pos:p2 -> [#unop, [p1, p2], "typeof", p]) | postfix, postfix = pos:p1 callExpr:p ( spacesNoNl "++" pos:p2 -> [#postop, [p1, p2], "++", p] | spacesNoNl "--" pos:p2 -> [#postop, [p1, p2], "--", p] | empty -> p ), args = "(" listOf(#exprPart, ','):as ")" -> as, callExpr = pos:p1 callExpr:p ( args:as pos:p2 -> [#call, [p1, p2], p].concat(as) | "." pos:p3 "name":m pos:p4 args:as pos:p2 -> [#send, [p1, p2], [#string, [p3,p4], m], p].concat(as) | "[" expr:i "]" args:as pos:p2 -> [#send, [p1, p2], i, p].concat(as) | "[" expr:i "]" pos:p2 -> [#getp, [p1, p2], i, p] | "." pos:p3 "name":f pos:p2 -> [#getp, [p1, p2], [#string, [p3,p2], f], p] ) | primExpr, memberExpr = pos:p1 memberExpr:p ( "[" expr:i "]" pos:p2 -> [#getp, [p1, p2], i, p] | "." pos:p3 "name":f pos:p2 -> [#getp, [p1, p2], [#string, [p3,p2], f], p] ) | primExpr, primExpr = "(" expr:e ")" -> e | spaces pos:p1 ( "this" pos:p2 -> [#this, [p1, p2]] | "new" pos:p3 memberExpr:e (args | empty -> []):as pos:p2 -> [#new, [p1, p2], [#call, [p3, p2], e].concat(as)] | "name":n pos:p2 -> [#get, [p1, p2], n] | "number":n pos:p2 -> [#number, [p1, p2], n] | "string":s pos:p2 -> [#string, [p1, p2], s] | "function" ("name" | empty) funcRest | "[" listOf(#exprPart, ','):es ("," | empty) "]" pos:p2 -> [#arr, [p1, p2]].concat(es) | "/" (escapeChar | ~'\/' char)*:e "/" letter*:f pos:p2 -> [#regex, [p1, p2], e.join(''), f.join('')] ) | json, json = pos:p1 "{" listOf(#jsonBinding, ','):bs ("," | empty) "}" pos:p2 -> [#json, [p1, p2]].concat(bs), jsonBinding = jsonGetter | jsonSetter | pos:p1 jsonPropName:n ":" exprPart:v pos:p2 -> [#binding, [p1, p2], n, v], jsonGetter = spaces pos:p1 ``get'' jsonPropName:n "(" ")" "{" srcElems:body "}" pos:p2 -> [#jsonGetter, [p1,p2], n, body], jsonSetter = spaces pos:p1 ``set'' jsonPropName:n "(" "name": arg ")" "{" srcElems:body "}" pos:p2 -> [#jsonSetter, [p1,p2], n, body, arg], jsonPropName = "name" | "number" | "string", memberFragment = spaces jsonBinding:jb (',' | empty) spaces end -> jb, categoryFragment = spaces pos:p1 listOf(#exprPart, ','):es pos:p2 ("," | empty) spaces end -> [#arr, [p1, p2]].concat(es), traitFragment = spaces pos:p1 "name" "(" spaces listOf(#exprPart, ','):es spaces ")" spaces sc pos:p2 spaces end -> [#arr, [p1, p2]].concat(es), formal = spaces pos:p1 "name":n pos:p2 -> [#get, [p1, p2], n], funcRest = pos: p1 "(" listOf(#formal, ','):args ")" "{" srcElems:body "}" pos:p2 -> [#func, [p1, p2], body].concat(args), sc = spacesNoNl ('\n' | &'}' | end) | ";", binding = pos:p1 "name":n ( "=" exprPart | empty pos:p -> [#get, [p, p], 'undefined'] ):v pos:p2 -> [#var, [p1, p2], n, v], bindingList = pos:p1 listOf(#binding, ','):bs pos:p2 -> [#begin, [p1, p2]].concat(bs), block = "{" srcElems:ss "}" -> ss, stmt = block | spaces pos:p1 ( "var" bindingList:bs sc pos:p2 -> bs | "if" "(" expr:c ")" stmt:t ( "else" stmt | empty pos:p -> [#get, [p,p], 'undefined'] ):f (sc | empty) pos:p2 -> [#if, [p1, p2], c, t, f] | "while" "(" expr:c ")" stmt:s pos:p2 -> [#while, [p1, p2], c, s] | "do" stmt:s "while" "(" expr:c ")" sc pos:p2 -> [#doWhile, [p1, p2], s, c] | "for" "(" ( "var" bindingList | expr | empty pos:p -> [#get, [p, p], 'undefined'] ):i ";" ( expr | empty pos:p -> [#get, [p, p], 'true'] ):c ";" ( expr | empty pos:p -> [#get, [p, p], 'undefined'] ):u ")" stmt:s pos:p2 -> [#for, [p1, p2], i, c, s, u] | "for" "(" ( pos:p3 ( "var" "name":n pos:p4 -> [#var, [p3, p4], n, [#get, [p3, p3], 'undefined']] ) | "name":n pos:p4 -> [#get, [p3, p4], n] ):v "in" expr:e ")" stmt:s pos:p2 -> [#forIn, [p1, p2], v, e, s] | "switch" "(" expr:e ")" "{" ( pos:p3 "case" expr:c ":" srcElems:cs pos:p4 -> [#case, [p3, p4], c, cs] | pos:p3 "default" ":" srcElems:cs pos:p4 -> [#default, [p3, p4], cs] )*:cs "}" pos:p2 -> [#switch, [p1, p2], e].concat(cs) | "break" sc pos:p2 -> [#break, [p1, p2]] | "debugger" sc pos:p2 -> [#debugger, [p1, p2]] | "continue" sc pos:p2 -> [#continue, [p1, p2]] | "throw" spacesNoNl expr:e sc pos:p2 -> [#throw, [p1, p2], e] | "try" block:t ( "catch" "(" formal:e ")" block | ( empty pos:p -> [#get, [p,p], 'undefined'] ):e ):c ( "finally" block | empty pos:p -> [#get, [p,p], 'undefined'] ):f pos:p2 -> [#try, [p1, p2], t, e, c, f] | "return" ( expr | empty pos:p -> [#get, [p,p], 'undefined'] ):e sc pos:p2 -> [#return, [p1, p2], e] | "with" "(" expr:x ")" stmt:s pos:p2 -> [#with, [p1, p2], x, s] | expr:e sc -> e | ";" pos:p2 -> [#get, [p1, p2], "undefined"]), functionDef = pos:p1 "function" "name":n funcRest:f pos:p2 -> [#var, [p1,p2], n, f], functionDefFragment = functionDef:f spaces end -> f, functionDefsFragment = pos:p1 functionDef*:fs pos:p2 spaces end -> [#arr, [p1, p2]].concat(fs), srcElem = functionDef | stmt, srcElems = pos:p1 srcElem*:ss pos:p2 -> [#begin, [p1,p2]].concat(ss), topLevel = srcElems:r spaces end -> r }