Use labeled expressions and variables instead of $1, $2, etc.

Labeled expressions lead to more maintainable code and also will allow
certain optimizations (we can ignore results of expressions not passed
to the actions).

This does not speed up the benchmark suite execution statistically
significantly on V8.

Detailed results (benchmark suite totals):

---------------------------------
 Test #     Before       After
---------------------------------
      1   28.43 kB/s   28.46 kB/s
      2   28.38 kB/s   28.56 kB/s
      3   28.22 kB/s   28.58 kB/s
      4   28.76 kB/s   28.55 kB/s
      5   28.57 kB/s   28.48 kB/s
---------------------------------
Average   28.47 kB/s   28.53 kB/s
---------------------------------

Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.55 Safari/533.4
redux
David Majda 15 years ago
parent 52704593cd
commit ee8c121676

@ -7,16 +7,16 @@ start
= additive = additive
additive additive
= multiplicative "+" additive { return $1 + $3; } = left:multiplicative "+" right:additive { return left + right; }
/ multiplicative / multiplicative
multiplicative multiplicative
= primary "*" multiplicative { return $1 * $3; } = left:primary "*" right:multiplicative { return left * right; }
/ primary / primary
primary primary
= integer = integer
/ "(" additive ")" { return $2; } / "(" additive:additive ")" { return additive; }
integer "integer" integer "integer"
= [0-9]+ { return parseInt($1.join(""), 10); } = digits:[0-9]+ { return parseInt(digits.join(""), 10); }

@ -15,106 +15,114 @@
/* ===== Syntactical Elements ===== */ /* ===== Syntactical Elements ===== */
start start
= stylesheet comment* { return $1; } = stylesheet:stylesheet comment* { return stylesheet; }
stylesheet stylesheet
= (CHARSET_SYM STRING ";")? (S / CDO / CDC)* = charset:(CHARSET_SYM STRING ";")? (S / CDO / CDC)*
(import (CDO S* / CDC S*)*)* imports:(import (CDO S* / CDC S*)*)*
((ruleset / media / page) (CDO S* / CDC S*)*)* { rules:((ruleset / media / page) (CDO S* / CDC S*)*)* {
var imports = []; var importsConverted = [];
for (var i = 0; i < $3.length; i++) { for (var i = 0; i < imports.length; i++) {
imports.push($3[i][0]); importsConverted.push(imports[i][0]);
} }
var rules = []; var rulesConverted = [];
for (i = 0; i < $4.length; i++) { for (i = 0; i < rules.length; i++) {
rules.push($4[i][0]); rulesConverted.push(rules[i][0]);
} }
return { return {
type: "stylesheet", type: "stylesheet",
charset: $1 !== "" ? $1[1] : null, charset: charset !== "" ? charset[1] : null,
imports: imports, imports: importsConverted,
rules: rules rules: rulesConverted
}; };
} }
import import
= IMPORT_SYM S* (STRING / URI) S* media_list? ";" S* { = IMPORT_SYM S* href:(STRING / URI) S* media:media_list? ";" S* {
return { return {
type: "import_rule", type: "import_rule",
href: $3, href: href,
media: $5 !== "" ? $5 : [] media: media !== "" ? media : []
}; };
} }
media media
= MEDIA_SYM S* media_list "{" S* ruleset* "}" S* { = MEDIA_SYM S* media:media_list "{" S* rules:ruleset* "}" S* {
return { return {
type: "media_rule", type: "media_rule",
media: $3, media: media,
rules: $6 rules: rules
}; };
} }
media_list media_list
= medium ("," S* medium)* { = head:medium tail:("," S* medium)* {
var result = [$1]; var result = [head];
for (var i = 0; i < $2.length; i++) { for (var i = 0; i < tail.length; i++) {
result.push($2[i][2]); result.push(tail[i][2]);
} }
return result; return result;
} }
medium medium
= IDENT S* { return $1; } = ident:IDENT S* { return ident; }
page page
= PAGE_SYM S* pseudo_page? "{" S* declaration? (";" S* declaration?)* "}" S* { = PAGE_SYM S* qualifier:pseudo_page?
var declarations = $6 !== "" ? [$6] : []; "{" S*
for (var i = 0; i < $7.length; i++) { declarationsHead:declaration?
if ($7[i][2] !== "") { declarationsTail:(";" S* declaration?)*
declarations.push($7[i][2]); "}" S* {
var declarations = declarationsHead !== "" ? [declarationsHead] : [];
for (var i = 0; i < declarationsTail.length; i++) {
if (declarationsTail[i][2] !== "") {
declarations.push(declarationsTail[i][2]);
} }
} }
return { return {
type: "page_rule", type: "page_rule",
qualifier: $3 !== "" ? $3 : null, qualifier: qualifier !== "" ? qualifier : null,
declarations: declarations declarations: declarations
}; };
} }
pseudo_page pseudo_page
= ":" IDENT S* { return $2; } = ":" ident:IDENT S* { return ident; }
operator operator
= "/" S* { return $1; } = "/" S* { return "/"; }
/ "," S* { return $1; } / "," S* { return ","; }
combinator combinator
= "+" S* { return $1; } = "+" S* { return "+"; }
/ ">" S* { return $1; } / ">" S* { return ">"; }
unary_operator unary_operator
= "+" = "+"
/ "-" / "-"
property property
= IDENT S* { return $1; } = ident:IDENT S* { return ident; }
ruleset ruleset
= selector ("," S* selector)* = selectorsHead:selector
"{" S* declaration? (";" S* declaration?)* "}" S* { selectorsTail:("," S* selector)*
var selectors = [$1]; "{" S*
for (var i = 0; i < $2.length; i++) { declarationsHead:declaration?
selectors.push($2[i][2]); declarationsTail:(";" S* declaration?)*
"}" S* {
var selectors = [selectorsHead];
for (var i = 0; i < selectorsTail.length; i++) {
selectors.push(selectorsTail[i][2]);
} }
var declarations = $5 !== "" ? [$5] : []; var declarations = declarationsHead !== "" ? [declarationsHead] : [];
for (i = 0; i < $6.length; i++) { for (i = 0; i < declarationsTail.length; i++) {
if ($6[i][2] !== "") { if (declarationsTail[i][2] !== "") {
declarations.push($6[i][2]); declarations.push(declarationsTail[i][2]);
} }
} }
@ -126,40 +134,40 @@ ruleset
} }
selector selector
= simple_selector S* combinator selector { = left:simple_selector S* combinator:combinator right:selector {
return { return {
type: "selector", type: "selector",
combinator: $3, combinator: combinator,
left: $1, left: left,
right: $4 right: right
}; };
} }
/ simple_selector S* selector { / left:simple_selector S* right:selector {
return { return {
type: "selector", type: "selector",
combinator: " ", combinator: " ",
left: $1, left: left,
right: $3 right: right
}; };
} }
/ simple_selector S* { return $1; } / selector:simple_selector S* { return selector; }
simple_selector simple_selector
= element_name = element:element_name
( qualifiers:(
HASH { return { type: "ID selector", id: $1.substr(1) }; } id:HASH { return { type: "ID selector", id: id.substr(1) }; }
/ class / class
/ attrib / attrib
/ pseudo / pseudo
)* { )* {
return { return {
type: "simple_selector", type: "simple_selector",
element: $1, element: element,
qualifiers: $2 qualifiers: qualifiers
}; };
} }
/ ( / qualifiers:(
HASH { return { type: "ID selector", id: $1.substr(1) }; } id:HASH { return { type: "ID selector", id: id.substr(1) }; }
/ class / class
/ attrib / attrib
/ pseudo / pseudo
@ -167,34 +175,40 @@ simple_selector
return { return {
type: "simple_selector", type: "simple_selector",
element: "*", element: "*",
qualifiers: $1 qualifiers: qualifiers
}; };
} }
class class
= "." IDENT { return { type: "class_selector", "class": $2 }; } = "." class:IDENT { return { type: "class_selector", "class": class }; }
element_name element_name
= IDENT / '*' = IDENT / '*'
attrib attrib
= "[" S* IDENT S* (('=' / INCLUDES / DASHMATCH) S* (IDENT / STRING) S*)? "]" { = "[" S*
attribute:IDENT S*
operatorAndValue:(
('=' / INCLUDES / DASHMATCH) S*
(IDENT / STRING) S*
)?
"]" {
return { return {
type: "attribute_selector", type: "attribute_selector",
attribute: $3, attribute: attribute,
operator: $5 !== "" ? $5[0] : null, operator: operatorAndValue !== "" ? operatorAndValue[0] : null,
value: $5 !== "" ? $5[2] : null value: operatorAndValue !== "" ? operatorAndValue[2] : null
}; };
} }
pseudo pseudo
= ":" = ":"
( value:(
FUNCTION S* (IDENT S*)? ")" { name:FUNCTION S* params:(IDENT S*)? ")" {
return { return {
type: "function", type: "function",
name: $1, name: name,
params: $3 !== "" ? [$3[0]] : [] params: params !== "" ? [params[0]] : []
}; };
} }
/ IDENT / IDENT
@ -206,17 +220,17 @@ pseudo
*/ */
return { return {
type: "pseudo_selector", type: "pseudo_selector",
value: $2 value: value
}; };
} }
declaration declaration
= property ":" S* expr prio? { = property:property ":" S* expression:expr important:prio? {
return { return {
type: "declaration", type: "declaration",
property: $1, property: property,
expression: $4, expression: expression,
important: $5 !== "" ? true : false important: important !== "" ? true : false
}; };
} }
@ -224,22 +238,22 @@ prio
= IMPORTANT_SYM S* = IMPORTANT_SYM S*
expr expr
= term (operator? term)* { = head:term tail:(operator? term)* {
var result = $1; var result = head;
for (var i = 0; i < $2.length; i++) { for (var i = 0; i < tail.length; i++) {
result = { result = {
type: "expression", type: "expression",
operator: $2[i][0], operator: tail[i][0],
left: result, left: result,
right: $2[i][1] right: tail[i][1]
}; };
} }
return result; return result;
} }
term term
= unary_operator? = operator:unary_operator?
( value:(
EMS S* EMS S*
/ EXS S* / EXS S*
/ LENGTH S* / LENGTH S*
@ -248,24 +262,24 @@ term
/ FREQ S* / FREQ S*
/ PERCENTAGE S* / PERCENTAGE S*
/ NUMBER S* / NUMBER S*
) { return { type: "value", value: $1 + $2[0] }; } ) { return { type: "value", value: operator + value[0] }; }
/ URI S* { return { type: "uri", value: $1 }; } / value:URI S* { return { type: "uri", value: value }; }
/ function / function
/ hexcolor / hexcolor
/ STRING S* { return { type: "string", value: $1 }; } / value:STRING S* { return { type: "string", value: value }; }
/ IDENT S* { return { type: "ident", value: $1 }; } / value:IDENT S* { return { type: "ident", value: value }; }
function function
= FUNCTION S* expr ")" S* { = name:FUNCTION S* params:expr ")" S* {
return { return {
type: "function", type: "function",
name: $1, name: name,
params: $3 params: params
}; };
} }
hexcolor hexcolor
= HASH S* { return { type: "hexcolor", value: $1}; } = value:HASH S* { return { type: "hexcolor", value: value}; }
/* ===== Lexical Elements ===== */ /* ===== Lexical Elements ===== */
@ -278,13 +292,13 @@ nonascii
= [\x80-\xFF] = [\x80-\xFF]
unicode unicode
= "\\" h h? h? h? h? h? ("\r\n" / [ \t\r\n\f])? { = "\\" h1:h h2:h? h3:h? h4:h? h5:h? h6:h? ("\r\n" / [ \t\r\n\f])? {
return String.fromCharCode(parseInt("0x" + $2 + $3 + $4 + $5 + $6 + $7)); return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4 + h5 + h6));
} }
escape escape
= unicode = unicode
/ "\\" [^\r\n\f0-9a-fA-F] { return $2; } / "\\" char:[^\r\n\f0-9a-fA-F] { return char; }
nmstart nmstart
= [_a-zA-Z] = [_a-zA-Z]
@ -297,29 +311,33 @@ nmchar
/ escape / escape
integer integer
= [0-9]+ { return parseInt($1.join("")); } = digits:[0-9]+ { return parseInt(digits.join("")); }
float 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 string1
= '"' ([^\n\r\f\\"] / "\\" nl { return $2 } / escape)* '"' { = '"' chars:([^\n\r\f\\"] / "\\" nl:nl { return nl } / escape)* '"' {
return $2.join(""); return chars.join("");
} }
string2 string2
= "'" ([^\n\r\f\\'] / "\\" nl { return $2 } / escape)* "'" { = "'" chars:([^\n\r\f\\'] / "\\" nl:nl { return nl } / escape)* "'" {
return $2.join(""); return chars.join("");
} }
comment comment
= "/*" [^*]* "*"+ ([^/*] [^*]* "*"+)* "/" = "/*" [^*]* "*"+ ([^/*] [^*]* "*"+)* "/"
ident ident
= "-"? nmstart nmchar* { return $1 + $2 + $3.join(""); } = dash:"-"? nmstart:nmstart nmchars:nmchar* {
return dash + nmstart + nmchars.join("");
}
name name
= nmchar+ { return $1.join(""); } = nmchars:nmchar+ { return nmchars.join(""); }
num num
= float = float
@ -330,7 +348,7 @@ string
/ string2 / string2
url url
= ([!#$%&*-~] / nonascii / escape)* { return $1.join(""); } = chars:([!#$%&*-~] / nonascii / escape)* { return chars.join(""); }
s s
= [ \t\r\n\f]+ = [ \t\r\n\f]+
@ -368,91 +386,91 @@ G
= [gG] = [gG]
/ "\\" "0"? "0"? "0"? "0"? "47" ("\r\n" / [ \t\r\n\f])? { return "G"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "67" ("\r\n" / [ \t\r\n\f])? { return "g"; }
/ "\\" [gG] { return $2; } / "\\" char:[gG] { return char; }
H H
= [hH] = h:[hH]
/ "\\" "0"? "0"? "0"? "0"? "48" ("\r\n" / [ \t\r\n\f])? { return "H"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "68" ("\r\n" / [ \t\r\n\f])? { return "h"; }
/ "\\" [hH] { return $2; } / "\\" char:[hH] { return char; }
I I
= [iI] = i:[iI]
/ "\\" "0"? "0"? "0"? "0"? "49" ("\r\n" / [ \t\r\n\f])? { return "I"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "69" ("\r\n" / [ \t\r\n\f])? { return "i"; }
/ "\\" [iI] { return $2; } / "\\" char:[iI] { return char; }
K K
= [kK] = [kK]
/ "\\" "0"? "0"? "0"? "0"? "4" [bB] ("\r\n" / [ \t\r\n\f])? { return "K"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "6" [bB] ("\r\n" / [ \t\r\n\f])? { return "k"; }
/ "\\" [kK] { return $2; } / "\\" char:[kK] { return char; }
L L
= [lL] = [lL]
/ "\\" "0"? "0"? "0"? "0"? "4" [cC] ("\r\n" / [ \t\r\n\f])? { return "L"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "6" [cC] ("\r\n" / [ \t\r\n\f])? { return "l"; }
/ "\\" [lL] { return $2; } / "\\" char:[lL] { return char; }
M M
= [mM] = [mM]
/ "\\" "0"? "0"? "0"? "0"? "4" [dD] ("\r\n" / [ \t\r\n\f])? { return "M"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "6" [dD] ("\r\n" / [ \t\r\n\f])? { return "m"; }
/ "\\" [mM] { return $2; } / "\\" char:[mM] { return char; }
N N
= [nN] = [nN]
/ "\\" "0"? "0"? "0"? "0"? "4" [eE] ("\r\n" / [ \t\r\n\f])? { return "N"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "6" [eE] ("\r\n" / [ \t\r\n\f])? { return "n"; }
/ "\\" [nN] { return $2; } / "\\" char:[nN] { return char; }
O O
= [oO] = [oO]
/ "\\" "0"? "0"? "0"? "0"? "4" [fF] ("\r\n" / [ \t\r\n\f])? { return "O"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "6" [fF] ("\r\n" / [ \t\r\n\f])? { return "o"; }
/ "\\" [oO] { return $2; } / "\\" char:[oO] { return char; }
P P
= [pP] = [pP]
/ "\\" "0"? "0"? "0"? "0"? "50" ("\r\n" / [ \t\r\n\f])? { return "P"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "70" ("\r\n" / [ \t\r\n\f])? { return "p"; }
/ "\\" [pP] { return $2; } / "\\" char:[pP] { return char; }
R R
= [rR] = [rR]
/ "\\" "0"? "0"? "0"? "0"? "52" ("\r\n" / [ \t\r\n\f])? { return "R"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "72" ("\r\n" / [ \t\r\n\f])? { return "r"; }
/ "\\" [rR] { return $2; } / "\\" char:[rR] { return char; }
S_ S_
= [sS] = [sS]
/ "\\" "0"? "0"? "0"? "0"? "53" ("\r\n" / [ \t\r\n\f])? { return "S"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "73" ("\r\n" / [ \t\r\n\f])? { return "s"; }
/ "\\" [sS] { return $2; } / "\\" char:[sS] { return char; }
T T
= [tT] = [tT]
/ "\\" "0"? "0"? "0"? "0"? "54" ("\r\n" / [ \t\r\n\f])? { return "T"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "74" ("\r\n" / [ \t\r\n\f])? { return "t"; }
/ "\\" [tT] { return $2; } / "\\" char:[tT] { return char; }
U U
= [uU] = [uU]
/ "\\" "0"? "0"? "0"? "0"? "55" ("\r\n" / [ \t\r\n\f])? { return "U"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "75" ("\r\n" / [ \t\r\n\f])? { return "u"; }
/ "\\" [uU] { return $2; } / "\\" char:[uU] { return char; }
X X
= [xX] = [xX]
/ "\\" "0"? "0"? "0"? "0"? "58" ("\r\n" / [ \t\r\n\f])? { return "X"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "78" ("\r\n" / [ \t\r\n\f])? { return "x"; }
/ "\\" [xX] { return $2; } / "\\" char:[xX] { return char; }
Z Z
= [zZ] = [zZ]
/ "\\" "0"? "0"? "0"? "0"? "5" [aA] ("\r\n" / [ \t\r\n\f])? { return "Z"; } / "\\" "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"; } / "\\" "0"? "0"? "0"? "0"? "7" [aA] ("\r\n" / [ \t\r\n\f])? { return "z"; }
/ "\\" [zZ] { return $2; } / "\\" char:[zZ] { return char; }
/* Tokens */ /* Tokens */
@ -472,13 +490,13 @@ DASHMATCH "|="
= comment* "|=" = comment* "|="
STRING "string" STRING "string"
= comment* string { return $2; } = comment* string:string { return string; }
IDENT "identifier" IDENT "identifier"
= comment* ident { return $2; } = comment* ident:ident { return ident; }
HASH "hash" HASH "hash"
= comment* "#" name { return $2 + $3; } = comment* "#" name:name { return "#" + name; }
IMPORT_SYM "@import" IMPORT_SYM "@import"
= comment* "@" I M P O R T = 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"; } = comment* "!" (s / comment)* I M P O R T A N T { return "!important"; }
EMS "length" EMS "length"
= comment* num E M { return $2 + $3 + $4; } = comment* num:num e:E m:M { return num + e + m; }
EXS "length" EXS "length"
= comment* num E X { return $2 + $3 + $4; } = comment* num:num e:E x:X { return num + e + x; }
LENGTH "length" LENGTH "length"
= comment* num (P X / C M / M M / I N / P T / P C) { = comment* num:num unit:(P X / C M / M M / I N / P T / P C) {
return $2 + $3.join(""); return num + unit.join("");
} }
ANGLE "angle" 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" 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" 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" DIMENSION "dimension"
= comment* num ident { return $2 + $3; } = comment* num:num unit:ident { return num + unit; }
PERCENTAGE "percentage" PERCENTAGE "percentage"
= comment* num "%" { return $2 + $3; } = comment* num:num "%" { return num + "%"; }
NUMBER "number" NUMBER "number"
= comment* num { return $2; } = comment* num:num { return num; }
URI "uri" 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" FUNCTION "function"
= comment* ident "(" { return $2; } = comment* name:ident "(" { return name; }

File diff suppressed because it is too large Load Diff

@ -3,34 +3,34 @@
/* ===== Syntactical Elements ===== */ /* ===== Syntactical Elements ===== */
start start
= _ object { return $2; } = _ object:object { return object; }
object object
= "{" _ "}" _ { return {}; } = "{" _ "}" _ { return {}; }
/ "{" _ members "}" _ { return $3; } / "{" _ members:members "}" _ { return members; }
members members
= pair ("," _ pair)* { = head:pair tail:("," _ pair)* {
var result = {}; var result = {};
result[$1[0]] = $1[1]; result[head[0]] = head[1];
for (var i = 0; i < $2.length; i++) { for (var i = 0; i < tail.length; i++) {
result[$2[i][2][0]] = $2[i][2][1]; result[tail[i][2][0]] = tail[i][2][1];
} }
return result; return result;
} }
pair pair
= string ":" _ value { return [$1, $4]; } = name:string ":" _ value:value { return [name, value]; }
array array
= "[" _ "]" _ { return []; } = "[" _ "]" _ { return []; }
/ "[" _ elements "]" _ { return $3; } / "[" _ elements:elements "]" _ { return elements; }
elements elements
= value ("," _ value)* { = head:value tail:("," _ value)* {
var result = [$1]; var result = [head];
for (var i = 0; i < $2.length; i++) { for (var i = 0; i < tail.length; i++) {
result.push($2[i][2]); result.push(tail[i][2]);
} }
return result; return result;
} }
@ -49,10 +49,10 @@ value
string "string" string "string"
= '"' '"' _ { return ""; } = '"' '"' _ { return ""; }
/ '"' chars '"' _ { return $2; } / '"' chars:chars '"' _ { return chars; }
chars chars
= char+ { return $1.join(""); } = chars:char+ { return chars.join(""); }
char char
// In the original JSON grammar: "any-Unicode-character-except-"-or-\-or-control-character" // In the original JSON grammar: "any-Unicode-character-except-"-or-\-or-control-character"
@ -65,33 +65,33 @@ char
/ "\\n" { return "\n"; } / "\\n" { return "\n"; }
/ "\\r" { return "\r"; } / "\\r" { return "\r"; }
/ "\\t" { return "\t"; } / "\\t" { return "\t"; }
/ "\\u" hexDigit hexDigit hexDigit hexDigit { / "\\u" h1:hexDigit h2:hexDigit h3:hexDigit h4:hexDigit {
return String.fromCharCode(parseInt("0x" + $2 + $3 + $4 + $5)); return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4));
} }
number "number" number "number"
= int frac exp _ { return parseFloat($1 + $2 + $3); } = int:int frac:frac exp:exp _ { return parseFloat(int + frac + exp); }
/ int frac _ { return parseFloat($1 + $2); } / int:int frac:frac _ { return parseFloat(int + frac); }
/ int exp _ { return parseFloat($1 + $2); } / int:int exp:exp _ { return parseFloat(int + exp); }
/ int _ { return parseFloat($1); } / int:int _ { return parseFloat(int); }
int int
= digit19 digits { return $1 + $2; } = digit19:digit19 digits:digits { return digit19 + digits; }
/ digit / digit:digit
/ "-" digit19 digits { return $1 + $2 + $3; } / "-" digit19:digit19 digits:digits { return "-" + digit19 + digits; }
/ "-" digit { return $1 + $2; } / "-" digit:digit { return "-" + digit; }
frac frac
= "." digits { return $1 + $2; } = "." digits:digits { return "." + digits; }
exp exp
= e digits { return $1 + $2; } = e:e digits:digits { return e + digits; }
digits digits
= digit+ { return $1.join(""); } = digits:digit+ { return digits.join(""); }
e 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 * The following rules are not present in the original JSON gramar, but they are

@ -716,7 +716,7 @@ PEG.Compiler = {
* In case of sequences, we splat their elements into function arguments * In case of sequences, we splat their elements into function arguments
* one by one. Example: * 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. * This behavior is reflected in this function.
*/ */
@ -724,38 +724,36 @@ PEG.Compiler = {
var expressionResultVar = PEG.Compiler.generateUniqueIdentifier("result"); var expressionResultVar = PEG.Compiler.generateUniqueIdentifier("result");
if (node.expression.type === "sequence") { if (node.expression.type === "sequence") {
var params = PEG.ArrayUtils.map( var formalParams = [];
PEG.ArrayUtils.range(1, node.expression.elements.length + 1), var actualParams = [];
function(n) { return "$" + n; }
).join(", ");
var invocationCode = PEG.Compiler.formatCode( var elements = node.expression.elements;
"(function(${params}) { ${action} }).apply(null, ${expressionResultVar})", var elementsLength = elements.length;
{ for (var i = 0; i < elementsLength; i++) {
params: params, if (elements[i].type === "labeled") {
action: node.action, formalParams.push(elements[i].label);
expressionResultVar: expressionResultVar actualParams.push(expressionResultVar + "[" + i + "]");
} }
);
} else {
var invocationCode = PEG.Compiler.formatCode(
"(function($1) { ${action} })(${expressionResultVar})",
{
action: node.action,
expressionResultVar: expressionResultVar
} }
); } else if (node.expression.type === "labeled") {
var formalParams = [node.expression.label];
var actualParams = [expressionResultVar];
} else {
var formalParams = [];
var actualParams = [];
} }
return PEG.Compiler.formatCode( return PEG.Compiler.formatCode(
"${expressionCode}", "${expressionCode}",
"var ${resultVar} = ${expressionResultVar} !== null", "var ${resultVar} = ${expressionResultVar} !== null",
" ? ${invocationCode}", " ? (function(${formalParams}) { ${action} })(${actualParams})",
" : null;", " : null;",
{ {
expressionCode: PEG.Compiler.compileNode(node.expression, expressionResultVar), expressionCode: PEG.Compiler.compileNode(node.expression, expressionResultVar),
expressionResultVar: expressionResultVar, expressionResultVar: expressionResultVar,
invocationCode: invocationCode, action: node.action,
formalParams: formalParams.join(", "),
actualParams: actualParams.join(", "),
resultVar: resultVar resultVar: resultVar
} }
); );

@ -85,11 +85,11 @@ PEG.grammarParser = (function(){
this._pos = savedPos0; this._pos = savedPos0;
} }
var result0 = result1 !== null var result0 = result1 !== null
? (function($1, $2) { ? (function(rules) {
var result = {}; var result = {};
PEG.ArrayUtils.each($2, function(rule) { result[rule.name] = rule; }); PEG.ArrayUtils.each(rules, function(rule) { result[rule.name] = rule; });
return result; return result;
}).apply(null, result1) })(result1[1])
: null; : null;
@ -157,14 +157,14 @@ PEG.grammarParser = (function(){
this._pos = savedPos1; this._pos = savedPos1;
} }
var result5 = result6 !== null var result5 = result6 !== null
? (function($1, $2, $3, $4) { ? (function(name, displayName, expression) {
return { return {
type: "rule", type: "rule",
name: $1, name: name,
displayName: $2 !== "" ? $2 : null, displayName: displayName !== "" ? displayName : null,
expression: $4 expression: expression
}; };
}).apply(null, result6) })(result6[0], result6[1], result6[3])
: null; : null;
@ -233,10 +233,10 @@ PEG.grammarParser = (function(){
this._pos = savedPos2; this._pos = savedPos2;
} }
var result13 = result14 !== null var result13 = result14 !== null
? (function($1, $2) { ? (function(head, tail) {
if ($2.length > 0) { if (tail.length > 0) {
var alternatives = [$1].concat(PEG.ArrayUtils.map( var alternatives = [head].concat(PEG.ArrayUtils.map(
$2, tail,
function(element) { return element[1]; } function(element) { return element[1]; }
)); ));
return { return {
@ -244,9 +244,9 @@ PEG.grammarParser = (function(){
alternatives: alternatives alternatives: alternatives
} }
} else { } else {
return $1; return head;
} }
}).apply(null, result14) })(result14[0], result14[1])
: null; : null;
@ -289,19 +289,19 @@ PEG.grammarParser = (function(){
this._pos = savedPos4; this._pos = savedPos4;
} }
var result24 = result25 !== null var result24 = result25 !== null
? (function($1, $2) { ? (function(elements, action) {
var expression = $1.length != 1 var expression = elements.length != 1
? { ? {
type: "sequence", type: "sequence",
elements: $1 elements: elements
} }
: $1[0]; : elements[0];
return { return {
type: "action", type: "action",
expression: expression, expression: expression,
action: $2 action: action
}; };
}).apply(null, result25) })(result25[0], result25[1])
: null; : null;
if (result24 !== null) { if (result24 !== null) {
var result20 = result24; var result20 = result24;
@ -313,13 +313,13 @@ PEG.grammarParser = (function(){
var result23 = this._parse_labeled(context); var result23 = this._parse_labeled(context);
} }
var result21 = result22 !== null var result21 = result22 !== null
? (function($1) { ? (function(elements) {
return $1.length != 1 return elements.length != 1
? { ? {
type: "sequence", type: "sequence",
elements: $1 elements: elements
} }
: $1[0]; : elements[0];
})(result22) })(result22)
: null; : null;
if (result21 !== null) { if (result21 !== null) {
@ -370,13 +370,13 @@ PEG.grammarParser = (function(){
this._pos = savedPos5; this._pos = savedPos5;
} }
var result31 = result32 !== null var result31 = result32 !== null
? (function($1, $2, $3) { ? (function(label, expression) {
return { return {
type: "labeled", type: "labeled",
label: $1, label: label,
expression: $3 expression: expression
}; };
}).apply(null, result32) })(result32[0], result32[2])
: null; : null;
if (result31 !== null) { if (result31 !== null) {
var result29 = result31; var result29 = result31;
@ -424,7 +424,12 @@ PEG.grammarParser = (function(){
this._pos = savedPos7; this._pos = savedPos7;
} }
var result42 = result43 !== null 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; : null;
if (result42 !== null) { if (result42 !== null) {
var result36 = result42; var result36 = result42;
@ -444,7 +449,12 @@ PEG.grammarParser = (function(){
this._pos = savedPos6; this._pos = savedPos6;
} }
var result38 = result39 !== null 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; : null;
if (result38 !== null) { if (result38 !== null) {
var result36 = result38; var result36 = result38;
@ -493,7 +503,12 @@ PEG.grammarParser = (function(){
this._pos = savedPos10; this._pos = savedPos10;
} }
var result56 = result57 !== null 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; : null;
if (result56 !== null) { if (result56 !== null) {
var result46 = result56; var result46 = result56;
@ -513,7 +528,12 @@ PEG.grammarParser = (function(){
this._pos = savedPos9; this._pos = savedPos9;
} }
var result52 = result53 !== null 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; : null;
if (result52 !== null) { if (result52 !== null) {
var result46 = result52; var result46 = result52;
@ -533,7 +553,12 @@ PEG.grammarParser = (function(){
this._pos = savedPos8; this._pos = savedPos8;
} }
var result48 = result49 !== null 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; : null;
if (result48 !== null) { if (result48 !== null) {
var result46 = result48; var result46 = result48;
@ -624,21 +649,31 @@ PEG.grammarParser = (function(){
this._pos = savedPos12; this._pos = savedPos12;
} }
var result71 = result72 !== null 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; : null;
if (result71 !== null) { if (result71 !== null) {
var result60 = result71; var result60 = result71;
} else { } else {
var result70 = this._parse_literal(context); var result70 = this._parse_literal(context);
var result69 = result70 !== null var result69 = result70 !== null
? (function($1) { return { type: "literal", value: $1 }; })(result70) ? (function(value) {
return {
type: "literal",
value: value
};
})(result70)
: null; : null;
if (result69 !== null) { if (result69 !== null) {
var result60 = result69; var result60 = result69;
} else { } else {
var result68 = this._parse_dot(context); var result68 = this._parse_dot(context);
var result67 = result68 !== null var result67 = result68 !== null
? (function($1) { return { type: "any" }; })(result68) ? (function() { return { type: "any" }; })()
: null; : null;
if (result67 !== null) { if (result67 !== null) {
var result60 = result67; var result60 = result67;
@ -668,7 +703,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos11; this._pos = savedPos11;
} }
var result61 = result62 !== null var result61 = result62 !== null
? (function($1, $2, $3) { return $2; }).apply(null, result62) ? (function(expression) { return expression; })(result62[1])
: null; : null;
if (result61 !== null) { if (result61 !== null) {
var result60 = result61; var result60 = result61;
@ -716,7 +751,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos15; this._pos = savedPos15;
} }
var result80 = result81 !== null 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; : null;
context.reportMatchFailures = savedReportMatchFailures; context.reportMatchFailures = savedReportMatchFailures;
if (context.reportMatchFailures && result80 === null) { if (context.reportMatchFailures && result80 === null) {
@ -803,7 +838,9 @@ PEG.grammarParser = (function(){
this._pos = savedPos16; this._pos = savedPos16;
} }
var result84 = result85 !== null var result84 = result85 !== null
? (function($1, $2, $3) { return $1 + $2.join("") + $3; }).apply(null, result85) ? (function(parts) {
return "{" + parts.join("") + "}";
})(result85[1])
: null; : null;
@ -837,7 +874,7 @@ PEG.grammarParser = (function(){
var result93 = null; var result93 = null;
} }
var result92 = result93 !== null var result92 = result93 !== null
? (function($1) { return $1.join(""); })(result93) ? (function(chars) { return chars.join(""); })(result93)
: null; : null;
@ -913,7 +950,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos17; this._pos = savedPos17;
} }
var result96 = result97 !== null var result96 = result97 !== null
? (function($1, $2) { return $1; }).apply(null, result97) ? (function() { return "="; })()
: null; : null;
@ -959,7 +996,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos18; this._pos = savedPos18;
} }
var result100 = result101 !== null var result100 = result101 !== null
? (function($1, $2) { return $1; }).apply(null, result101) ? (function() { return ":"; })()
: null; : null;
@ -1005,7 +1042,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos19; this._pos = savedPos19;
} }
var result104 = result105 !== null var result104 = result105 !== null
? (function($1, $2) { return $1; }).apply(null, result105) ? (function() { return "/"; })()
: null; : null;
@ -1051,7 +1088,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos20; this._pos = savedPos20;
} }
var result108 = result109 !== null var result108 = result109 !== null
? (function($1, $2) { return $1; }).apply(null, result109) ? (function() { return "&"; })()
: null; : null;
@ -1097,7 +1134,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos21; this._pos = savedPos21;
} }
var result112 = result113 !== null var result112 = result113 !== null
? (function($1, $2) { return $1; }).apply(null, result113) ? (function() { return "!"; })()
: null; : null;
@ -1143,7 +1180,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos22; this._pos = savedPos22;
} }
var result116 = result117 !== null var result116 = result117 !== null
? (function($1, $2) { return $1; }).apply(null, result117) ? (function() { return "?"; })()
: null; : null;
@ -1189,7 +1226,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos23; this._pos = savedPos23;
} }
var result120 = result121 !== null var result120 = result121 !== null
? (function($1, $2) { return $1; }).apply(null, result121) ? (function() { return "*"; })()
: null; : null;
@ -1235,7 +1272,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos24; this._pos = savedPos24;
} }
var result124 = result125 !== null var result124 = result125 !== null
? (function($1, $2) { return $1; }).apply(null, result125) ? (function() { return "+"; })()
: null; : null;
@ -1281,7 +1318,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos25; this._pos = savedPos25;
} }
var result128 = result129 !== null var result128 = result129 !== null
? (function($1, $2) { return $1; }).apply(null, result129) ? (function() { return "("; })()
: null; : null;
@ -1327,7 +1364,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos26; this._pos = savedPos26;
} }
var result132 = result133 !== null var result132 = result133 !== null
? (function($1, $2) { return $1; }).apply(null, result133) ? (function() { return ")"; })()
: null; : null;
@ -1373,7 +1410,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos27; this._pos = savedPos27;
} }
var result136 = result137 !== null var result136 = result137 !== null
? (function($1, $2) { return $1; }).apply(null, result137) ? (function() { return "."; })()
: null; : null;
@ -1526,9 +1563,9 @@ PEG.grammarParser = (function(){
this._pos = savedPos28; this._pos = savedPos28;
} }
var result140 = result141 !== null var result140 = result141 !== null
? (function($1, $2, $3) { ? (function(head, tail) {
return $1 + $2.join(""); return head + tail.join("");
}).apply(null, result141) })(result141[0], result141[1])
: null; : null;
context.reportMatchFailures = savedReportMatchFailures; context.reportMatchFailures = savedReportMatchFailures;
if (context.reportMatchFailures && result140 === null) { if (context.reportMatchFailures && result140 === null) {
@ -1579,7 +1616,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos29; this._pos = savedPos29;
} }
var result153 = result154 !== null var result153 = result154 !== null
? (function($1, $2) { return $1; }).apply(null, result154) ? (function(literal) { return literal; })(result154[0])
: null; : null;
context.reportMatchFailures = savedReportMatchFailures; context.reportMatchFailures = savedReportMatchFailures;
if (context.reportMatchFailures && result153 === null) { if (context.reportMatchFailures && result153 === null) {
@ -1646,7 +1683,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos30; this._pos = savedPos30;
} }
var result159 = result160 !== null var result159 = result160 !== null
? (function($1, $2, $3) { return $2.join(""); }).apply(null, result160) ? (function(chars) { return chars.join(""); })(result160[1])
: null; : null;
@ -1785,7 +1822,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos31; this._pos = savedPos31;
} }
var result172 = result173 !== null var result172 = result173 !== null
? (function($1, $2) { return $2; }).apply(null, result173) ? (function(char_) { return char_; })(result173[1])
: null; : null;
@ -1850,7 +1887,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos33; this._pos = savedPos33;
} }
var result180 = result181 !== null var result180 = result181 !== null
? (function($1, $2, $3) { return $2.join(""); }).apply(null, result181) ? (function(chars) { return chars.join(""); })(result181[1])
: null; : null;
@ -1989,7 +2026,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos34; this._pos = savedPos34;
} }
var result193 = result194 !== null var result193 = result194 !== null
? (function($1, $2) { return $2; }).apply(null, result194) ? (function(char_) { return char_; })(result194[1])
: null; : null;
@ -2096,23 +2133,25 @@ PEG.grammarParser = (function(){
this._pos = savedPos36; this._pos = savedPos36;
} }
var result201 = result202 !== null var result201 = result202 !== null
? (function($1, $2, $3, $4, $5) { ? (function(inverted, parts) {
parts = PEG.ArrayUtils.map($3, function(part) { return part.data; }); partsConverted = PEG.ArrayUtils.map(parts, function(part) {
return part.data;
});
rawText = "[" rawText = "["
+ $2 + inverted
+ PEG.ArrayUtils.map($3, function(part) { + PEG.ArrayUtils.map(parts, function(part) {
return part.rawText; return part.rawText;
}).join("") }).join("")
+ "]"; + "]";
return { return {
type: "class", type: "class",
inverted: $2 === "^", inverted: inverted === "^",
parts: parts, parts: partsConverted,
// FIXME: Get the raw text from the input directly. // FIXME: Get the raw text from the input directly.
rawText: rawText rawText: rawText
}; };
}).apply(null, result202) })(result202[1], result202[2])
: null; : null;
context.reportMatchFailures = savedReportMatchFailures; context.reportMatchFailures = savedReportMatchFailures;
if (context.reportMatchFailures && result201 === null) { if (context.reportMatchFailures && result201 === null) {
@ -2166,19 +2205,19 @@ PEG.grammarParser = (function(){
this._pos = savedPos37; this._pos = savedPos37;
} }
var result212 = result213 !== null var result212 = result213 !== null
? (function($1, $2, $3) { ? (function(begin, end) {
if ($1.data.charCodeAt(0) > $3.data.charCodeAt(0)) { if (begin.data.charCodeAt(0) > end.data.charCodeAt(0)) {
throw new this.SyntaxError( throw new this.SyntaxError(
"Invalid character range: " + $1.rawText + "-" + $3.rawText + "." "Invalid character range: " + begin.rawText + "-" + end.rawText + "."
); );
} }
return { return {
data: [$1.data, $3.data], data: [begin.data, end.data],
// FIXME: Get the raw text from the input directly. // 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; : null;
@ -2203,11 +2242,11 @@ PEG.grammarParser = (function(){
var result218 = this._parse_bracketDelimitedCharacter(context); var result218 = this._parse_bracketDelimitedCharacter(context);
var result217 = result218 !== null var result217 = result218 !== null
? (function($1) { ? (function(char_) {
return { return {
data: $1, data: char_,
// FIXME: Get the raw text from the input directly. // FIXME: Get the raw text from the input directly.
rawText: PEG.RegExpUtils.quoteForClass($1) rawText: PEG.RegExpUtils.quoteForClass(char_)
}; };
})(result218) })(result218)
: null; : null;
@ -2348,7 +2387,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos38; this._pos = savedPos38;
} }
var result226 = result227 !== null var result226 = result227 !== null
? (function($1, $2) { return $2; }).apply(null, result227) ? (function(char_) { return char_; })(result227[1])
: null; : null;
@ -2454,15 +2493,15 @@ PEG.grammarParser = (function(){
this._pos = savedPos40; this._pos = savedPos40;
} }
var result234 = result235 !== null var result234 = result235 !== null
? (function($1, $2, $3) { ? (function(char_) {
return $3 return char_
.replace("b", "\b") .replace("b", "\b")
.replace("f", "\f") .replace("f", "\f")
.replace("n", "\n") .replace("n", "\n")
.replace("r", "\r") .replace("r", "\r")
.replace("t", "\t") .replace("t", "\t")
.replace("v", "\x0B") // IE does not recognize "\v". .replace("v", "\x0B") // IE does not recognize "\v".
}).apply(null, result235) })(result235[2])
: null; : null;
@ -2518,7 +2557,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos42; this._pos = savedPos42;
} }
var result244 = result245 !== null var result244 = result245 !== null
? (function($1, $2) { return "\0"; }).apply(null, result245) ? (function() { return "\0"; })()
: null; : null;
@ -2570,9 +2609,9 @@ PEG.grammarParser = (function(){
this._pos = savedPos44; this._pos = savedPos44;
} }
var result249 = result250 !== null var result249 = result250 !== null
? (function($1, $2, $3) { ? (function(h1, h2) {
return String.fromCharCode(parseInt("0x" + $2 + $3)); return String.fromCharCode(parseInt("0x" + h1 + h2));
}).apply(null, result250) })(result250[1], result250[2])
: null; : null;
@ -2636,9 +2675,9 @@ PEG.grammarParser = (function(){
this._pos = savedPos45; this._pos = savedPos45;
} }
var result254 = result255 !== null var result254 = result255 !== null
? (function($1, $2, $3, $4, $5) { ? (function(h1, h2, h3, h4) {
return String.fromCharCode(parseInt("0x" + $2 + $3 + $4 + $5)); return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4));
}).apply(null, result255) })(result255[1], result255[2], result255[3], result255[4])
: null; : null;
@ -2684,7 +2723,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos46; this._pos = savedPos46;
} }
var result261 = result262 !== null var result261 = result262 !== null
? (function($1, $2) { return $2; }).apply(null, result262) ? (function(eol) { return eol; })(result262[1])
: null; : null;

@ -1,17 +1,17 @@
grammar grammar
= __ rule+ { = __ rules:rule+ {
var result = {}; var result = {};
PEG.ArrayUtils.each($2, function(rule) { result[rule.name] = rule; }); PEG.ArrayUtils.each(rules, function(rule) { result[rule.name] = rule; });
return result; return result;
} }
rule rule
= identifier (literal / "") equals expression { = name:identifier displayName:(literal / "") equals expression:expression {
return { return {
type: "rule", type: "rule",
name: $1, name: name,
displayName: $2 !== "" ? $2 : null, displayName: displayName !== "" ? displayName : null,
expression: $4 expression: expression
}; };
} }
@ -19,10 +19,10 @@ expression
= choice = choice
choice choice
= sequence (slash sequence)* { = head:sequence tail:(slash sequence)* {
if ($2.length > 0) { if (tail.length > 0) {
var alternatives = [$1].concat(PEG.ArrayUtils.map( var alternatives = [head].concat(PEG.ArrayUtils.map(
$2, tail,
function(element) { return element[1]; } function(element) { return element[1]; }
)); ));
return { return {
@ -30,86 +30,123 @@ choice
alternatives: alternatives alternatives: alternatives
} }
} else { } else {
return $1; return head;
} }
} }
sequence sequence
= labeled* action { = elements:labeled* action:action {
var expression = $1.length != 1 var expression = elements.length != 1
? { ? {
type: "sequence", type: "sequence",
elements: $1 elements: elements
} }
: $1[0]; : elements[0];
return { return {
type: "action", type: "action",
expression: expression, expression: expression,
action: $2 action: action
}; };
} }
/ labeled* { / elements:labeled* {
return $1.length != 1 return elements.length != 1
? { ? {
type: "sequence", type: "sequence",
elements: $1 elements: elements
} }
: $1[0]; : elements[0];
} }
labeled labeled
= identifier colon prefixed { = label:identifier colon expression:prefixed {
return { return {
type: "labeled", type: "labeled",
label: $1, label: label,
expression: $3 expression: expression
}; };
} }
/ prefixed / prefixed
prefixed prefixed
= and suffixed { return { type: "and_predicate", expression: $2 }; } = and expression:suffixed {
/ not suffixed { return { type: "not_predicate", expression: $2 }; } return {
type: "and_predicate",
expression: expression
};
}
/ not expression:suffixed {
return {
type: "not_predicate",
expression: expression
};
}
/ suffixed / suffixed
suffixed suffixed
= primary question { return { type: "optional", expression: $1}; } = expression:primary question {
/ primary star { return { type: "zero_or_more", expression: $1}; } return {
/ primary plus { return { type: "one_or_more", expression: $1}; } 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
primary primary
= identifier !(( literal / "") equals) { return { type: "rule_ref", name: $1 }; } = name:identifier !(( literal / "") equals) {
/ literal { return { type: "literal", value: $1 }; } return {
type: "rule_ref",
name: name
};
}
/ value:literal {
return {
type: "literal",
value: value
};
}
/ dot { return { type: "any" }; } / dot { return { type: "any" }; }
/ class / class
/ lparen expression rparen { return $2; } / lparen expression:expression rparen { return expression; }
/* "Lexical" elements */ /* "Lexical" elements */
action "action" action "action"
= braced __ { return $1.substr(1, $1.length - 2); } = braced:braced __ { return braced.substr(1, braced.length - 2); }
braced braced
= "{" (braced / nonBraceCharacter)* "}" { return $1 + $2.join("") + $3; } = "{" parts:(braced / nonBraceCharacter)* "}" {
return "{" + parts.join("") + "}";
}
nonBraceCharacters nonBraceCharacters
= nonBraceCharacter+ { return $1.join(""); } = chars:nonBraceCharacter+ { return chars.join(""); }
nonBraceCharacter nonBraceCharacter
= [^{}] = [^{}]
equals = "=" __ { return $1; } equals = "=" __ { return "="; }
colon = ":" __ { return $1; } colon = ":" __ { return ":"; }
slash = "/" __ { return $1; } slash = "/" __ { return "/"; }
and = "&" __ { return $1; } and = "&" __ { return "&"; }
not = "!" __ { return $1; } not = "!" __ { return "!"; }
question = "?" __ { return $1; } question = "?" __ { return "?"; }
star = "*" __ { return $1; } star = "*" __ { return "*"; }
plus = "+" __ { return $1; } plus = "+" __ { return "+"; }
lparen = "(" __ { return $1; } lparen = "(" __ { return "("; }
rparen = ")" __ { return $1; } rparen = ")" __ { return ")"; }
dot = "." __ { return $1; } dot = "." __ { return "."; }
/* /*
* Modelled after ECMA-262, 5th ed., 7.6, but much simplified: * 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. * easier, there is no "philosophical" reason behind them.
*/ */
identifier "identifier" identifier "identifier"
= (letter / "_" / "$") (letter / digit / "_" / "$")* __ { = head:(letter / "_" / "$") tail:(letter / digit / "_" / "$")* __ {
return $1 + $2.join(""); return head + tail.join("");
} }
/* /*
@ -136,10 +173,10 @@ identifier "identifier"
* vaguely). * vaguely).
*/ */
literal "literal" literal "literal"
= (doubleQuotedLiteral / singleQuotedLiteral) __ { return $1; } = literal:(doubleQuotedLiteral / singleQuotedLiteral) __ { return literal; }
doubleQuotedLiteral doubleQuotedLiteral
= '"' doubleQuotedCharacter* '"' { return $2.join(""); } = '"' chars:doubleQuotedCharacter* '"' { return chars.join(""); }
doubleQuotedCharacter doubleQuotedCharacter
= simpleDoubleQuotedCharacter = simpleDoubleQuotedCharacter
@ -150,10 +187,10 @@ doubleQuotedCharacter
/ eolEscapeSequence / eolEscapeSequence
simpleDoubleQuotedCharacter simpleDoubleQuotedCharacter
= !('"' / "\\" / eolChar) . { return $2; } = !('"' / "\\" / eolChar) char_:. { return char_; }
singleQuotedLiteral singleQuotedLiteral
= "'" singleQuotedCharacter* "'" { return $2.join(""); } = "'" chars:singleQuotedCharacter* "'" { return chars.join(""); }
singleQuotedCharacter singleQuotedCharacter
= simpleSingleQuotedCharacter = simpleSingleQuotedCharacter
@ -164,48 +201,50 @@ singleQuotedCharacter
/ eolEscapeSequence / eolEscapeSequence
simpleSingleQuotedCharacter simpleSingleQuotedCharacter
= !("'" / "\\" / eolChar) . { return $2; } = !("'" / "\\" / eolChar) char_:. { return char_; }
class "character class" class "character class"
= "[" "^"? (classCharacterRange / classCharacter)* "]" __ { = "[" inverted:"^"? parts:(classCharacterRange / classCharacter)* "]" __ {
parts = PEG.ArrayUtils.map($3, function(part) { return part.data; }); partsConverted = PEG.ArrayUtils.map(parts, function(part) {
return part.data;
});
rawText = "[" rawText = "["
+ $2 + inverted
+ PEG.ArrayUtils.map($3, function(part) { + PEG.ArrayUtils.map(parts, function(part) {
return part.rawText; return part.rawText;
}).join("") }).join("")
+ "]"; + "]";
return { return {
type: "class", type: "class",
inverted: $2 === "^", inverted: inverted === "^",
parts: parts, parts: partsConverted,
// FIXME: Get the raw text from the input directly. // FIXME: Get the raw text from the input directly.
rawText: rawText rawText: rawText
}; };
} }
classCharacterRange classCharacterRange
= classCharacter "-" classCharacter { = begin:classCharacter "-" end:classCharacter {
if ($1.data.charCodeAt(0) > $3.data.charCodeAt(0)) { if (begin.data.charCodeAt(0) > end.data.charCodeAt(0)) {
throw new this.SyntaxError( throw new this.SyntaxError(
"Invalid character range: " + $1.rawText + "-" + $3.rawText + "." "Invalid character range: " + begin.rawText + "-" + end.rawText + "."
); );
} }
return { return {
data: [$1.data, $3.data], data: [begin.data, end.data],
// FIXME: Get the raw text from the input directly. // FIXME: Get the raw text from the input directly.
rawText: $1.rawText + "-" + $3.rawText rawText: begin.rawText + "-" + end.rawText
} }
} }
classCharacter classCharacter
= bracketDelimitedCharacter { = char_:bracketDelimitedCharacter {
return { return {
data: $1, data: char_,
// FIXME: Get the raw text from the input directly. // 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 / eolEscapeSequence
simpleBracketDelimitedCharacter simpleBracketDelimitedCharacter
= !("]" / "\\" / eolChar) . { return $2; } = !("]" / "\\" / eolChar) char_:. { return char_; }
simpleEscapeSequence simpleEscapeSequence
= "\\" !(digit / "x" / "u" / eolChar) . { = "\\" !(digit / "x" / "u" / eolChar) char_:. {
return $3 return char_
.replace("b", "\b") .replace("b", "\b")
.replace("f", "\f") .replace("f", "\f")
.replace("n", "\n") .replace("n", "\n")
@ -235,17 +274,17 @@ zeroEscapeSequence
= "\\0" !digit { return "\0"; } = "\\0" !digit { return "\0"; }
hexEscapeSequence hexEscapeSequence
= "\\x" hexDigit hexDigit { = "\\x" h1:hexDigit h2:hexDigit {
return String.fromCharCode(parseInt("0x" + $2 + $3)); return String.fromCharCode(parseInt("0x" + h1 + h2));
} }
unicodeEscapeSequence unicodeEscapeSequence
= "\\u" hexDigit hexDigit hexDigit hexDigit { = "\\u" h1:hexDigit h2:hexDigit h3:hexDigit h4:hexDigit {
return String.fromCharCode(parseInt("0x" + $2 + $3 + $4 + $5)); return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4));
} }
eolEscapeSequence eolEscapeSequence
= "\\" eol { return $2; } = "\\" eol:eol { return eol; }
digit digit
= [0-9] = [0-9]

@ -342,33 +342,41 @@ test("one or more expressions", function() {
}); });
test("actions", function() { test("actions", function() {
var singleMatchParser = PEG.buildParser( var singleElementUnlabeledParser = PEG.buildParser(
'start = "a" { return Array.prototype.slice.call(arguments).join("").toUpperCase(); }' 'start = "a" { return arguments.length; }'
); );
parses(singleMatchParser, "a", "A"); parses(singleElementUnlabeledParser, "a", 0);
var multiMatchParser = PEG.buildParser( var singleElementLabeledParser = PEG.buildParser(
'start = "a" "b" "c" { return Array.prototype.slice.call(arguments).join("").toUpperCase(); }' 'start = a:"a" { return [arguments.length, a]; }'
); );
parses(multiMatchParser, "abc", "ABC"); parses(singleElementLabeledParser, "a", [1, "a"]);
var innerMatchParser = PEG.buildParser( var multiElementUnlabeledParser = PEG.buildParser(
'start = "a" ("b" "c" "d" { return Array.prototype.slice.call(arguments).join("").toUpperCase(); }) "e"' '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. */ /* Test that the action is not called when its expression does not match. */
var notAMatchParser = PEG.buildParser( var notAMatchParser = PEG.buildParser(
'start = "a" { ok(false, "action got called when it should not be"); }' 'start = "a" { ok(false, "action got called when it should not be"); }'
); );
doesNotParse(notAMatchParser, "b"); 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() { test("rule references", function() {
@ -581,8 +589,8 @@ test("error messages", function() {
test("error positions", function() { test("error positions", function() {
var parser = PEG.buildParser([ var parser = PEG.buildParser([
'start = line (("\\r" / "\\n" / "\\u2028" / "\\u2029")+ line)*', 'start = line (("\\r" / "\\n" / "\\u2028" / "\\u2029")+ line)*',
'line = digit (" "+ digit)*', 'line = digits (" "+ digits)*',
'digit = [0-9]+ { return $1.join(""); }' 'digits = digits:[0-9]+ { return digits.join(""); }'
].join("\n")); ].join("\n"));
doesNotParseWithPos(parser, "a", 1, 1); doesNotParseWithPos(parser, "a", 1, 1);
@ -611,21 +619,21 @@ test("arithmetics", function() {
* Expr Sum * Expr Sum
*/ */
var parser = PEG.buildParser([ var parser = PEG.buildParser([
'Value = [0-9]+ { return parseInt($1.join("")); }', 'Value = digits:[0-9]+ { return parseInt(digits.join("")); }',
' / "(" Expr ")" { return $2; }', ' / "(" expr:Expr ")" { return expr; }',
'Product = Value (("*" / "/") Value)* {', 'Product = head:Value tail:(("*" / "/") Value)* {',
' var result = $1;', ' var result = head;',
' for (var i = 0; i < $2.length; i++) {', ' for (var i = 0; i < tail.length; i++) {',
' if ($2[i][0] == "*") { result *= $2[i][1]; }', ' if (tail[i][0] == "*") { result *= tail[i][1]; }',
' if ($2[i][0] == "/") { result /= $2[i][1]; }', ' if (tail[i][0] == "/") { result /= tail[i][1]; }',
' }', ' }',
' return result;', ' return result;',
' }', ' }',
'Sum = Product (("+" / "-") Product)* {', 'Sum = head:Product tail:(("+" / "-") Product)* {',
' var result = $1;', ' var result = head;',
' for (var i = 0; i < $2.length; i++) {', ' for (var i = 0; i < tail.length; i++) {',
' if ($2[i][0] == "+") { result += $2[i][1]; }', ' if (tail[i][0] == "+") { result += tail[i][1]; }',
' if ($2[i][0] == "-") { result -= $2[i][1]; }', ' if (tail[i][0] == "-") { result -= tail[i][1]; }',
' }', ' }',
' return result;', ' return result;',
' }', ' }',
@ -667,9 +675,9 @@ test("non-context-free language", function() {
* B b B? c * B b B? c
*/ */
var parser = PEG.buildParser([ var parser = PEG.buildParser([
'S = &(A "c") "a"+ B !("a" / "b" / "c") { return $2.join("") + $3; }', 'S = &(A "c") a:"a"+ B:B !("a" / "b" / "c") { return a.join("") + B; }',
'A = "a" A? "b" { return $1 + $2 + $3; }', 'A = a:"a" A:A? b:"b" { return a + A + b; }',
'B = "b" B? "c" { return $1 + $2 + $3; }', 'B = b:"b" B:B? c:"c" { return b + B + c; }',
].join("\n"), "S"); ].join("\n"), "S");
parses(parser, "abc", "abc"); parses(parser, "abc", "abc");
@ -693,9 +701,9 @@ test("nested comments", function() {
var parser = PEG.buildParser([ var parser = PEG.buildParser([
'Begin = "(*"', 'Begin = "(*"',
'End = "*)"', 'End = "*)"',
'C = Begin N* End { return $1 + $2.join("") + $3; }', 'C = begin:Begin ns:N* end:End { return begin + ns.join("") + end; }',
'N = C', 'N = C',
' / (!Begin !End Z) { return $3; }', ' / !Begin !End z:Z { return z; }',
'Z = .' 'Z = .'
].join("\n"), "C"); ].join("\n"), "C");

Loading…
Cancel
Save