javascript - Jison Google-Like Parser -
javascript - Jison Google-Like Parser -
i have written parser using jison able handle google-like search queries operators , boolean operation support. currently, having difficulty figuring out how take whitespace in between , or , not operators. help appreciated , have attached examples of desired input/output below.
input:
true && false || true ( true ) && ( false || true ) true&&false||trueresult:
1-3. ([true]&&([false]||[true]))
code:
%lex %% /* lexical grammar */ "and"|"&&" { homecoming "and" } "or"|"||" { homecoming "or" } "not"|"!" { homecoming "not" } "(" { homecoming "open" } ")" { homecoming "close" } ":" { homecoming "qual" } "-" { homecoming "dash" } "\""|"'" { homecoming "quote" } \s+ { homecoming "space" } \w+ { homecoming "word" } "." { homecoming "dot" } <<eof>> { homecoming "eof" } . { homecoming "invalid" } /lex /* operators */ %right , or %right not %right qual dash dot %start start %% /* language grammar */ start : exp eof { homecoming $1; } ; exp : exp , exp { $$ = "(" + $1 + "&&" + $3 + ")"; } | exp or exp { $$ = "(" + $1 + "||" + $3 + ")"; } | not exp { $$ = "(!" + $2 + ")"; } | open exp close { $$ = $2; } | args { $$ = "[" + $1 + "]"; } ; args : arg space args { $$ = [ $1 ].concat($3); } | op space args { $$ = [ $1 ].concat($3); } | arg { $$ = [ $1 ]; } | op { $$ = [ $1 ]; } ; op : dash op { $$ = "-" + $2; } | arg qual arg { $$ = $1 + ":" + $3; } ; arg : dash arg { $$ = "-" + $2; } | quote terms quote { $$ = $2.join(" "); } | term { $$ = $1; } ; terms : term space terms { $$ = [ $1 ].concat($3); } | term { $$ = [ $1 ]; } ; term : term dash term { $$ = $1 + $2 + $3; } | term dot term { $$ = $1 + $2 + $3; } | word { $$ = $1; } ;
figured out. started ignoring whitespace, changed few rules, , resolved conflicts. parser returns function used determine if object matches query. here final result:
/* google-like parser */ /* lexical grammar */ %lex %% \s+ { /* ignore whitespace */ } "and"|"&&" { homecoming "and" } "or"|"||" { homecoming "or" } "not"|"!" { homecoming "not" } "(" { homecoming "open" } ")" { homecoming "close" } ":" { homecoming "qual" } "-" { homecoming "neg" } "\""|"'" { homecoming "quote" } \w+ { homecoming "word" } "." { homecoming "dot" } <<eof>> { homecoming "eof" } . { homecoming "invalid" } /lex /* operators */ %right , or %right not %right qual neg dot %start start %% /* language grammar */ start : exp eof { homecoming $1; } ; exp : exp , exp { $$ = function(obj) { homecoming ($1(obj) && $3(obj)); }; } | exp or exp { $$ = function(obj) { homecoming ($1(obj) || $3(obj)); }; } | not exp { $$ = function(obj) { homecoming !($2(obj)); }; } | open exp close { $$ = $2; } | args { $$ = function(obj) { homecoming parser.processargs(obj, $1)(obj); }; } ; args : arg args { $$ = [ $1, $2]; } | op args { $$ = [ $1, $2]; } | arg { $$ = [ $1 ]; } | op { $$ = [ $1 ]; } ; op : neg arg {{ $2.not = true; $$ = $2; }} | neg arg qual arg {{ $$ = { "not": true, "operator": $2.operand, "operand": $4.operand }; }} | arg qual arg {{ $$ = { "not": false, "operator": $1.operand, "operand": $3.operand }; }} ; arg : quote terms quote {{ $$ = { "not": false, "operator": null, "operand": $2.join(" ") }; }} | term {{ $$ = { "not": false, "operator": null, "operand": $1 }; }} ; terms : term terms { $$ = [ $1 ].concat($2); } | term { $$ = [ $1 ]; } ; term : word dot term { $$ = $1 + $2 + $3; } | word { $$ = $1; } ; %% parser.processargs = function(obj, args) { if (args.length > 1) { if (args[0].operator) homecoming function(obj) { homecoming (parser.matcharg(obj, args[0]) && parser.processargs(args[1])(obj)); }; else homecoming function(obj) { homecoming (parser.matcharg(obj, args[0]) || parser.processargs(args[1])(obj)); }; } else { homecoming function(obj) { homecoming parser.matcharg(obj, args[0]); }; } } /* override later */ parser.matcharg = function(obj, arg) { homecoming true; }
javascript jison
Comments
Post a Comment