/* description: jio grammar */ /* lexical grammar */ %lex %x letsquote %x endquote %% "\"" {this.begin("letsquote"); return "QUOTE";} <letsquote>(\\\"|[^"])* {this.popState(); this.begin("endquote"); return "QUOTED_STRING";} <endquote>"\"" {this.popState(); return "QUOTE";} [^\S]+ /* skip whitespace */ "(" {return "LEFT_PARENTHESE";} ")" {return "RIGHT_PARENTHESE";} "AND" {return "AND";} "OR" {return "OR";} "NOT" {return "NOT";} ":" {return "DEFINITION";} (\!?\=|\<\=?|\>\=?) {return 'OPERATOR';} [^\s\n"():><!=]+ {return 'WORD';} <<EOF>> {return 'EOF';} /lex /* operator associations and precedence */ %start begin %% /* language grammar */ begin : search_text end { return $1; } ; end : | EOF | NEWLINE ; search_text : and_expression { $$ = $1; } | and_expression search_text { $$ = mkComplexQuery('AND', [$1, $2]); } | and_expression OR search_text { $$ = mkComplexQuery('OR', [$1, $3]); } ; and_expression : boolean_expression { $$ = $1; } | boolean_expression AND and_expression { $$ = mkComplexQuery('AND', [$1, $3]); } ; boolean_expression : NOT expression { $$ = mkNotQuery($2); } | expression { $$ = $1; } ; expression : LEFT_PARENTHESE search_text RIGHT_PARENTHESE { $$ = $2; } | WORD DEFINITION expression { simpleQuerySetKey($3, $1); $$ = $3; } | value { $$ = $1; } ; value : OPERATOR string { $2.operator = $1 ; $$ = $2; } | string { $$ = $1; } ; string : WORD { $$ = mkSimpleQuery('', $1); } | QUOTE QUOTED_STRING QUOTE { $$ = mkSimpleQuery('', $2); } ;