diff --git a/examples/arithmetics.pegjs b/examples/arithmetics.pegjs index be7fffc..52fae2a 100644 --- a/examples/arithmetics.pegjs +++ b/examples/arithmetics.pegjs @@ -7,16 +7,16 @@ start = additive additive - = multiplicative "+" additive { return $1 + $3; } + = left:multiplicative "+" right:additive { return left + right; } / multiplicative multiplicative - = primary "*" multiplicative { return $1 * $3; } + = left:primary "*" right:multiplicative { return left * right; } / primary primary = integer - / "(" additive ")" { return $2; } + / "(" additive:additive ")" { return additive; } integer "integer" - = [0-9]+ { return parseInt($1.join(""), 10); } + = digits:[0-9]+ { return parseInt(digits.join(""), 10); } diff --git a/examples/css.pegjs b/examples/css.pegjs index 18fe7b8..5a8bd07 100644 --- a/examples/css.pegjs +++ b/examples/css.pegjs @@ -15,106 +15,114 @@ /* ===== Syntactical Elements ===== */ start - = stylesheet comment* { return $1; } + = stylesheet:stylesheet comment* { return stylesheet; } stylesheet - = (CHARSET_SYM STRING ";")? (S / CDO / CDC)* - (import (CDO S* / CDC S*)*)* - ((ruleset / media / page) (CDO S* / CDC S*)*)* { - var imports = []; - for (var i = 0; i < $3.length; i++) { - imports.push($3[i][0]); + = charset:(CHARSET_SYM STRING ";")? (S / CDO / CDC)* + imports:(import (CDO S* / CDC S*)*)* + rules:((ruleset / media / page) (CDO S* / CDC S*)*)* { + var importsConverted = []; + for (var i = 0; i < imports.length; i++) { + importsConverted.push(imports[i][0]); } - var rules = []; - for (i = 0; i < $4.length; i++) { - rules.push($4[i][0]); + var rulesConverted = []; + for (i = 0; i < rules.length; i++) { + rulesConverted.push(rules[i][0]); } return { type: "stylesheet", - charset: $1 !== "" ? $1[1] : null, - imports: imports, - rules: rules + charset: charset !== "" ? charset[1] : null, + imports: importsConverted, + rules: rulesConverted }; } import - = IMPORT_SYM S* (STRING / URI) S* media_list? ";" S* { + = IMPORT_SYM S* href:(STRING / URI) S* media:media_list? ";" S* { return { type: "import_rule", - href: $3, - media: $5 !== "" ? $5 : [] + href: href, + media: media !== "" ? media : [] }; } media - = MEDIA_SYM S* media_list "{" S* ruleset* "}" S* { + = MEDIA_SYM S* media:media_list "{" S* rules:ruleset* "}" S* { return { type: "media_rule", - media: $3, - rules: $6 + media: media, + rules: rules }; } media_list - = medium ("," S* medium)* { - var result = [$1]; - for (var i = 0; i < $2.length; i++) { - result.push($2[i][2]); + = head:medium tail:("," S* medium)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][2]); } return result; } medium - = IDENT S* { return $1; } + = ident:IDENT S* { return ident; } page - = PAGE_SYM S* pseudo_page? "{" S* declaration? (";" S* declaration?)* "}" S* { - var declarations = $6 !== "" ? [$6] : []; - for (var i = 0; i < $7.length; i++) { - if ($7[i][2] !== "") { - declarations.push($7[i][2]); + = PAGE_SYM S* qualifier:pseudo_page? + "{" S* + declarationsHead:declaration? + declarationsTail:(";" S* declaration?)* + "}" S* { + var declarations = declarationsHead !== "" ? [declarationsHead] : []; + for (var i = 0; i < declarationsTail.length; i++) { + if (declarationsTail[i][2] !== "") { + declarations.push(declarationsTail[i][2]); } } return { type: "page_rule", - qualifier: $3 !== "" ? $3 : null, + qualifier: qualifier !== "" ? qualifier : null, declarations: declarations }; } pseudo_page - = ":" IDENT S* { return $2; } + = ":" ident:IDENT S* { return ident; } operator - = "/" S* { return $1; } - / "," S* { return $1; } + = "/" S* { return "/"; } + / "," S* { return ","; } combinator - = "+" S* { return $1; } - / ">" S* { return $1; } + = "+" S* { return "+"; } + / ">" S* { return ">"; } unary_operator = "+" / "-" property - = IDENT S* { return $1; } + = ident:IDENT S* { return ident; } ruleset - = selector ("," S* selector)* - "{" S* declaration? (";" S* declaration?)* "}" S* { - var selectors = [$1]; - for (var i = 0; i < $2.length; i++) { - selectors.push($2[i][2]); + = selectorsHead:selector + selectorsTail:("," S* selector)* + "{" S* + declarationsHead:declaration? + declarationsTail:(";" S* declaration?)* + "}" S* { + var selectors = [selectorsHead]; + for (var i = 0; i < selectorsTail.length; i++) { + selectors.push(selectorsTail[i][2]); } - var declarations = $5 !== "" ? [$5] : []; - for (i = 0; i < $6.length; i++) { - if ($6[i][2] !== "") { - declarations.push($6[i][2]); + var declarations = declarationsHead !== "" ? [declarationsHead] : []; + for (i = 0; i < declarationsTail.length; i++) { + if (declarationsTail[i][2] !== "") { + declarations.push(declarationsTail[i][2]); } } @@ -126,40 +134,40 @@ ruleset } selector - = simple_selector S* combinator selector { + = left:simple_selector S* combinator:combinator right:selector { return { type: "selector", - combinator: $3, - left: $1, - right: $4 + combinator: combinator, + left: left, + right: right }; } - / simple_selector S* selector { + / left:simple_selector S* right:selector { return { type: "selector", combinator: " ", - left: $1, - right: $3 + left: left, + right: right }; } - / simple_selector S* { return $1; } + / selector:simple_selector S* { return selector; } simple_selector - = element_name - ( - HASH { return { type: "ID selector", id: $1.substr(1) }; } + = element:element_name + qualifiers:( + id:HASH { return { type: "ID selector", id: id.substr(1) }; } / class / attrib / pseudo )* { return { type: "simple_selector", - element: $1, - qualifiers: $2 + element: element, + qualifiers: qualifiers }; } - / ( - HASH { return { type: "ID selector", id: $1.substr(1) }; } + / qualifiers:( + id:HASH { return { type: "ID selector", id: id.substr(1) }; } / class / attrib / pseudo @@ -167,34 +175,40 @@ simple_selector return { type: "simple_selector", element: "*", - qualifiers: $1 + qualifiers: qualifiers }; } class - = "." IDENT { return { type: "class_selector", "class": $2 }; } + = "." class:IDENT { return { type: "class_selector", "class": class }; } element_name = IDENT / '*' attrib - = "[" S* IDENT S* (('=' / INCLUDES / DASHMATCH) S* (IDENT / STRING) S*)? "]" { + = "[" S* + attribute:IDENT S* + operatorAndValue:( + ('=' / INCLUDES / DASHMATCH) S* + (IDENT / STRING) S* + )? + "]" { return { type: "attribute_selector", - attribute: $3, - operator: $5 !== "" ? $5[0] : null, - value: $5 !== "" ? $5[2] : null + attribute: attribute, + operator: operatorAndValue !== "" ? operatorAndValue[0] : null, + value: operatorAndValue !== "" ? operatorAndValue[2] : null }; } pseudo = ":" - ( - FUNCTION S* (IDENT S*)? ")" { + value:( + name:FUNCTION S* params:(IDENT S*)? ")" { return { type: "function", - name: $1, - params: $3 !== "" ? [$3[0]] : [] + name: name, + params: params !== "" ? [params[0]] : [] }; } / IDENT @@ -206,17 +220,17 @@ pseudo */ return { type: "pseudo_selector", - value: $2 + value: value }; } declaration - = property ":" S* expr prio? { + = property:property ":" S* expression:expr important:prio? { return { type: "declaration", - property: $1, - expression: $4, - important: $5 !== "" ? true : false + property: property, + expression: expression, + important: important !== "" ? true : false }; } @@ -224,22 +238,22 @@ prio = IMPORTANT_SYM S* expr - = term (operator? term)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:term tail:(operator? term)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "expression", - operator: $2[i][0], + operator: tail[i][0], left: result, - right: $2[i][1] + right: tail[i][1] }; } return result; } term - = unary_operator? - ( + = operator:unary_operator? + value:( EMS S* / EXS S* / LENGTH S* @@ -248,24 +262,24 @@ term / FREQ S* / PERCENTAGE S* / NUMBER S* - ) { return { type: "value", value: $1 + $2[0] }; } - / URI S* { return { type: "uri", value: $1 }; } + ) { return { type: "value", value: operator + value[0] }; } + / value:URI S* { return { type: "uri", value: value }; } / function / hexcolor - / STRING S* { return { type: "string", value: $1 }; } - / IDENT S* { return { type: "ident", value: $1 }; } + / value:STRING S* { return { type: "string", value: value }; } + / value:IDENT S* { return { type: "ident", value: value }; } function - = FUNCTION S* expr ")" S* { + = name:FUNCTION S* params:expr ")" S* { return { type: "function", - name: $1, - params: $3 + name: name, + params: params }; } hexcolor - = HASH S* { return { type: "hexcolor", value: $1}; } + = value:HASH S* { return { type: "hexcolor", value: value}; } /* ===== Lexical Elements ===== */ @@ -278,13 +292,13 @@ nonascii = [\x80-\xFF] unicode - = "\\" h h? h? h? h? h? ("\r\n" / [ \t\r\n\f])? { - return String.fromCharCode(parseInt("0x" + $2 + $3 + $4 + $5 + $6 + $7)); + = "\\" h1:h h2:h? h3:h? h4:h? h5:h? h6:h? ("\r\n" / [ \t\r\n\f])? { + return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4 + h5 + h6)); } escape = unicode - / "\\" [^\r\n\f0-9a-fA-F] { return $2; } + / "\\" char:[^\r\n\f0-9a-fA-F] { return char; } nmstart = [_a-zA-Z] @@ -297,29 +311,33 @@ nmchar / escape integer - = [0-9]+ { return parseInt($1.join("")); } + = digits:[0-9]+ { return parseInt(digits.join("")); } float - = [0-9]* "." [0-9]+ { return parseFloat($1.join("") + $2 + $3.join("")); } + = before:[0-9]* "." after:[0-9]+ { + return parseFloat(before.join("") + "." + after.join("")); + } string1 - = '"' ([^\n\r\f\\"] / "\\" nl { return $2 } / escape)* '"' { - return $2.join(""); + = '"' chars:([^\n\r\f\\"] / "\\" nl:nl { return nl } / escape)* '"' { + return chars.join(""); } string2 - = "'" ([^\n\r\f\\'] / "\\" nl { return $2 } / escape)* "'" { - return $2.join(""); + = "'" chars:([^\n\r\f\\'] / "\\" nl:nl { return nl } / escape)* "'" { + return chars.join(""); } comment = "/*" [^*]* "*"+ ([^/*] [^*]* "*"+)* "/" ident - = "-"? nmstart nmchar* { return $1 + $2 + $3.join(""); } + = dash:"-"? nmstart:nmstart nmchars:nmchar* { + return dash + nmstart + nmchars.join(""); + } name - = nmchar+ { return $1.join(""); } + = nmchars:nmchar+ { return nmchars.join(""); } num = float @@ -330,7 +348,7 @@ string / string2 url - = ([!#$%&*-~] / nonascii / escape)* { return $1.join(""); } + = chars:([!#$%&*-~] / nonascii / escape)* { return chars.join(""); } s = [ \t\r\n\f]+ @@ -368,91 +386,91 @@ G = [gG] / "\\" "0"? "0"? "0"? "0"? "47" ("\r\n" / [ \t\r\n\f])? { return "G"; } / "\\" "0"? "0"? "0"? "0"? "67" ("\r\n" / [ \t\r\n\f])? { return "g"; } - / "\\" [gG] { return $2; } + / "\\" char:[gG] { return char; } H - = [hH] + = h:[hH] / "\\" "0"? "0"? "0"? "0"? "48" ("\r\n" / [ \t\r\n\f])? { return "H"; } / "\\" "0"? "0"? "0"? "0"? "68" ("\r\n" / [ \t\r\n\f])? { return "h"; } - / "\\" [hH] { return $2; } + / "\\" char:[hH] { return char; } I - = [iI] + = i:[iI] / "\\" "0"? "0"? "0"? "0"? "49" ("\r\n" / [ \t\r\n\f])? { return "I"; } / "\\" "0"? "0"? "0"? "0"? "69" ("\r\n" / [ \t\r\n\f])? { return "i"; } - / "\\" [iI] { return $2; } + / "\\" char:[iI] { return char; } K = [kK] / "\\" "0"? "0"? "0"? "0"? "4" [bB] ("\r\n" / [ \t\r\n\f])? { return "K"; } / "\\" "0"? "0"? "0"? "0"? "6" [bB] ("\r\n" / [ \t\r\n\f])? { return "k"; } - / "\\" [kK] { return $2; } + / "\\" char:[kK] { return char; } L = [lL] / "\\" "0"? "0"? "0"? "0"? "4" [cC] ("\r\n" / [ \t\r\n\f])? { return "L"; } / "\\" "0"? "0"? "0"? "0"? "6" [cC] ("\r\n" / [ \t\r\n\f])? { return "l"; } - / "\\" [lL] { return $2; } + / "\\" char:[lL] { return char; } M = [mM] / "\\" "0"? "0"? "0"? "0"? "4" [dD] ("\r\n" / [ \t\r\n\f])? { return "M"; } / "\\" "0"? "0"? "0"? "0"? "6" [dD] ("\r\n" / [ \t\r\n\f])? { return "m"; } - / "\\" [mM] { return $2; } + / "\\" char:[mM] { return char; } N = [nN] / "\\" "0"? "0"? "0"? "0"? "4" [eE] ("\r\n" / [ \t\r\n\f])? { return "N"; } / "\\" "0"? "0"? "0"? "0"? "6" [eE] ("\r\n" / [ \t\r\n\f])? { return "n"; } - / "\\" [nN] { return $2; } + / "\\" char:[nN] { return char; } O = [oO] / "\\" "0"? "0"? "0"? "0"? "4" [fF] ("\r\n" / [ \t\r\n\f])? { return "O"; } / "\\" "0"? "0"? "0"? "0"? "6" [fF] ("\r\n" / [ \t\r\n\f])? { return "o"; } - / "\\" [oO] { return $2; } + / "\\" char:[oO] { return char; } P = [pP] / "\\" "0"? "0"? "0"? "0"? "50" ("\r\n" / [ \t\r\n\f])? { return "P"; } / "\\" "0"? "0"? "0"? "0"? "70" ("\r\n" / [ \t\r\n\f])? { return "p"; } - / "\\" [pP] { return $2; } + / "\\" char:[pP] { return char; } R = [rR] / "\\" "0"? "0"? "0"? "0"? "52" ("\r\n" / [ \t\r\n\f])? { return "R"; } / "\\" "0"? "0"? "0"? "0"? "72" ("\r\n" / [ \t\r\n\f])? { return "r"; } - / "\\" [rR] { return $2; } + / "\\" char:[rR] { return char; } S_ = [sS] / "\\" "0"? "0"? "0"? "0"? "53" ("\r\n" / [ \t\r\n\f])? { return "S"; } / "\\" "0"? "0"? "0"? "0"? "73" ("\r\n" / [ \t\r\n\f])? { return "s"; } - / "\\" [sS] { return $2; } + / "\\" char:[sS] { return char; } T = [tT] / "\\" "0"? "0"? "0"? "0"? "54" ("\r\n" / [ \t\r\n\f])? { return "T"; } / "\\" "0"? "0"? "0"? "0"? "74" ("\r\n" / [ \t\r\n\f])? { return "t"; } - / "\\" [tT] { return $2; } + / "\\" char:[tT] { return char; } U = [uU] / "\\" "0"? "0"? "0"? "0"? "55" ("\r\n" / [ \t\r\n\f])? { return "U"; } / "\\" "0"? "0"? "0"? "0"? "75" ("\r\n" / [ \t\r\n\f])? { return "u"; } - / "\\" [uU] { return $2; } + / "\\" char:[uU] { return char; } X = [xX] / "\\" "0"? "0"? "0"? "0"? "58" ("\r\n" / [ \t\r\n\f])? { return "X"; } / "\\" "0"? "0"? "0"? "0"? "78" ("\r\n" / [ \t\r\n\f])? { return "x"; } - / "\\" [xX] { return $2; } + / "\\" char:[xX] { return char; } Z = [zZ] / "\\" "0"? "0"? "0"? "0"? "5" [aA] ("\r\n" / [ \t\r\n\f])? { return "Z"; } / "\\" "0"? "0"? "0"? "0"? "7" [aA] ("\r\n" / [ \t\r\n\f])? { return "z"; } - / "\\" [zZ] { return $2; } + / "\\" char:[zZ] { return char; } /* Tokens */ @@ -472,13 +490,13 @@ DASHMATCH "|=" = comment* "|=" STRING "string" - = comment* string { return $2; } + = comment* string:string { return string; } IDENT "identifier" - = comment* ident { return $2; } + = comment* ident:ident { return ident; } HASH "hash" - = comment* "#" name { return $2 + $3; } + = comment* "#" name:name { return "#" + name; } IMPORT_SYM "@import" = comment* "@" I M P O R T @@ -497,36 +515,40 @@ IMPORTANT_SYM "!important" = comment* "!" (s / comment)* I M P O R T A N T { return "!important"; } EMS "length" - = comment* num E M { return $2 + $3 + $4; } + = comment* num:num e:E m:M { return num + e + m; } EXS "length" - = comment* num E X { return $2 + $3 + $4; } + = comment* num:num e:E x:X { return num + e + x; } LENGTH "length" - = comment* num (P X / C M / M M / I N / P T / P C) { - return $2 + $3.join(""); + = comment* num:num unit:(P X / C M / M M / I N / P T / P C) { + return num + unit.join(""); } ANGLE "angle" - = comment* num (D E G / R A D / G R A D) { return $2 + $3.join(""); } + = comment* num:num unit:(D E G / R A D / G R A D) { + return num + unit.join(""); + } TIME "time" - = comment* num (M S_ { return $1 + $2; } / S_) { return $2 + $3; } + = comment* num:num unit:(m:M s:S_ { return m + s; } / S_) { + return num + unit; + } FREQ "frequency" - = comment* num (H Z / K H Z) { return $2 + $3.join(""); } + = comment* num:num unit:(H Z / K H Z) { return num + unit.join(""); } DIMENSION "dimension" - = comment* num ident { return $2 + $3; } + = comment* num:num unit:ident { return num + unit; } PERCENTAGE "percentage" - = comment* num "%" { return $2 + $3; } + = comment* num:num "%" { return num + "%"; } NUMBER "number" - = comment* num { return $2; } + = comment* num:num { return num; } URI "uri" - = comment* U R L "(" w (string / url) w ")" { return $7; } + = comment* U R L "(" w value:(string / url) w ")" { return value; } FUNCTION "function" - = comment* ident "(" { return $2; } + = comment* name:ident "(" { return name; } diff --git a/examples/javascript.pegjs b/examples/javascript.pegjs index 838e9ff..1de4bd0 100644 --- a/examples/javascript.pegjs +++ b/examples/javascript.pegjs @@ -46,7 +46,7 @@ */ start - = __ Program __ { return $2; } + = __ program:Program __ { return program; } /* ===== A.1 Lexical Grammar ===== */ @@ -81,16 +81,18 @@ SingleLineComment = "//" (!LineTerminator SourceCharacter)* Identifier "identifier" - = !ReservedWord IdentifierName { return $2; } + = !ReservedWord name:IdentifierName { return name; } IdentifierName "identifier" - = IdentifierStart IdentifierPart* { return $1 + $2.join(""); } + = start:IdentifierStart parts:IdentifierPart* { + return start + parts.join(""); + } IdentifierStart = UnicodeLetter / "$" / "_" - / "\\" UnicodeEscapeSequence { return $2; } + / "\\" sequence:UnicodeEscapeSequence { return sequence; } IdentifierPart = IdentifierStart @@ -174,8 +176,18 @@ FutureReservedWord Literal = NullLiteral / BooleanLiteral - / NumericLiteral { return { type: "NumericLiteral", value: $1 }; } - / StringLiteral { return { type: "StringLiteral", value: $1 }; } + / value:NumericLiteral { + return { + type: "NumericLiteral", + value: value + }; + } + / value:StringLiteral { + return { + type: "StringLiteral", + value: value + }; + } / RegularExpressionLiteral NullLiteral @@ -186,24 +198,29 @@ BooleanLiteral / FalseToken { return { type: "BooleanLiteral", value: false }; } NumericLiteral "number" - = (HexIntegerLiteral / DecimalLiteral) !IdentifierStart { return $1; } + = literal:(HexIntegerLiteral / DecimalLiteral) !IdentifierStart { + return literal; + } DecimalLiteral - = DecimalIntegerLiteral "." DecimalDigits? ExponentPart? { - return parseFloat($1 + $2 + $3 + $4); + = before:DecimalIntegerLiteral + "." + after:DecimalDigits? + exponent:ExponentPart? { + return parseFloat(before + "." + after + exponent); } - / "." DecimalDigits ExponentPart? { - return parseFloat($1 + $2 + $3); + / "." after:DecimalDigits exponent:ExponentPart? { + return parseFloat("." + after + exponent); } - / DecimalIntegerLiteral ExponentPart? { - return parseFloat($1 + $2); + / before:DecimalIntegerLiteral exponent:ExponentPart? { + return parseFloat(before + exponent); } DecimalIntegerLiteral - = "0" / NonZeroDigit DecimalDigits? { return $1 + $2; } + = "0" / digit:NonZeroDigit digits:DecimalDigits? { return digit + digits; } DecimalDigits - = DecimalDigit+ { return $1.join(""); } + = digits:DecimalDigit+ { return digits.join(""); } DecimalDigit = [0-9] @@ -212,43 +229,45 @@ NonZeroDigit = [1-9] ExponentPart - = ExponentIndicator SignedInteger { return $1 + $2; } + = indicator:ExponentIndicator integer:SignedInteger { + return indicator + integer; + } ExponentIndicator = [eE] SignedInteger - = [-+]? DecimalDigits { return $1 + $2; } + = sign:[-+]? digits:DecimalDigits { return sign + digits; } HexIntegerLiteral - = "0" [xX] HexDigit+ { return parseInt($1 + $2 + $3.join("")); } + = "0" [xX] digits:HexDigit+ { return parseInt("0x" + dgits.join("")); } HexDigit = [0-9a-fA-F] StringLiteral "string" - = ('"' DoubleStringCharacters? '"' / "'" SingleStringCharacters? "'") { - return $1[1]; + = parts:('"' DoubleStringCharacters? '"' / "'" SingleStringCharacters? "'") { + return parts[1]; } DoubleStringCharacters - = DoubleStringCharacter+ { return $1.join(""); } + = chars:DoubleStringCharacter+ { return chars.join(""); } SingleStringCharacters - = SingleStringCharacter+ { return $1.join(""); } + = chars:SingleStringCharacter+ { return chars.join(""); } DoubleStringCharacter - = !('"' / "\\" / LineTerminator) SourceCharacter { return $2; } - / "\\" EscapeSequence { return $2; } + = !('"' / "\\" / LineTerminator) char:SourceCharacter { return char; } + / "\\" sequence:EscapeSequence { return sequence; } / LineContinuation SingleStringCharacter - = !("'" / "\\" / LineTerminator) SourceCharacter { return $2; } - / "\\" EscapeSequence { return $2; } + = !("'" / "\\" / LineTerminator) char:SourceCharacter { return char; } + / "\\" sequence:EscapeSequence { return sequence; } / LineContinuation LineContinuation - = "\\" LineTerminatorSequence { return $2; } + = "\\" sequence:LineTerminatorSequence { return sequence; } EscapeSequence = CharacterEscapeSequence @@ -261,8 +280,8 @@ CharacterEscapeSequence / NonEscapeCharacter SingleEscapeCharacter - = ['"\\bfnrtv] { - return $1 + = char:['"\\bfnrtv] { + return char .replace("b", "\b") .replace("f", "\f") .replace("n", "\n") @@ -272,7 +291,7 @@ SingleEscapeCharacter } NonEscapeCharacter - = (!EscapeCharacter / LineTerminator) SourceCharacter { return $2; } + = (!EscapeCharacter / LineTerminator) char:SourceCharacter { return char; } EscapeCharacter = SingleEscapeCharacter @@ -281,37 +300,39 @@ EscapeCharacter / "u" HexEscapeSequence - = "x" HexDigit HexDigit { - return String.fromCharCode(parseInt("0x" + $2 + $3)); + = "x" h1:HexDigit h2:HexDigit { + return String.fromCharCode(parseInt("0x" + h1 + h2)); } UnicodeEscapeSequence - = "u" HexDigit HexDigit HexDigit HexDigit { - return String.fromCharCode(parseInt("0x" + $2 + $3 + $4 + $5)); + = "u" h1:HexDigit h2:HexDigit h3:HexDigit h4:HexDigit { + return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4)); } RegularExpressionLiteral "regular expression" - = "/" RegularExpressionBody "/" RegularExpressionFlags { + = "/" body:RegularExpressionBody "/" flags:RegularExpressionFlags { return { type: "RegularExpressionLiteral", - body: $2, - flags: $4 + body: body, + flags: flags }; } RegularExpressionBody - = RegularExpressionFirstChar RegularExpressionChars { return $1 + $2; } + = char:RegularExpressionFirstChar chars:RegularExpressionChars { + return char + chars; + } RegularExpressionChars - = RegularExpressionChar* { return $1.join(""); } + = chars:RegularExpressionChar* { return chars.join(""); } RegularExpressionFirstChar - = ![*\\/[] RegularExpressionNonTerminator { return $2; } + = ![*\\/[] char:RegularExpressionNonTerminator { return char; } / RegularExpressionBackslashSequence / RegularExpressionClass RegularExpressionChar - = ![\\/[] RegularExpressionNonTerminator { return $2; } + = ![\\/[] char:RegularExpressionNonTerminator { return char; } / RegularExpressionBackslashSequence / RegularExpressionClass @@ -320,57 +341,57 @@ RegularExpressionChar * "RegularExpressionNonTerminator". */ RegularExpressionBackslashSequence - = "\\" RegularExpressionNonTerminator { return $1 + $2; } + = "\\" char:RegularExpressionNonTerminator { return "\\" + char; } RegularExpressionNonTerminator - = !LineTerminator SourceCharacter { return $2; } + = !LineTerminator char:SourceCharacter { return char; } RegularExpressionClass - = "[" RegularExpressionClassChars "]" { return $1 + $2 + $3; } + = "[" chars:RegularExpressionClassChars "]" { return "[" + chars + "]"; } RegularExpressionClassChars - = RegularExpressionClassChar* { return $1.join(""); } + = chars:RegularExpressionClassChar* { return chars.join(""); } RegularExpressionClassChar - = ![\]\\] RegularExpressionNonTerminator { return $2; } + = ![\]\\] char:RegularExpressionNonTerminator { return char; } / RegularExpressionBackslashSequence RegularExpressionFlags - = IdentifierPart* { return $1.join(""); } + = parts:IdentifierPart* { return parts.join(""); } /* Tokens */ -BreakToken = "break" !IdentifierPart -CaseToken = "case" !IdentifierPart -CatchToken = "catch" !IdentifierPart -ContinueToken = "continue" !IdentifierPart -DebuggerToken = "debugger" !IdentifierPart -DefaultToken = "default" !IdentifierPart -DeleteToken = "delete" !IdentifierPart { return $1; } -DoToken = "do" !IdentifierPart -ElseToken = "else" !IdentifierPart -FalseToken = "false" !IdentifierPart -FinallyToken = "finally" !IdentifierPart -ForToken = "for" !IdentifierPart -FunctionToken = "function" !IdentifierPart -GetToken = "get" !IdentifierPart -IfToken = "if" !IdentifierPart -InstanceofToken = "instanceof" !IdentifierPart { return $1; } -InToken = "in" !IdentifierPart { return $1; } -NewToken = "new" !IdentifierPart -NullToken = "null" !IdentifierPart -ReturnToken = "return" !IdentifierPart -SetToken = "set" !IdentifierPart -SwitchToken = "switch" !IdentifierPart -ThisToken = "this" !IdentifierPart -ThrowToken = "throw" !IdentifierPart -TrueToken = "true" !IdentifierPart -TryToken = "try" !IdentifierPart -TypeofToken = "typeof" !IdentifierPart { return $1; } -VarToken = "var" !IdentifierPart -VoidToken = "void" !IdentifierPart { return $1; } -WhileToken = "while" !IdentifierPart -WithToken = "with" !IdentifierPart +BreakToken = "break" !IdentifierPart +CaseToken = "case" !IdentifierPart +CatchToken = "catch" !IdentifierPart +ContinueToken = "continue" !IdentifierPart +DebuggerToken = "debugger" !IdentifierPart +DefaultToken = "default" !IdentifierPart +DeleteToken = "delete" !IdentifierPart { return "delete"; } +DoToken = "do" !IdentifierPart +ElseToken = "else" !IdentifierPart +FalseToken = "false" !IdentifierPart +FinallyToken = "finally" !IdentifierPart +ForToken = "for" !IdentifierPart +FunctionToken = "function" !IdentifierPart +GetToken = "get" !IdentifierPart +IfToken = "if" !IdentifierPart +InstanceofToken = "instanceof" !IdentifierPart { return "instanceof"; } +InToken = "in" !IdentifierPart { return "in"; } +NewToken = "new" !IdentifierPart +NullToken = "null" !IdentifierPart +ReturnToken = "return" !IdentifierPart +SetToken = "set" !IdentifierPart +SwitchToken = "switch" !IdentifierPart +ThisToken = "this" !IdentifierPart +ThrowToken = "throw" !IdentifierPart +TrueToken = "true" !IdentifierPart +TryToken = "try" !IdentifierPart +TypeofToken = "typeof" !IdentifierPart { return "typeof"; } +VarToken = "var" !IdentifierPart +VoidToken = "void" !IdentifierPart { return "void"; } +WhileToken = "while" !IdentifierPart +WithToken = "with" !IdentifierPart /* * Unicode Character Categories @@ -455,27 +476,28 @@ __ /* ===== A.3 Expressions ===== */ PrimaryExpression - = ThisToken { return { type: "This" }; } - / Identifier { return { type: "Variable", name: $1 }; } + = ThisToken { return { type: "This" }; } + / name:Identifier { return { type: "Variable", name: name }; } / Literal / ArrayLiteral / ObjectLiteral - / "(" __ Expression __ ")" { return $3; } + / "(" __ expression:Expression __ ")" { return expression; } ArrayLiteral - = "[" __ ElementList? __ (Elision __)? "]" { + = "[" __ elements:ElementList? __ (Elision __)? "]" { return { type: "ArrayLiteral", - elements: $3 !== "" ? $3 : [] + elements: elements !== "" ? elements : [] }; } ElementList - = (Elision __)? AssignmentExpression - (__ "," __ Elision? __ AssignmentExpression)* { - var result = [$2]; - for (var i = 0; i < $3.length; i++) { - result.push($3[i][5]); + = (Elision __)? + head:AssignmentExpression + tail:(__ "," __ Elision? __ AssignmentExpression)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][5]); } return result; } @@ -484,45 +506,47 @@ Elision = "," (__ ",")* ObjectLiteral - = "{" __ (PropertyNameAndValueList __ ("," __)?)? "}" { + = "{" __ properties:(PropertyNameAndValueList __ ("," __)?)? "}" { return { type: "ObjectLiteral", - properties: $3 !== "" ? $3[0] : [] + properties: properties !== "" ? properties[0] : [] }; } PropertyNameAndValueList - = PropertyAssignment (__ "," __ PropertyAssignment)* { - var result = [$1]; - for (var i = 0; i < $2.length; i++) { - result.push($2[i][3]); + = head:PropertyAssignment tail:(__ "," __ PropertyAssignment)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][3]); } return result; } PropertyAssignment - = PropertyName __ ":" __ AssignmentExpression { + = name:PropertyName __ ":" __ value:AssignmentExpression { return { type: "PropertyAssignment", - name: $1, - value: $5 + name: name, + value: value }; } - / GetToken __ PropertyName __ "(" __ ")" __ "{" __ FunctionBody __ "}" { + / GetToken __ name:PropertyName __ + "(" __ ")" __ + "{" __ body:FunctionBody __ "}" { return { type: "GetterDefinition", - name: $3, - body: $11 + name: name, + body: body }; } - / SetToken __ PropertyName __ - "(" __ PropertySetParameterList __ ")" __ - "{" __ FunctionBody __ "}" { + / SetToken __ name:PropertyName __ + "(" __ param:PropertySetParameterList __ ")" __ + "{" __ body:FunctionBody __ "}" { return { type: "SetterDefinition", - name: $3, - param: $7, - body: $13 + name: name, + param: param, + body: body }; } @@ -535,27 +559,27 @@ PropertySetParameterList = Identifier MemberExpression - = ( + = base:( PrimaryExpression / FunctionExpression - / NewToken __ MemberExpression __ Arguments { + / NewToken __ constructor:MemberExpression __ arguments:Arguments { return { type: "NewOperator", - constructor: $3, - arguments: $5 + constructor: constructor, + arguments: arguments }; } ) - ( - __ "[" __ Expression __ "]" { return $4; } - / __ "." __ IdentifierName { return $4; } + accessors:( + __ "[" __ name:Expression __ "]" { return name; } + / __ "." __ name:IdentifierName { return name; } )* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + var result = base; + for (var i = 0; i < accessors.length; i++) { result = { type: "PropertyAccess", base: result, - name: $2[i] + name: accessors[i] }; } return result; @@ -563,76 +587,80 @@ MemberExpression NewExpression = MemberExpression - / NewToken __ NewExpression { + / NewToken __ constructor:NewExpression { return { type: "NewOperator", - constructor: $3, + constructor: constructor, arguments: [] }; } CallExpression - = ( - MemberExpression __ Arguments { + = base:( + name:MemberExpression __ arguments:Arguments { return { type: "FunctionCall", - name: $1, - arguments: $3 + name: name, + arguments: arguments }; } ) - ( - __ Arguments { + argumentsOrAccessors:( + __ arguments:Arguments { return { type: "FunctionCallArguments", - arguments: $2 + arguments: arguments }; } - / __ "[" __ Expression __ "]" { + / __ "[" __ name:Expression __ "]" { return { type: "PropertyAccessProperty", - name: $4 + name: name }; } - / __ "." __ IdentifierName { + / __ "." __ name:IdentifierName { return { type: "PropertyAccessProperty", - name: $4 + name: name }; } )* { - var result = $1; - for (var i = 0; i < $2.length; i++) { - switch ($2[i].type) { + var result = base; + for (var i = 0; i < argumentsOrAccessors.length; i++) { + switch (argumentsOrAccessors[i].type) { case "FunctionCallArguments": result = { type: "FuctionCall", name: result, - arguments: $2[i].arguments + arguments: argumentsOrAccessors[i].arguments }; break; case "PropertyAccessProperty": result = { type: "PropertyAccess", base: result, - name: $2[i].name + name: argumentsOrAccessors[i].name }; break; default: - throw new Error("Invalid expression type: " + $2[i].type); + throw new Error( + "Invalid expression type: " + argumentsOrAccessors[i].type + ); } } return result; } Arguments - = "(" __ ArgumentList? __ ")" { return $3 !== "" ? $3 : []; } + = "(" __ arguments:ArgumentList? __ ")" { + return arguments !== "" ? arguments : []; + } ArgumentList - = AssignmentExpression (__ "," __ AssignmentExpression)* { - var result = [$1]; - for (var i = 0; i < $2.length; i++) { - result.push($2[i][3]); + = head:AssignmentExpression tail:(__ "," __ AssignmentExpression)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][3]); } return result; } @@ -642,11 +670,11 @@ LeftHandSideExpression / NewExpression PostfixExpression - = LeftHandSideExpression _ PostfixOperator { + = expression:LeftHandSideExpression _ operator:PostfixOperator { return { type: "PostfixExpression", - operator: $3, - expression: $1 + operator: operator, + expression: expression }; } / LeftHandSideExpression @@ -657,11 +685,11 @@ PostfixOperator UnaryExpression = PostfixExpression - / UnaryOperator __ UnaryExpression { + / operator:UnaryOperator __ expression:UnaryExpression { return { type: "UnaryExpression", - operator: $1, - expression: $3 + operator: operator, + expression: expression }; } @@ -677,49 +705,52 @@ UnaryOperator / "!" MultiplicativeExpression - = UnaryExpression (__ MultiplicativeOperator __ UnaryExpression)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:UnaryExpression + tail:(__ MultiplicativeOperator __ UnaryExpression)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } MultiplicativeOperator - = ("*" / "/" / "%") !"=" { return $1; } + = operator:("*" / "/" / "%") !"=" { return operator; } AdditiveExpression - = MultiplicativeExpression (__ AdditiveOperator __ MultiplicativeExpression)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:MultiplicativeExpression + tail:(__ AdditiveOperator __ MultiplicativeExpression)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } AdditiveOperator - = "+" !("+" / "=") { return $1; } - / "-" !("-" / "=") { return $1; } + = "+" !("+" / "=") { return "+"; } + / "-" !("-" / "=") { return "-"; } ShiftExpression - = AdditiveExpression (__ ShiftOperator __ AdditiveExpression)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:AdditiveExpression + tail:(__ ShiftOperator __ AdditiveExpression)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; @@ -731,14 +762,15 @@ ShiftOperator / ">>" RelationalExpression - = ShiftExpression (__ RelationalOperator __ ShiftExpression)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:ShiftExpression + tail:(__ RelationalOperator __ ShiftExpression)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; @@ -753,14 +785,15 @@ RelationalOperator / InToken RelationalExpressionNoIn - = ShiftExpression (__ RelationalOperatorNoIn __ ShiftExpression)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:ShiftExpression + tail:(__ RelationalOperatorNoIn __ ShiftExpression)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; @@ -774,28 +807,30 @@ RelationalOperatorNoIn / InstanceofToken EqualityExpression - = RelationalExpression (__ EqualityOperator __ RelationalExpression)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:RelationalExpression + tail:(__ EqualityOperator __ RelationalExpression)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } EqualityExpressionNoIn - = RelationalExpressionNoIn (__ EqualityOperator __ RelationalExpressionNoIn)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:RelationalExpressionNoIn + tail:(__ EqualityOperator __ RelationalExpressionNoIn)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; @@ -808,210 +843,224 @@ EqualityOperator / "!=" BitwiseANDExpression - = EqualityExpression (__ BitwiseANDOperator __ EqualityExpression)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:EqualityExpression + tail:(__ BitwiseANDOperator __ EqualityExpression)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } BitwiseANDExpressionNoIn - = EqualityExpressionNoIn (__ BitwiseANDOperator __ EqualityExpressionNoIn)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:EqualityExpressionNoIn + tail:(__ BitwiseANDOperator __ EqualityExpressionNoIn)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } BitwiseANDOperator - = "&" !("&" / "=") { return $1; } + = "&" !("&" / "=") { return "&"; } BitwiseXORExpression - = BitwiseANDExpression (__ BitwiseXOROperator __ BitwiseANDExpression)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:BitwiseANDExpression + tail:(__ BitwiseXOROperator __ BitwiseANDExpression)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } BitwiseXORExpressionNoIn - = BitwiseANDExpressionNoIn (__ BitwiseXOROperator __ BitwiseANDExpressionNoIn)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:BitwiseANDExpressionNoIn + tail:(__ BitwiseXOROperator __ BitwiseANDExpressionNoIn)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } BitwiseXOROperator - = "^" !("^" / "=") { return $1; } + = "^" !("^" / "=") { return "^"; } BitwiseORExpression - = BitwiseXORExpression (__ BitwiseOROperator __ BitwiseXORExpression)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:BitwiseXORExpression + tail:(__ BitwiseOROperator __ BitwiseXORExpression)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } BitwiseORExpressionNoIn - = BitwiseXORExpressionNoIn (__ BitwiseOROperator __ BitwiseXORExpressionNoIn)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:BitwiseXORExpressionNoIn + tail:(__ BitwiseOROperator __ BitwiseXORExpressionNoIn)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } BitwiseOROperator - = "|" !("|" / "=") { return $1; } + = "|" !("|" / "=") { return "|"; } LogicalANDExpression - = BitwiseORExpression (__ LogicalANDOperator __ BitwiseORExpression)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:BitwiseORExpression + tail:(__ LogicalANDOperator __ BitwiseORExpression)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } LogicalANDExpressionNoIn - = BitwiseORExpressionNoIn (__ LogicalANDOperator __ BitwiseORExpressionNoIn)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:BitwiseORExpressionNoIn + tail:(__ LogicalANDOperator __ BitwiseORExpressionNoIn)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } LogicalANDOperator - = "&&" !"=" { return $1; } + = "&&" !"=" { return "&&"; } LogicalORExpression - = LogicalANDExpression (__ LogicalOROperator __ LogicalANDExpression)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:LogicalANDExpression + tail:(__ LogicalOROperator __ LogicalANDExpression)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } LogicalORExpressionNoIn - = LogicalANDExpressionNoIn (__ LogicalOROperator __ LogicalANDExpressionNoIn)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:LogicalANDExpressionNoIn + tail:(__ LogicalOROperator __ LogicalANDExpressionNoIn)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } LogicalOROperator - = "||" !"=" { return $1; } + = "||" !"=" { return "||"; } ConditionalExpression - = LogicalORExpression __ - "?" __ AssignmentExpression __ - ":" __ AssignmentExpression { + = condition:LogicalORExpression __ + "?" __ trueExpression:AssignmentExpression __ + ":" __ falseExpression:AssignmentExpression { return { type: "ConditionalExpression", - condition: $1, - trueExpression: $5, - falseExpression: $9 + condition: condition, + trueExpression: trueExpression, + falseExpression: falseExpression }; } / LogicalORExpression ConditionalExpressionNoIn - = LogicalORExpressionNoIn __ - "?" __ AssignmentExpressionNoIn __ - ":" __ AssignmentExpressionNoIn { + = condition:LogicalORExpressionNoIn __ + "?" __ trueExpression:AssignmentExpressionNoIn __ + ":" __ falseExpression:AssignmentExpressionNoIn { return { type: "ConditionalExpression", - condition: $1, - trueExpression: $5, - falseExpression: $9 + condition: condition, + trueExpression: trueExpression, + falseExpression: falseExpression }; } / LogicalORExpressionNoIn AssignmentExpression - = LeftHandSideExpression __ AssignmentOperator __ AssignmentExpression { + = left:LeftHandSideExpression __ + operator:AssignmentOperator __ + right:AssignmentExpression { return { type: "AssignmentExpression", - operator: $3, - left: $1, - right: $5 + operator: operator, + left: left, + right: right }; } / ConditionalExpression AssignmentExpressionNoIn - = LeftHandSideExpression __ AssignmentOperator __ AssignmentExpressionNoIn { + = left:LeftHandSideExpression __ + operator:AssignmentOperator __ + right:AssignmentExpressionNoIn { return { type: "AssignmentExpression", - operator: $3, - left: $1, - right: $5 + operator: operator, + left: left, + right: right }; } / ConditionalExpressionNoIn AssignmentOperator - = "=" (!"=") { return $1; } + = "=" (!"=") { return "="; } / "*=" / "/=" / "%=" @@ -1025,28 +1074,30 @@ AssignmentOperator / "|=" Expression - = AssignmentExpression (__ "," __ AssignmentExpression)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:AssignmentExpression + tail:(__ "," __ AssignmentExpression)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; } ExpressionNoIn - = AssignmentExpressionNoIn (__ "," __ AssignmentExpressionNoIn)* { - var result = $1; - for (var i = 0; i < $2.length; i++) { + = head:AssignmentExpressionNoIn + tail:(__ "," __ AssignmentExpressionNoIn)* { + var result = head; + for (var i = 0; i < tail.length; i++) { result = { type: "BinaryExpression", - operator: $2[i][1], + operator: tail[i][1], left: result, - right: $2[i][3] + right: tail[i][3] }; } return result; @@ -1079,85 +1130,88 @@ Statement / FunctionExpression Block - = "{" __ (StatementList __)? "}" { + = "{" __ statements:(StatementList __)? "}" { return { type: "Block", - statements: $3 !== "" ? $3[0] : [] + statements: statements !== "" ? statements[0] : [] }; } StatementList - = Statement (__ Statement)* { - var result = [$1]; - for (var i = 0; i < $2.length; i++) { - result.push($2[i][1]); + = head:Statement tail:(__ Statement)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][1]); } return result; } VariableStatement - = VarToken __ VariableDeclarationList EOS { + = VarToken __ declarations:VariableDeclarationList EOS { return { type: "VariableStatement", - declarations: $3 + declarations: declarations }; } VariableDeclarationList - = VariableDeclaration (__ "," __ VariableDeclaration)* { - var result = [$1]; - for (var i = 0; i < $2.length; i++) { - result.push($2[i][3]); + = head:VariableDeclaration tail:(__ "," __ VariableDeclaration)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][3]); } return result; } VariableDeclarationListNoIn - = VariableDeclarationNoIn (__ "," __ VariableDeclarationNoIn)* { - var result = [$1]; - for (var i = 0; i < $2.length; i++) { - result.push($2[i][3]); + = head:VariableDeclarationNoIn tail:(__ "," __ VariableDeclarationNoIn)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][3]); } return result; } VariableDeclaration - = Identifier __ Initialiser? { + = name:Identifier __ value:Initialiser? { return { type: "VariableDeclaration", - name: $1, - value: $3 !== "" ? $3 : null + name: name, + value: value !== "" ? value : null }; } VariableDeclarationNoIn - = Identifier __ InitialiserNoIn? { + = name:Identifier __ value:InitialiserNoIn? { return { type: "VariableDeclaration", - name: $1, - value: $3 !== "" ? $3 : null + name: name, + value: value !== "" ? value : null }; } Initialiser - = "=" (!"=") __ AssignmentExpression { return $4; } + = "=" (!"=") __ expression:AssignmentExpression { return expression; } InitialiserNoIn - = "=" (!"=") __ AssignmentExpressionNoIn { return $4; } + = "=" (!"=") __ expression:AssignmentExpressionNoIn { return expression; } EmptyStatement = ";" { return { type: "EmptyStatement" }; } ExpressionStatement - = !("{" / FunctionToken) Expression EOS { return $2; } + = !("{" / FunctionToken) expression:Expression EOS { return expression; } IfStatement - = IfToken __ "(" __ Expression __ ")" __ Statement (__ ElseToken __ Statement)? { + = IfToken __ + "(" __ condition:Expression __ ")" __ + ifStatement:Statement + elseStatement:(__ ElseToken __ Statement)? { return { type: "IfStatement", - condition: $5, - ifStatement: $9, - elseStatement: $10 !== "" ? $10[3] : null + condition: condition, + ifStatement: ifStatement, + elseStatement: elseStatement !== "" ? elseStatement[3] : null }; } @@ -1168,222 +1222,229 @@ IterationStatement / ForInStatement DoWhileStatement - = DoToken __ Statement __ WhileToken __ "(" __ Expression __ ")" EOS { + = DoToken __ + statement:Statement __ + WhileToken __ "(" __ condition:Expression __ ")" EOS { return { type: "DoWhileStatement", - condition: $9, - statement: $3 + condition: condition, + statement: statement }; } WhileStatement - = WhileToken __ "(" __ Expression __ ")" __ Statement { + = WhileToken __ "(" __ condition:Expression __ ")" __ statement:Statement { return { type: "WhileStatement", - condition: $5, - statement: $9 + condition: condition, + statement: statement }; } ForStatement = ForToken __ "(" __ - ( - VarToken __ VariableDeclarationListNoIn { + initializer:( + VarToken __ declarations:VariableDeclarationListNoIn { return { type: "VariableStatement", - declarations: $3 + declarations: declarations }; } / ExpressionNoIn? ) __ ";" __ - Expression? __ + test:Expression? __ ";" __ - Expression? __ + counter:Expression? __ ")" __ - Statement + statement:Statement { return { type: "ForStatement", - initializer: $5 !== "" ? $5 : null, - test: $9 !== "" ? $9 : null, - counter: $13 !== "" ? $13 : null, - statement: $17 + initializer: initializer !== "" ? initializer : null, + test: test !== "" ? test : null, + counter: counter !== "" ? counter : null, + statement: statement }; } ForInStatement = ForToken __ "(" __ - ( - VarToken __ VariableDeclarationNoIn { return $3; } + iterator:( + VarToken __ declaration:VariableDeclarationNoIn { return declaration; } / LeftHandSideExpression ) __ InToken __ - Expression __ + collection:Expression __ ")" __ - Statement + statement:Statement { return { type: "ForInStatement", - iterator: $5, - collection: $9, - statement: $13 + iterator: iterator, + collection: collection, + statement: statement }; } ContinueStatement = ContinueToken _ - ( - Identifier EOS { return $1; } - / EOSNoLineTerminator { return ""; } + label:( + identifier:Identifier EOS { return identifier; } + / EOSNoLineTerminator { return ""; } ) { return { type: "ContinueStatement", - label: $3 !== "" ? $3 : null + label: label !== "" ? label : null }; } BreakStatement = BreakToken _ - ( - Identifier EOS { return $1; } - / EOSNoLineTerminator { return ""; } + label:( + identifier:Identifier EOS { return identifier; } + / EOSNoLineTerminator { return ""; } ) { return { type: "BreakStatement", - label: $3 !== "" ? $3 : null + label: label !== "" ? label : null }; } ReturnStatement = ReturnToken _ - ( - Expression EOS { return $1; } - / EOSNoLineTerminator { return ""; } + value:( + expression:Expression EOS { return expression; } + / EOSNoLineTerminator { return ""; } ) { return { type: "ReturnStatement", - value: $3 !== "" ? $3 : null + value: value !== "" ? value : null }; } WithStatement - = WithToken __ "(" __ Expression __ ")" __ Statement { + = WithToken __ "(" __ environment:Expression __ ")" __ statement:Statement { return { type: "WithStatement", - environment: $5, - statement: $9 + environment: environment, + statement: statement }; } SwitchStatement - = SwitchToken __ "(" __ Expression __ ")" __ CaseBlock { + = SwitchToken __ "(" __ expression:Expression __ ")" __ clauses:CaseBlock { return { type: "SwitchStatement", - expression: $5, - clauses: $9 + expression: expression, + clauses: clauses }; } CaseBlock - = "{" __ CaseClauses? (__ DefaultClause __ CaseClauses?)? __ "}" { - var clausesBefore = $3 !== "" ? $3 : []; - if ($4 !== "") { - var defaultClause = $4[1]; - var clausesAfter = $4[3] !== "" ? $4[3] : []; + = "{" __ + before:CaseClauses? + defaultAndAfter:(__ DefaultClause __ CaseClauses?)? __ + "}" { + var before = before !== "" ? before : []; + if (defaultAndAfter !== "") { + var defaultClause = defaultAndAfter[1]; + var clausesAfter = defaultAndAfter[3] !== "" + ? defaultAndAfter[3] + : []; } else { var defaultClause = null; var clausesAfter = []; } - return (defaultClause ? clausesBefore.concat(defaultClause) : clausesBefore).concat(clausesAfter); + return (defaultClause ? before.concat(defaultClause) : before).concat(clausesAfter); } CaseClauses - = CaseClause (__ CaseClause)* { - var result = [$1]; - for (var i = 0; i < $2.length; i++) { - result.push($2[i][1]); + = head:CaseClause tail:(__ CaseClause)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][1]); } return result; } CaseClause - = CaseToken __ Expression __ ":" (__ StatementList)? { + = CaseToken __ selector:Expression __ ":" statements:(__ StatementList)? { return { type: "CaseClause", - selector: $3, - statements: $6 !== "" ? $6[1] : [] + selector: selector, + statements: statements !== "" ? statements[1] : [] }; } DefaultClause - = DefaultToken __ ":" (__ StatementList)? { + = DefaultToken __ ":" statements:(__ StatementList)? { return { type: "DefaultClause", - statements: $4 !== "" ? $4[1] : [] + statements: statements !== "" ? statements[1] : [] }; } LabelledStatement - = Identifier __ ":" __ Statement { + = label:Identifier __ ":" __ statement:Statement { return { type: "LabelledStatement", - label: $1, - statement: $5 + label: label, + statement: statement }; } ThrowStatement - = ThrowToken _ Expression EOSNoLineTerminator { + = ThrowToken _ exception:Expression EOSNoLineTerminator { return { type: "ThrowStatement", - exception: $3 + exception: exception }; } TryStatement - = TryToken __ Block __ Catch __ Finally { + = TryToken __ block:Block __ catch_:Catch __ finally_:Finally { return { type: "TryStatement", - block: $3, - "catch": $5, - "finally": $7 + block: block, + "catch": catch_, + "finally": finally_ }; } - / TryToken __ Block __ Catch { + / TryToken __ block:Block __ catch_:Catch { return { type: "TryStatement", - block: $3, - "catch": $5, + block: block, + "catch": catch_, "finally": null }; } - / TryToken __ Block __ Finally { + / TryToken __ block:Block __ finally_:Finally { return { type: "TryStatement", - block: $3, + block: block, "catch": null, - "finally": $5 + "finally": finally_ }; } Catch - = CatchToken __ "(" __ Identifier __ ")" __ Block { + = CatchToken __ "(" __ identifier:Identifier __ ")" __ block:Block { return { type: "Catch", - identifier: $5, - block: $9 + identifier: identifier, + block: block }; } Finally - = FinallyToken __ Block { + = FinallyToken __ block:Block { return { type: "Finally", - block: $3 + block: block }; } @@ -1393,54 +1454,54 @@ DebuggerStatement /* ===== A.5 Functions and Programs ===== */ FunctionDeclaration - = FunctionToken __ Identifier __ - "(" __ FormalParameterList? __ ")" __ - "{" __ FunctionBody __ "}" { + = FunctionToken __ name:Identifier __ + "(" __ params:FormalParameterList? __ ")" __ + "{" __ elements:FunctionBody __ "}" { return { type: "Function", - name: $3, - params: $7 !== "" ? $7 : [], - elements: $13 + name: name, + params: params !== "" ? params : [], + elements: elements }; } FunctionExpression - = FunctionToken __ Identifier? __ - "(" __ FormalParameterList? __ ")" __ - "{" __ FunctionBody __ "}" { + = FunctionToken __ name:Identifier? __ + "(" __ params:FormalParameterList? __ ")" __ + "{" __ elements:FunctionBody __ "}" { return { type: "Function", - name: $3 !== "" ? $3 : null, - params: $7 !== "" ? $7 : [], - elements: $13 + name: name !== "" ? name : null, + params: params !== "" ? params : [], + elements: elements }; } FormalParameterList - = Identifier (__ "," __ Identifier)* { - var result = [$1]; - for (var i = 0; i < $2.length; i++) { - result.push($2[i][3]); + = head:Identifier tail:(__ "," __ Identifier)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][3]); } return result; } FunctionBody - = SourceElements? { return $1 !== "" ? $1 : []; } + = elements:SourceElements? { return elements !== "" ? elements : []; } Program - = SourceElements? { + = elements:SourceElements? { return { type: "Program", - elements: $1 !== "" ? $1 : [] + elements: elements !== "" ? elements : [] }; } SourceElements - = SourceElement (__ SourceElement)* { - var result = [$1]; - for (var i = 0; i < $2.length; i++) { - result.push($2[i][1]); + = head:SourceElement tail:(__ SourceElement)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][1]); } return result; } diff --git a/examples/json.pegjs b/examples/json.pegjs index 6bfa538..0e06fc1 100644 --- a/examples/json.pegjs +++ b/examples/json.pegjs @@ -3,34 +3,34 @@ /* ===== Syntactical Elements ===== */ start - = _ object { return $2; } + = _ object:object { return object; } object - = "{" _ "}" _ { return {}; } - / "{" _ members "}" _ { return $3; } + = "{" _ "}" _ { return {}; } + / "{" _ members:members "}" _ { return members; } members - = pair ("," _ pair)* { + = head:pair tail:("," _ pair)* { var result = {}; - result[$1[0]] = $1[1]; - for (var i = 0; i < $2.length; i++) { - result[$2[i][2][0]] = $2[i][2][1]; + result[head[0]] = head[1]; + for (var i = 0; i < tail.length; i++) { + result[tail[i][2][0]] = tail[i][2][1]; } return result; } pair - = string ":" _ value { return [$1, $4]; } + = name:string ":" _ value:value { return [name, value]; } array - = "[" _ "]" _ { return []; } - / "[" _ elements "]" _ { return $3; } + = "[" _ "]" _ { return []; } + / "[" _ elements:elements "]" _ { return elements; } elements - = value ("," _ value)* { - var result = [$1]; - for (var i = 0; i < $2.length; i++) { - result.push($2[i][2]); + = head:value tail:("," _ value)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][2]); } return result; } @@ -48,11 +48,11 @@ value /* ===== Lexical Elements ===== */ string "string" - = '"' '"' _ { return ""; } - / '"' chars '"' _ { return $2; } + = '"' '"' _ { return ""; } + / '"' chars:chars '"' _ { return chars; } chars - = char+ { return $1.join(""); } + = chars:char+ { return chars.join(""); } char // In the original JSON grammar: "any-Unicode-character-except-"-or-\-or-control-character" @@ -65,33 +65,33 @@ char / "\\n" { return "\n"; } / "\\r" { return "\r"; } / "\\t" { return "\t"; } - / "\\u" hexDigit hexDigit hexDigit hexDigit { - return String.fromCharCode(parseInt("0x" + $2 + $3 + $4 + $5)); + / "\\u" h1:hexDigit h2:hexDigit h3:hexDigit h4:hexDigit { + return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4)); } number "number" - = int frac exp _ { return parseFloat($1 + $2 + $3); } - / int frac _ { return parseFloat($1 + $2); } - / int exp _ { return parseFloat($1 + $2); } - / int _ { return parseFloat($1); } + = int:int frac:frac exp:exp _ { return parseFloat(int + frac + exp); } + / int:int frac:frac _ { return parseFloat(int + frac); } + / int:int exp:exp _ { return parseFloat(int + exp); } + / int:int _ { return parseFloat(int); } int - = digit19 digits { return $1 + $2; } - / digit - / "-" digit19 digits { return $1 + $2 + $3; } - / "-" digit { return $1 + $2; } + = digit19:digit19 digits:digits { return digit19 + digits; } + / digit:digit + / "-" digit19:digit19 digits:digits { return "-" + digit19 + digits; } + / "-" digit:digit { return "-" + digit; } frac - = "." digits { return $1 + $2; } + = "." digits:digits { return "." + digits; } exp - = e digits { return $1 + $2; } + = e:e digits:digits { return e + digits; } digits - = digit+ { return $1.join(""); } + = digits:digit+ { return digits.join(""); } e - = [eE] [+-]? { return $1 + $2; } + = e:[eE] sign:[+-]? { return e + sign; } /* * The following rules are not present in the original JSON gramar, but they are diff --git a/lib/compiler.js b/lib/compiler.js index 0698700..af54255 100644 --- a/lib/compiler.js +++ b/lib/compiler.js @@ -716,7 +716,7 @@ PEG.Compiler = { * In case of sequences, we splat their elements into function arguments * one by one. Example: * - * start: "a" "b" "c" { alert(arguments.length) } // => 3 + * start: a:"a" b:"b" c:"c" { alert(arguments.length) } // => 3 * * This behavior is reflected in this function. */ @@ -724,38 +724,36 @@ PEG.Compiler = { var expressionResultVar = PEG.Compiler.generateUniqueIdentifier("result"); if (node.expression.type === "sequence") { - var params = PEG.ArrayUtils.map( - PEG.ArrayUtils.range(1, node.expression.elements.length + 1), - function(n) { return "$" + n; } - ).join(", "); - - var invocationCode = PEG.Compiler.formatCode( - "(function(${params}) { ${action} }).apply(null, ${expressionResultVar})", - { - params: params, - action: node.action, - expressionResultVar: expressionResultVar + var formalParams = []; + var actualParams = []; + + var elements = node.expression.elements; + var elementsLength = elements.length; + for (var i = 0; i < elementsLength; i++) { + if (elements[i].type === "labeled") { + formalParams.push(elements[i].label); + actualParams.push(expressionResultVar + "[" + i + "]"); } - ); + } + } else if (node.expression.type === "labeled") { + var formalParams = [node.expression.label]; + var actualParams = [expressionResultVar]; } else { - var invocationCode = PEG.Compiler.formatCode( - "(function($1) { ${action} })(${expressionResultVar})", - { - action: node.action, - expressionResultVar: expressionResultVar - } - ); + var formalParams = []; + var actualParams = []; } return PEG.Compiler.formatCode( "${expressionCode}", "var ${resultVar} = ${expressionResultVar} !== null", - " ? ${invocationCode}", + " ? (function(${formalParams}) { ${action} })(${actualParams})", " : null;", { expressionCode: PEG.Compiler.compileNode(node.expression, expressionResultVar), expressionResultVar: expressionResultVar, - invocationCode: invocationCode, + action: node.action, + formalParams: formalParams.join(", "), + actualParams: actualParams.join(", "), resultVar: resultVar } ); diff --git a/lib/metagrammar.js b/lib/metagrammar.js index f7f38a0..324f6e6 100644 --- a/lib/metagrammar.js +++ b/lib/metagrammar.js @@ -85,11 +85,11 @@ PEG.grammarParser = (function(){ this._pos = savedPos0; } var result0 = result1 !== null - ? (function($1, $2) { + ? (function(rules) { var result = {}; - PEG.ArrayUtils.each($2, function(rule) { result[rule.name] = rule; }); + PEG.ArrayUtils.each(rules, function(rule) { result[rule.name] = rule; }); return result; - }).apply(null, result1) + })(result1[1]) : null; @@ -157,14 +157,14 @@ PEG.grammarParser = (function(){ this._pos = savedPos1; } var result5 = result6 !== null - ? (function($1, $2, $3, $4) { + ? (function(name, displayName, expression) { return { type: "rule", - name: $1, - displayName: $2 !== "" ? $2 : null, - expression: $4 + name: name, + displayName: displayName !== "" ? displayName : null, + expression: expression }; - }).apply(null, result6) + })(result6[0], result6[1], result6[3]) : null; @@ -233,10 +233,10 @@ PEG.grammarParser = (function(){ this._pos = savedPos2; } var result13 = result14 !== null - ? (function($1, $2) { - if ($2.length > 0) { - var alternatives = [$1].concat(PEG.ArrayUtils.map( - $2, + ? (function(head, tail) { + if (tail.length > 0) { + var alternatives = [head].concat(PEG.ArrayUtils.map( + tail, function(element) { return element[1]; } )); return { @@ -244,9 +244,9 @@ PEG.grammarParser = (function(){ alternatives: alternatives } } else { - return $1; + return head; } - }).apply(null, result14) + })(result14[0], result14[1]) : null; @@ -289,19 +289,19 @@ PEG.grammarParser = (function(){ this._pos = savedPos4; } var result24 = result25 !== null - ? (function($1, $2) { - var expression = $1.length != 1 + ? (function(elements, action) { + var expression = elements.length != 1 ? { type: "sequence", - elements: $1 + elements: elements } - : $1[0]; + : elements[0]; return { type: "action", expression: expression, - action: $2 + action: action }; - }).apply(null, result25) + })(result25[0], result25[1]) : null; if (result24 !== null) { var result20 = result24; @@ -313,13 +313,13 @@ PEG.grammarParser = (function(){ var result23 = this._parse_labeled(context); } var result21 = result22 !== null - ? (function($1) { - return $1.length != 1 + ? (function(elements) { + return elements.length != 1 ? { type: "sequence", - elements: $1 + elements: elements } - : $1[0]; + : elements[0]; })(result22) : null; if (result21 !== null) { @@ -370,13 +370,13 @@ PEG.grammarParser = (function(){ this._pos = savedPos5; } var result31 = result32 !== null - ? (function($1, $2, $3) { + ? (function(label, expression) { return { type: "labeled", - label: $1, - expression: $3 + label: label, + expression: expression }; - }).apply(null, result32) + })(result32[0], result32[2]) : null; if (result31 !== null) { var result29 = result31; @@ -424,7 +424,12 @@ PEG.grammarParser = (function(){ this._pos = savedPos7; } var result42 = result43 !== null - ? (function($1, $2) { return { type: "and_predicate", expression: $2 }; }).apply(null, result43) + ? (function(expression) { + return { + type: "and_predicate", + expression: expression + }; + })(result43[1]) : null; if (result42 !== null) { var result36 = result42; @@ -444,7 +449,12 @@ PEG.grammarParser = (function(){ this._pos = savedPos6; } var result38 = result39 !== null - ? (function($1, $2) { return { type: "not_predicate", expression: $2 }; }).apply(null, result39) + ? (function(expression) { + return { + type: "not_predicate", + expression: expression + }; + })(result39[1]) : null; if (result38 !== null) { var result36 = result38; @@ -493,7 +503,12 @@ PEG.grammarParser = (function(){ this._pos = savedPos10; } var result56 = result57 !== null - ? (function($1, $2) { return { type: "optional", expression: $1}; }).apply(null, result57) + ? (function(expression) { + return { + type: "optional", + expression: expression + }; + })(result57[0]) : null; if (result56 !== null) { var result46 = result56; @@ -513,7 +528,12 @@ PEG.grammarParser = (function(){ this._pos = savedPos9; } var result52 = result53 !== null - ? (function($1, $2) { return { type: "zero_or_more", expression: $1}; }).apply(null, result53) + ? (function(expression) { + return { + type: "zero_or_more", + expression: expression + }; + })(result53[0]) : null; if (result52 !== null) { var result46 = result52; @@ -533,7 +553,12 @@ PEG.grammarParser = (function(){ this._pos = savedPos8; } var result48 = result49 !== null - ? (function($1, $2) { return { type: "one_or_more", expression: $1}; }).apply(null, result49) + ? (function(expression) { + return { + type: "one_or_more", + expression: expression + }; + })(result49[0]) : null; if (result48 !== null) { var result46 = result48; @@ -624,21 +649,31 @@ PEG.grammarParser = (function(){ this._pos = savedPos12; } var result71 = result72 !== null - ? (function($1, $2) { return { type: "rule_ref", name: $1 }; }).apply(null, result72) + ? (function(name) { + return { + type: "rule_ref", + name: name + }; + })(result72[0]) : null; if (result71 !== null) { var result60 = result71; } else { var result70 = this._parse_literal(context); var result69 = result70 !== null - ? (function($1) { return { type: "literal", value: $1 }; })(result70) + ? (function(value) { + return { + type: "literal", + value: value + }; + })(result70) : null; if (result69 !== null) { var result60 = result69; } else { var result68 = this._parse_dot(context); var result67 = result68 !== null - ? (function($1) { return { type: "any" }; })(result68) + ? (function() { return { type: "any" }; })() : null; if (result67 !== null) { var result60 = result67; @@ -668,7 +703,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos11; } var result61 = result62 !== null - ? (function($1, $2, $3) { return $2; }).apply(null, result62) + ? (function(expression) { return expression; })(result62[1]) : null; if (result61 !== null) { var result60 = result61; @@ -716,7 +751,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos15; } var result80 = result81 !== null - ? (function($1, $2) { return $1.substr(1, $1.length - 2); }).apply(null, result81) + ? (function(braced) { return braced.substr(1, braced.length - 2); })(result81[0]) : null; context.reportMatchFailures = savedReportMatchFailures; if (context.reportMatchFailures && result80 === null) { @@ -803,7 +838,9 @@ PEG.grammarParser = (function(){ this._pos = savedPos16; } var result84 = result85 !== null - ? (function($1, $2, $3) { return $1 + $2.join("") + $3; }).apply(null, result85) + ? (function(parts) { + return "{" + parts.join("") + "}"; + })(result85[1]) : null; @@ -837,7 +874,7 @@ PEG.grammarParser = (function(){ var result93 = null; } var result92 = result93 !== null - ? (function($1) { return $1.join(""); })(result93) + ? (function(chars) { return chars.join(""); })(result93) : null; @@ -913,7 +950,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos17; } var result96 = result97 !== null - ? (function($1, $2) { return $1; }).apply(null, result97) + ? (function() { return "="; })() : null; @@ -959,7 +996,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos18; } var result100 = result101 !== null - ? (function($1, $2) { return $1; }).apply(null, result101) + ? (function() { return ":"; })() : null; @@ -1005,7 +1042,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos19; } var result104 = result105 !== null - ? (function($1, $2) { return $1; }).apply(null, result105) + ? (function() { return "/"; })() : null; @@ -1051,7 +1088,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos20; } var result108 = result109 !== null - ? (function($1, $2) { return $1; }).apply(null, result109) + ? (function() { return "&"; })() : null; @@ -1097,7 +1134,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos21; } var result112 = result113 !== null - ? (function($1, $2) { return $1; }).apply(null, result113) + ? (function() { return "!"; })() : null; @@ -1143,7 +1180,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos22; } var result116 = result117 !== null - ? (function($1, $2) { return $1; }).apply(null, result117) + ? (function() { return "?"; })() : null; @@ -1189,7 +1226,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos23; } var result120 = result121 !== null - ? (function($1, $2) { return $1; }).apply(null, result121) + ? (function() { return "*"; })() : null; @@ -1235,7 +1272,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos24; } var result124 = result125 !== null - ? (function($1, $2) { return $1; }).apply(null, result125) + ? (function() { return "+"; })() : null; @@ -1281,7 +1318,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos25; } var result128 = result129 !== null - ? (function($1, $2) { return $1; }).apply(null, result129) + ? (function() { return "("; })() : null; @@ -1327,7 +1364,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos26; } var result132 = result133 !== null - ? (function($1, $2) { return $1; }).apply(null, result133) + ? (function() { return ")"; })() : null; @@ -1373,7 +1410,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos27; } var result136 = result137 !== null - ? (function($1, $2) { return $1; }).apply(null, result137) + ? (function() { return "."; })() : null; @@ -1526,9 +1563,9 @@ PEG.grammarParser = (function(){ this._pos = savedPos28; } var result140 = result141 !== null - ? (function($1, $2, $3) { - return $1 + $2.join(""); - }).apply(null, result141) + ? (function(head, tail) { + return head + tail.join(""); + })(result141[0], result141[1]) : null; context.reportMatchFailures = savedReportMatchFailures; if (context.reportMatchFailures && result140 === null) { @@ -1579,7 +1616,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos29; } var result153 = result154 !== null - ? (function($1, $2) { return $1; }).apply(null, result154) + ? (function(literal) { return literal; })(result154[0]) : null; context.reportMatchFailures = savedReportMatchFailures; if (context.reportMatchFailures && result153 === null) { @@ -1646,7 +1683,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos30; } var result159 = result160 !== null - ? (function($1, $2, $3) { return $2.join(""); }).apply(null, result160) + ? (function(chars) { return chars.join(""); })(result160[1]) : null; @@ -1785,7 +1822,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos31; } var result172 = result173 !== null - ? (function($1, $2) { return $2; }).apply(null, result173) + ? (function(char_) { return char_; })(result173[1]) : null; @@ -1850,7 +1887,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos33; } var result180 = result181 !== null - ? (function($1, $2, $3) { return $2.join(""); }).apply(null, result181) + ? (function(chars) { return chars.join(""); })(result181[1]) : null; @@ -1989,7 +2026,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos34; } var result193 = result194 !== null - ? (function($1, $2) { return $2; }).apply(null, result194) + ? (function(char_) { return char_; })(result194[1]) : null; @@ -2096,23 +2133,25 @@ PEG.grammarParser = (function(){ this._pos = savedPos36; } var result201 = result202 !== null - ? (function($1, $2, $3, $4, $5) { - parts = PEG.ArrayUtils.map($3, function(part) { return part.data; }); + ? (function(inverted, parts) { + partsConverted = PEG.ArrayUtils.map(parts, function(part) { + return part.data; + }); rawText = "[" - + $2 - + PEG.ArrayUtils.map($3, function(part) { + + inverted + + PEG.ArrayUtils.map(parts, function(part) { return part.rawText; }).join("") + "]"; return { type: "class", - inverted: $2 === "^", - parts: parts, + inverted: inverted === "^", + parts: partsConverted, // FIXME: Get the raw text from the input directly. rawText: rawText }; - }).apply(null, result202) + })(result202[1], result202[2]) : null; context.reportMatchFailures = savedReportMatchFailures; if (context.reportMatchFailures && result201 === null) { @@ -2166,19 +2205,19 @@ PEG.grammarParser = (function(){ this._pos = savedPos37; } var result212 = result213 !== null - ? (function($1, $2, $3) { - if ($1.data.charCodeAt(0) > $3.data.charCodeAt(0)) { + ? (function(begin, end) { + if (begin.data.charCodeAt(0) > end.data.charCodeAt(0)) { throw new this.SyntaxError( - "Invalid character range: " + $1.rawText + "-" + $3.rawText + "." + "Invalid character range: " + begin.rawText + "-" + end.rawText + "." ); } return { - data: [$1.data, $3.data], + data: [begin.data, end.data], // FIXME: Get the raw text from the input directly. - rawText: $1.rawText + "-" + $3.rawText + rawText: begin.rawText + "-" + end.rawText } - }).apply(null, result213) + })(result213[0], result213[2]) : null; @@ -2203,11 +2242,11 @@ PEG.grammarParser = (function(){ var result218 = this._parse_bracketDelimitedCharacter(context); var result217 = result218 !== null - ? (function($1) { + ? (function(char_) { return { - data: $1, + data: char_, // FIXME: Get the raw text from the input directly. - rawText: PEG.RegExpUtils.quoteForClass($1) + rawText: PEG.RegExpUtils.quoteForClass(char_) }; })(result218) : null; @@ -2348,7 +2387,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos38; } var result226 = result227 !== null - ? (function($1, $2) { return $2; }).apply(null, result227) + ? (function(char_) { return char_; })(result227[1]) : null; @@ -2454,15 +2493,15 @@ PEG.grammarParser = (function(){ this._pos = savedPos40; } var result234 = result235 !== null - ? (function($1, $2, $3) { - return $3 + ? (function(char_) { + return char_ .replace("b", "\b") .replace("f", "\f") .replace("n", "\n") .replace("r", "\r") .replace("t", "\t") .replace("v", "\x0B") // IE does not recognize "\v". - }).apply(null, result235) + })(result235[2]) : null; @@ -2518,7 +2557,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos42; } var result244 = result245 !== null - ? (function($1, $2) { return "\0"; }).apply(null, result245) + ? (function() { return "\0"; })() : null; @@ -2570,9 +2609,9 @@ PEG.grammarParser = (function(){ this._pos = savedPos44; } var result249 = result250 !== null - ? (function($1, $2, $3) { - return String.fromCharCode(parseInt("0x" + $2 + $3)); - }).apply(null, result250) + ? (function(h1, h2) { + return String.fromCharCode(parseInt("0x" + h1 + h2)); + })(result250[1], result250[2]) : null; @@ -2636,9 +2675,9 @@ PEG.grammarParser = (function(){ this._pos = savedPos45; } var result254 = result255 !== null - ? (function($1, $2, $3, $4, $5) { - return String.fromCharCode(parseInt("0x" + $2 + $3 + $4 + $5)); - }).apply(null, result255) + ? (function(h1, h2, h3, h4) { + return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4)); + })(result255[1], result255[2], result255[3], result255[4]) : null; @@ -2684,7 +2723,7 @@ PEG.grammarParser = (function(){ this._pos = savedPos46; } var result261 = result262 !== null - ? (function($1, $2) { return $2; }).apply(null, result262) + ? (function(eol) { return eol; })(result262[1]) : null; diff --git a/lib/metagrammar.pegjs b/lib/metagrammar.pegjs index 27acd09..9fb170a 100644 --- a/lib/metagrammar.pegjs +++ b/lib/metagrammar.pegjs @@ -1,17 +1,17 @@ grammar - = __ rule+ { + = __ rules:rule+ { var result = {}; - PEG.ArrayUtils.each($2, function(rule) { result[rule.name] = rule; }); + PEG.ArrayUtils.each(rules, function(rule) { result[rule.name] = rule; }); return result; } rule - = identifier (literal / "") equals expression { + = name:identifier displayName:(literal / "") equals expression:expression { return { type: "rule", - name: $1, - displayName: $2 !== "" ? $2 : null, - expression: $4 + name: name, + displayName: displayName !== "" ? displayName : null, + expression: expression }; } @@ -19,10 +19,10 @@ expression = choice choice - = sequence (slash sequence)* { - if ($2.length > 0) { - var alternatives = [$1].concat(PEG.ArrayUtils.map( - $2, + = head:sequence tail:(slash sequence)* { + if (tail.length > 0) { + var alternatives = [head].concat(PEG.ArrayUtils.map( + tail, function(element) { return element[1]; } )); return { @@ -30,86 +30,123 @@ choice alternatives: alternatives } } else { - return $1; + return head; } } sequence - = labeled* action { - var expression = $1.length != 1 + = elements:labeled* action:action { + var expression = elements.length != 1 ? { type: "sequence", - elements: $1 + elements: elements } - : $1[0]; + : elements[0]; return { type: "action", expression: expression, - action: $2 + action: action }; } - / labeled* { - return $1.length != 1 + / elements:labeled* { + return elements.length != 1 ? { type: "sequence", - elements: $1 + elements: elements } - : $1[0]; + : elements[0]; } labeled - = identifier colon prefixed { + = label:identifier colon expression:prefixed { return { type: "labeled", - label: $1, - expression: $3 + label: label, + expression: expression }; } / prefixed prefixed - = and suffixed { return { type: "and_predicate", expression: $2 }; } - / not suffixed { return { type: "not_predicate", expression: $2 }; } + = and expression:suffixed { + return { + type: "and_predicate", + expression: expression + }; + } + / not expression:suffixed { + return { + type: "not_predicate", + expression: expression + }; + } / suffixed suffixed - = primary question { return { type: "optional", expression: $1}; } - / primary star { return { type: "zero_or_more", expression: $1}; } - / primary plus { return { type: "one_or_more", expression: $1}; } + = expression:primary question { + return { + type: "optional", + expression: expression + }; + } + / expression:primary star { + return { + type: "zero_or_more", + expression: expression + }; + } + / expression:primary plus { + return { + type: "one_or_more", + expression: expression + }; + } / primary primary - = identifier !(( literal / "") equals) { return { type: "rule_ref", name: $1 }; } - / literal { return { type: "literal", value: $1 }; } - / dot { return { type: "any" }; } + = name:identifier !(( literal / "") equals) { + return { + type: "rule_ref", + name: name + }; + } + / value:literal { + return { + type: "literal", + value: value + }; + } + / dot { return { type: "any" }; } / class - / lparen expression rparen { return $2; } + / lparen expression:expression rparen { return expression; } /* "Lexical" elements */ action "action" - = braced __ { return $1.substr(1, $1.length - 2); } + = braced:braced __ { return braced.substr(1, braced.length - 2); } braced - = "{" (braced / nonBraceCharacter)* "}" { return $1 + $2.join("") + $3; } + = "{" parts:(braced / nonBraceCharacter)* "}" { + return "{" + parts.join("") + "}"; + } nonBraceCharacters - = nonBraceCharacter+ { return $1.join(""); } + = chars:nonBraceCharacter+ { return chars.join(""); } nonBraceCharacter = [^{}] -equals = "=" __ { return $1; } -colon = ":" __ { return $1; } -slash = "/" __ { return $1; } -and = "&" __ { return $1; } -not = "!" __ { return $1; } -question = "?" __ { return $1; } -star = "*" __ { return $1; } -plus = "+" __ { return $1; } -lparen = "(" __ { return $1; } -rparen = ")" __ { return $1; } -dot = "." __ { return $1; } +equals = "=" __ { return "="; } +colon = ":" __ { return ":"; } +slash = "/" __ { return "/"; } +and = "&" __ { return "&"; } +not = "!" __ { return "!"; } +question = "?" __ { return "?"; } +star = "*" __ { return "*"; } +plus = "+" __ { return "+"; } +lparen = "(" __ { return "("; } +rparen = ")" __ { return ")"; } +dot = "." __ { return "."; } /* * Modelled after ECMA-262, 5th ed., 7.6, but much simplified: @@ -127,8 +164,8 @@ dot = "." __ { return $1; } * easier, there is no "philosophical" reason behind them. */ identifier "identifier" - = (letter / "_" / "$") (letter / digit / "_" / "$")* __ { - return $1 + $2.join(""); + = head:(letter / "_" / "$") tail:(letter / digit / "_" / "$")* __ { + return head + tail.join(""); } /* @@ -136,10 +173,10 @@ identifier "identifier" * vaguely). */ literal "literal" - = (doubleQuotedLiteral / singleQuotedLiteral) __ { return $1; } + = literal:(doubleQuotedLiteral / singleQuotedLiteral) __ { return literal; } doubleQuotedLiteral - = '"' doubleQuotedCharacter* '"' { return $2.join(""); } + = '"' chars:doubleQuotedCharacter* '"' { return chars.join(""); } doubleQuotedCharacter = simpleDoubleQuotedCharacter @@ -150,10 +187,10 @@ doubleQuotedCharacter / eolEscapeSequence simpleDoubleQuotedCharacter - = !('"' / "\\" / eolChar) . { return $2; } + = !('"' / "\\" / eolChar) char_:. { return char_; } singleQuotedLiteral - = "'" singleQuotedCharacter* "'" { return $2.join(""); } + = "'" chars:singleQuotedCharacter* "'" { return chars.join(""); } singleQuotedCharacter = simpleSingleQuotedCharacter @@ -164,48 +201,50 @@ singleQuotedCharacter / eolEscapeSequence simpleSingleQuotedCharacter - = !("'" / "\\" / eolChar) . { return $2; } + = !("'" / "\\" / eolChar) char_:. { return char_; } class "character class" - = "[" "^"? (classCharacterRange / classCharacter)* "]" __ { - parts = PEG.ArrayUtils.map($3, function(part) { return part.data; }); + = "[" inverted:"^"? parts:(classCharacterRange / classCharacter)* "]" __ { + partsConverted = PEG.ArrayUtils.map(parts, function(part) { + return part.data; + }); rawText = "[" - + $2 - + PEG.ArrayUtils.map($3, function(part) { + + inverted + + PEG.ArrayUtils.map(parts, function(part) { return part.rawText; }).join("") + "]"; return { type: "class", - inverted: $2 === "^", - parts: parts, + inverted: inverted === "^", + parts: partsConverted, // FIXME: Get the raw text from the input directly. rawText: rawText }; } classCharacterRange - = classCharacter "-" classCharacter { - if ($1.data.charCodeAt(0) > $3.data.charCodeAt(0)) { + = begin:classCharacter "-" end:classCharacter { + if (begin.data.charCodeAt(0) > end.data.charCodeAt(0)) { throw new this.SyntaxError( - "Invalid character range: " + $1.rawText + "-" + $3.rawText + "." + "Invalid character range: " + begin.rawText + "-" + end.rawText + "." ); } return { - data: [$1.data, $3.data], + data: [begin.data, end.data], // FIXME: Get the raw text from the input directly. - rawText: $1.rawText + "-" + $3.rawText + rawText: begin.rawText + "-" + end.rawText } } classCharacter - = bracketDelimitedCharacter { + = char_:bracketDelimitedCharacter { return { - data: $1, + data: char_, // FIXME: Get the raw text from the input directly. - rawText: PEG.RegExpUtils.quoteForClass($1) + rawText: PEG.RegExpUtils.quoteForClass(char_) }; } @@ -218,11 +257,11 @@ bracketDelimitedCharacter / eolEscapeSequence simpleBracketDelimitedCharacter - = !("]" / "\\" / eolChar) . { return $2; } + = !("]" / "\\" / eolChar) char_:. { return char_; } simpleEscapeSequence - = "\\" !(digit / "x" / "u" / eolChar) . { - return $3 + = "\\" !(digit / "x" / "u" / eolChar) char_:. { + return char_ .replace("b", "\b") .replace("f", "\f") .replace("n", "\n") @@ -235,17 +274,17 @@ zeroEscapeSequence = "\\0" !digit { return "\0"; } hexEscapeSequence - = "\\x" hexDigit hexDigit { - return String.fromCharCode(parseInt("0x" + $2 + $3)); + = "\\x" h1:hexDigit h2:hexDigit { + return String.fromCharCode(parseInt("0x" + h1 + h2)); } unicodeEscapeSequence - = "\\u" hexDigit hexDigit hexDigit hexDigit { - return String.fromCharCode(parseInt("0x" + $2 + $3 + $4 + $5)); + = "\\u" h1:hexDigit h2:hexDigit h3:hexDigit h4:hexDigit { + return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4)); } eolEscapeSequence - = "\\" eol { return $2; } + = "\\" eol:eol { return eol; } digit = [0-9] diff --git a/test/compiler-test.js b/test/compiler-test.js index 34aadd9..8e2a3bb 100644 --- a/test/compiler-test.js +++ b/test/compiler-test.js @@ -342,33 +342,41 @@ test("one or more expressions", function() { }); test("actions", function() { - var singleMatchParser = PEG.buildParser( - 'start = "a" { return Array.prototype.slice.call(arguments).join("").toUpperCase(); }' + var singleElementUnlabeledParser = PEG.buildParser( + 'start = "a" { return arguments.length; }' ); - parses(singleMatchParser, "a", "A"); + parses(singleElementUnlabeledParser, "a", 0); - var multiMatchParser = PEG.buildParser( - 'start = "a" "b" "c" { return Array.prototype.slice.call(arguments).join("").toUpperCase(); }' + var singleElementLabeledParser = PEG.buildParser( + 'start = a:"a" { return [arguments.length, a]; }' ); - parses(multiMatchParser, "abc", "ABC"); + parses(singleElementLabeledParser, "a", [1, "a"]); - var innerMatchParser = PEG.buildParser( - 'start = "a" ("b" "c" "d" { return Array.prototype.slice.call(arguments).join("").toUpperCase(); }) "e"' + var multiElementUnlabeledParser = PEG.buildParser( + 'start = "a" "b" "c" { return arguments.length; }' ); - parses(innerMatchParser, "abcde", ["a", "BCD", "e"]); + parses(multiElementUnlabeledParser, "abc", 0); + + var multiElementLabeledParser = PEG.buildParser( + 'start = a:"a" "b" c:"c" { return [arguments.length, a, c]; }' + ); + parses(multiElementLabeledParser, "abc", [2, "a", "c"]); + + var innerElementsUnlabeledParser = PEG.buildParser( + 'start = "a" ("b" "c" "d" { return arguments.length; }) "e"' + ); + parses(innerElementsUnlabeledParser, "abcde", ["a", 0, "e"]); + + var innerElementsLabeledParser = PEG.buildParser( + 'start = "a" (b:"b" "c" d:"d" { return [arguments.length, b, d]; }) "e"' + ); + parses(innerElementsLabeledParser, "abcde", ["a", [2, "b", "d"], "e"]); /* Test that the action is not called when its expression does not match. */ var notAMatchParser = PEG.buildParser( 'start = "a" { ok(false, "action got called when it should not be"); }' ); doesNotParse(notAMatchParser, "b"); - - var variablesParser = PEG.buildParser([ - 'start = "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" {', - ' return [$1, $2, $3, $4, $5, $6, $7, $8, $9, $10].join("").toUpperCase();', - ' }' - ].join("\n")); - parses(variablesParser, "abcdefghij", "ABCDEFGHIJ"); }); test("rule references", function() { @@ -580,9 +588,9 @@ test("error messages", function() { test("error positions", function() { var parser = PEG.buildParser([ - 'start = line (("\\r" / "\\n" / "\\u2028" / "\\u2029")+ line)*', - 'line = digit (" "+ digit)*', - 'digit = [0-9]+ { return $1.join(""); }' + 'start = line (("\\r" / "\\n" / "\\u2028" / "\\u2029")+ line)*', + 'line = digits (" "+ digits)*', + 'digits = digits:[0-9]+ { return digits.join(""); }' ].join("\n")); doesNotParseWithPos(parser, "a", 1, 1); @@ -611,21 +619,21 @@ test("arithmetics", function() { * Expr ← Sum */ var parser = PEG.buildParser([ - 'Value = [0-9]+ { return parseInt($1.join("")); }', - ' / "(" Expr ")" { return $2; }', - 'Product = Value (("*" / "/") Value)* {', - ' var result = $1;', - ' for (var i = 0; i < $2.length; i++) {', - ' if ($2[i][0] == "*") { result *= $2[i][1]; }', - ' if ($2[i][0] == "/") { result /= $2[i][1]; }', + 'Value = digits:[0-9]+ { return parseInt(digits.join("")); }', + ' / "(" expr:Expr ")" { return expr; }', + 'Product = head:Value tail:(("*" / "/") Value)* {', + ' var result = head;', + ' for (var i = 0; i < tail.length; i++) {', + ' if (tail[i][0] == "*") { result *= tail[i][1]; }', + ' if (tail[i][0] == "/") { result /= tail[i][1]; }', ' }', ' return result;', ' }', - 'Sum = Product (("+" / "-") Product)* {', - ' var result = $1;', - ' for (var i = 0; i < $2.length; i++) {', - ' if ($2[i][0] == "+") { result += $2[i][1]; }', - ' if ($2[i][0] == "-") { result -= $2[i][1]; }', + 'Sum = head:Product tail:(("+" / "-") Product)* {', + ' var result = head;', + ' for (var i = 0; i < tail.length; i++) {', + ' if (tail[i][0] == "+") { result += tail[i][1]; }', + ' if (tail[i][0] == "-") { result -= tail[i][1]; }', ' }', ' return result;', ' }', @@ -667,9 +675,9 @@ test("non-context-free language", function() { * B ← b B? c */ var parser = PEG.buildParser([ - 'S = &(A "c") "a"+ B !("a" / "b" / "c") { return $2.join("") + $3; }', - 'A = "a" A? "b" { return $1 + $2 + $3; }', - 'B = "b" B? "c" { return $1 + $2 + $3; }', + 'S = &(A "c") a:"a"+ B:B !("a" / "b" / "c") { return a.join("") + B; }', + 'A = a:"a" A:A? b:"b" { return a + A + b; }', + 'B = b:"b" B:B? c:"c" { return b + B + c; }', ].join("\n"), "S"); parses(parser, "abc", "abc"); @@ -693,9 +701,9 @@ test("nested comments", function() { var parser = PEG.buildParser([ 'Begin = "(*"', 'End = "*)"', - 'C = Begin N* End { return $1 + $2.join("") + $3; }', + 'C = begin:Begin ns:N* end:End { return begin + ns.join("") + end; }', 'N = C', - ' / (!Begin !End Z) { return $3; }', + ' / !Begin !End z:Z { return z; }', 'Z = .' ].join("\n"), "C");