start = itemlist:Itemlist _ globals:Globals _ within:Within { return {'items': itemlist, 'globals': globals, 'within': within } } Itemlist = head:Item tail:(_ Item)* { var result = [head]; for (var i = 0; i < tail.length; i++) { result.push(tail[i][1]); } return result; } Globals = _ "::" _ head:Globalexpr tail:(_ ("&"/"|") _ Globalexpr)* { var result = [{'expr': head}]; for (var i = 0; i < tail.length; i++) { var item = {'expr': tail[i][3]}; item.join = tail[i][1]; result.push(item); } return result; } / "" Within = _ "within " _ region:Regionname { return region } / "" Globalexpr = att1:Globalname _ eq:("!"?("=" / ">" / "<" )) _ att2:Globalname { return [ att1, eq.join(""), att2] } Globalname = Number / Regex / hook:Tokenname "." att1:Attname { return {'satt': att1, 'hook': hook} } Item = _ name:(("@" / [a-z]+":")?) "[" _ tokenex:Tokenexpr _ "]" multiplier:([*+?]?) _ { if ( name != null && typeof(name) != "undefined" ) { if ( name === "@" ) name = 'target'; else name = name.join("").replace(":",""); }; return {'type': 'token', 'rule': tokenex, 'multiplier': multiplier, 'name': name } } / _ "<" _ region:Regionname ("_" pAttname )? _ ">" _ { return {'type': 'region', 'name': region } } / _ "(" _ itemlist:Itemgroup _ ")" _ { return { 'type': 'group', 'items': itemlist } } / _ "<" _ region:Regionname "_" rule:Tokeneq _ ">" _ { return {'type': 'region', 'name': region, 'rule': rule } } / _ re:Regex _ { return {'type': 'token', 'rule': ['word', '=', re ] } } Tokenexpr = head: Tokeneq tail:( _ eq:("&" / "|") _ Tokeneq)* { var result = [ {'expr': head} ]; for (var i = 0; i < tail.length; i++) { var item = {'expr': tail[i][3]}; item.join = tail[i][1]; result.push(item); } return result; } / "" Itemgroup = head: Itemlist tail:( _ eq:("&" / "|") _ Itemlist)* { var result = [{'expr': head}]; for (var i = 0; i < tail.length; i++) { var item = {'expr': tail[i][3]}; item.join = tail[i][1]; result.push(item); } return result; } / "" Tokeneq = _ "(" _ t1:Tokenexpr _ ")" _ { return { 'group': t1 } } / _ att1:Att _ eq:("!"?("=" / ">" / "<" )) _ att2:Att _ { return [att1, eq.join(""), att2] } Att = Attname / Regex / Number Regionname = region:[a-z0-9]+ { return region.join(""); } Tokenname = region:[a-z0-9_]+ { return region.join(""); } Attname = sAttname / pAttname sAttname = region:Regionname "_" attribute:[a-z0-9_]+ { return {'patt': region+'_'+attribute.join(""), 'region': region, 'attribute': attribute.join("")}; } pAttname = name:[a-z0-9_]+ { return {'patt': name.join("")}; } Number = name:[0-9.]+ { return {'number': name.join("")}; } Regex = "'" expression:[^']* "'" { return {'re': expression.join("")}; } / '"' expression:[^"]* '"' { return {'re': expression.join("")}; } _ "whitespace (optional)" = [ \t\n\r]*