From 7d2e9b289fae25e9350bc43f8082cf2cc9689ba4 Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Fri, 24 Jan 2020 14:43:46 +0100 Subject: [PATCH] add more rules tu parser grammar and write more tests for new rules --- grammar.y | 8 +++ spec/query_lexer_spec.rb | 18 ++++++ spec/query_parser_spec.rb | 129 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) diff --git a/grammar.y b/grammar.y index 7c8657c..5484994 100644 --- a/grammar.y +++ b/grammar.y @@ -1,4 +1,9 @@ class Query + prechigh + left OPERATOR_NOT + left OPERATOR_AND + left OPERATOR_OR + preclow rule target: expression | /* none */ { result = 0 } @@ -7,6 +12,9 @@ class Query | TERM_WITH_QUOTES { result = {:DEFAULT_COLUMN => val[0]} } | TERM_WITHOUT_QUOTES COLON TERM_WITHOUT_QUOTES { result = {val[0] => val[2]} } | TERM_WITHOUT_QUOTES COLON TERM_WITH_QUOTES { result = {val[0] => val[2]} } + | expression OPERATOR_OR expression { result = {:OPERATOR_OR => [val[0], val[2]]} } + | expression OPERATOR_AND expression { result = {:OPERATOR_AND => [val[0], val[2]]} } + | L_BRACKET expression R_BRACKET { result = val[1] } end ---- header diff --git a/spec/query_lexer_spec.rb b/spec/query_lexer_spec.rb index 9fd4e77..b97a65a 100644 --- a/spec/query_lexer_spec.rb +++ b/spec/query_lexer_spec.rb @@ -117,6 +117,24 @@ class QueryLexerTester expect(@result[2][1]).to eq 'JF' end + it 'tests simple query with two columns with name and search terms without quotes' do + @result = @evaluator.tokenize('name:JF tag:mta') + + expect(@result.length).to eq 6 + + expect(@result[0][0]).to eq :TERM_WITHOUT_QUOTES + expect(@result[0][1]).to eq 'name' + expect(@result[1][0]).to eq :COLON + expect(@result[2][0]).to eq :TERM_WITHOUT_QUOTES + expect(@result[2][1]).to eq 'JF' + expect(@result[3][0]).to eq :TERM_WITHOUT_QUOTES + expect(@result[3][1]).to eq 'tag' + expect(@result[4][0]).to eq :COLON + expect(@result[5][0]).to eq :TERM_WITHOUT_QUOTES + expect(@result[5][1]).to eq 'mta' + + end + it 'tests simple query with column name and search term with quotes' do @result = @evaluator.tokenize('name:"name with space"') diff --git a/spec/query_parser_spec.rb b/spec/query_parser_spec.rb index 8e2de5b..f26c4a3 100644 --- a/spec/query_parser_spec.rb +++ b/spec/query_parser_spec.rb @@ -30,6 +30,135 @@ class QueryParserTester expect(@result['tag']).to eq '"tag 120"' end + it 'tests query with two columns connected with OR and search terms without quotes' do + @result = @evaluator.parse('tag:mta OR tag:12') + + @expected_array = [ + { 'tag' => 'mta' }, + { 'tag' => '12' } + ] + + expect(@result.count).to eq 1 + expect(@result[:OPERATOR_OR]).to eq @expected_array + end + + it 'tests query with two columns connected with OR and search terms with quotes' do + @result = @evaluator.parse('tag:mta OR tag:"tag 12"') + + @expected_array = [ + { 'tag' => 'mta' }, + { 'tag' => '"tag 12"' } + ] + + expect(@result.count).to eq 1 + expect(@result[:OPERATOR_OR]).to eq @expected_array + end + + it 'tests query with two columns connected with AND and search terms without quotes' do + @result = @evaluator.parse('tag:mta AND tag:12') + + @expected_array = [ + { 'tag' => 'mta' }, + { 'tag' => '12' } + ] + + expect(@result.count).to eq 1 + expect(@result[:OPERATOR_AND]).to eq @expected_array + end + + it 'tests query with two columns connected with AND and search terms with quotes' do + @result = @evaluator.parse('tag:mta and tag:"tag 12"') + + @expected_array = [ + { 'tag' => 'mta' }, + { 'tag' => '"tag 12"' } + ] + + expect(@result.count).to eq 1 + expect(@result[:OPERATOR_AND]).to eq @expected_array + end + + it 'tests simple query with brackets' do + @result = @evaluator.parse('(123)') + + expect(@result.count).to eq 1 + expect(@result[:DEFAULT_COLUMN]).to eq '123' + end + + it 'tests simple query with brackets and with a column name' do + @result = @evaluator.parse('(name:JF)') + + expect(@result.count).to eq 1 + expect(@result['name']).to eq 'JF' + end + + it 'tests query with OR operator in brackets' do + @result = @evaluator.parse('(name:JF or tag:mta)') + + @expected_array = [ + { 'name' => 'JF' }, + { 'tag' => 'mta' } + ] + + expect(@result.count).to eq 1 + expect(@result[:OPERATOR_OR]).to eq @expected_array + end + + it 'tests query with two simple brackets expressions' do + @result = @evaluator.parse('(name:JF) and (-456)') + + @expected_array = [ + { 'name' => 'JF' }, + { :DEFAULT_COLUMN => '-456' } + ] + + expect(@result.count).to eq 1 + expect(@result[:OPERATOR_AND]).to eq @expected_array + end + + it 'tests query with two brackets expressions' do + @result = @evaluator.parse('(name:JF or tag:"tag 0") and (-456)') + + @expected_array_part_1 = [ + { 'name' => 'JF' }, + { 'tag' => '"tag 0"' } + ] + + @expected_array_total = [ + {:OPERATOR_OR => @expected_array_part_1}, + {:DEFAULT_COLUMN => '-456'} + ] + + expect(@result.count).to eq 1 + expect(@result[:OPERATOR_AND]).to eq @expected_array_total + end + + it 'tests operator precedence' do + @result1 = @evaluator.parse('tag:mta or name:JF and 12_4') + @result2 = @evaluator.parse('tag:mta or (name:JF and 12_4)') + + expect(@result1).to eq @result2 + + expect(@result1.length).to eq 1 + + @expected_array_part_2 = [ + {'name' => 'JF'}, + {:DEFAULT_COLUMN => '12_4'} + ] + + @expected_array_total = [ + {'tag' => 'mta'}, + {:OPERATOR_AND => @expected_array_part_2} + ] + + expect(@result1[:OPERATOR_OR]).to eq @expected_array_total + + end + + # Tests to write : + # * query with multiple column names and search terms without logical operators + # * AND NOT, OR NOT tests + end end