diff --git a/exe/mm2ep-depend b/exe/mm2ep-depend index 94c6eed..40114fe 100755 --- a/exe/mm2ep-depend +++ b/exe/mm2ep-depend @@ -20,7 +20,7 @@ module Mm2ep vars.each do |var| tab_vars[var.split('=')[0]] = var.split('=')[1] end - + # Give vars name and value from shell command to parser parser.names=tab_vars @@ -28,8 +28,11 @@ module Mm2ep pp token puts "RAW : #{line}" puts "EVAL: #{token.to_s}" - exit 1 unless token.errors.empty? + parser.check_grammar line, token + binding.pry + exit 1 unless token.errors.empty? || token.nil? puts "RESULT: #{token.compute}" + end end end diff --git a/lib/errors/invalid_grammar.rb b/lib/errors/invalid_grammar.rb new file mode 100644 index 0000000..a3b8466 --- /dev/null +++ b/lib/errors/invalid_grammar.rb @@ -0,0 +1,6 @@ +module Mm2ep + module Depend + class InvalidGrammar < Depend::EvalError + end + end +end diff --git a/lib/errors/var_not_defined.rb b/lib/errors/var_not_defined.rb index 11c0ed5..2ec0de1 100644 --- a/lib/errors/var_not_defined.rb +++ b/lib/errors/var_not_defined.rb @@ -1,7 +1,6 @@ module Mm2ep module Depend class VarNotDefined < Depend::EvalError - end end end diff --git a/lib/mm2ep_depend.rb b/lib/mm2ep_depend.rb index ef6197f..c5dacf9 100644 --- a/lib/mm2ep_depend.rb +++ b/lib/mm2ep_depend.rb @@ -10,3 +10,4 @@ require 'mm2ep_depend/lexer' require 'mm2ep_depend/parser' require 'mm2ep_depend/eval_error' require 'errors/var_not_defined' +require 'errors/invalid_grammar' diff --git a/lib/mm2ep_depend/eval_error.rb b/lib/mm2ep_depend/eval_error.rb index df75bcb..4425a1a 100644 --- a/lib/mm2ep_depend/eval_error.rb +++ b/lib/mm2ep_depend/eval_error.rb @@ -12,7 +12,6 @@ module Mm2ep @message = hash[:message] @var = hash[:var] end - end end end diff --git a/lib/mm2ep_depend/parser.rb b/lib/mm2ep_depend/parser.rb index aab4c80..2329b1d 100755 --- a/lib/mm2ep_depend/parser.rb +++ b/lib/mm2ep_depend/parser.rb @@ -1,17 +1,13 @@ module Mm2ep module Depend class TreeExpr - def compute raise NotImplementedError end end class TreeValue - - def value - @value - end + attr_reader :value def to_s raise NotImplementedError @@ -29,12 +25,11 @@ module Mm2ep when /false/i then false else value end - if @value.nil? - @errors << VarNotDefined.new( - message:"No value for #{@name}", - var: @name - ) - end + return unless @value.nil? + @errors << VarNotDefined.new( + message: "No value for #{@name}", + var: @name + ) end def compute @@ -167,7 +162,6 @@ module Mm2ep @errors.concat rval.errors @lval = lval @rval = rval - end def compute @@ -181,10 +175,16 @@ module Mm2ep class Parser < Rly::Yacc attr_writer :names - attr_reader :errors - # def names(tab) - # @names = tab - # end + + def check_grammar(line, tokens) + grammar = tokens.to_s.split(/=|AND|OR/) + expr = line.split(/=|AND|OR/) + return if grammar.size == expr.size + return if grammar.empty? + tokens.errors << InvalidGrammar.new( + message: 'Invalid Grammar' + ) + end precedence :left, :OR_OP precedence :left, :AND_OP @@ -232,7 +232,6 @@ module Mm2ep end rule 'expr : VAR EQ_OP bool_expr' do |ex, v, _eq, n| - # binding.pry ex.value = EqOp.new( VarValue.new(v.value.to_s, @names[v.value]), BoolValue.new(n.value) diff --git a/spec/files/grammar_completely_invalid.txt b/spec/files/grammar_completely_invalid.txt new file mode 100644 index 0000000..34d777f --- /dev/null +++ b/spec/files/grammar_completely_invalid.txt @@ -0,0 +1 @@ +false = "Arya" diff --git a/spec/files/grammar_partially_invalid.txt b/spec/files/grammar_partially_invalid.txt new file mode 100644 index 0000000..5724920 --- /dev/null +++ b/spec/files/grammar_partially_invalid.txt @@ -0,0 +1 @@ +( a_girl_has_no_name = true ) ANDAND ( character = "Arya Stark" ) OR false AND true diff --git a/spec/mm2ep_depend/parser_spec.rb b/spec/mm2ep_depend/parser_spec.rb new file mode 100644 index 0000000..ff4250b --- /dev/null +++ b/spec/mm2ep_depend/parser_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' +require 'mm2ep_depend' + +describe Mm2ep::Depend::Parser do + it 'has to report var which is not defined' do + line = File.read(testfile('simple_eq_expr_boolexpr.txt')).delete("\n") + parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) + parser.names = {} + token = parser.parse(line.chomp) + token.errors + .select do |elem| + elem.is_a? Mm2ep::Depend::VarNotDefined + end.size.must_equal 1 + end + + it 'has to report vars which are not defined' do + line = File.read(testfile('simple_expr_or_expr.txt')).delete("\n") + parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) + parser.names = {} + token = parser.parse(line.chomp) + token.errors + .select do |elem| + elem.is_a? Mm2ep::Depend::VarNotDefined + end.size.must_equal 2 + end + + it 'has to report invalid_grammar' do + line = File.read(testfile('grammar_partially_invalid.txt')).delete("\n") + parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) + parser.names = { 'a_girl_has_no_name' => true, 'character' => 'Arya Stark' } + token = parser.parse(line.chomp) + parser.check_grammar line, token + token.errors.select do |elem| + elem.is_a? Mm2ep::Depend::InvalidGrammar + end.size.must_equal 1 + end + + it 'has to be nil when grammar is completely invalid' do + line = File.read(testfile('grammar_completely_invalid.txt')).delete("\n") + parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) + parser.names = {} + token = parser.parse(line.chomp) + parser.check_grammar line, token + assert_nil token + end +end diff --git a/spec/mm2ep_depend/priority_parser_spec.rb b/spec/mm2ep_depend/priority_parser_spec.rb index 902ad70..3774eec 100644 --- a/spec/mm2ep_depend/priority_parser_spec.rb +++ b/spec/mm2ep_depend/priority_parser_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' require 'mm2ep_depend' describe Mm2ep::Depend::Parser do - it 'has to do not before or' do line = File.read(testfile('priority_not_or.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) @@ -30,5 +29,4 @@ describe Mm2ep::Depend::Parser do token = parser.parse(line.chomp) assert_equal(true, token.compute) end - end diff --git a/spec/mm2ep_depend/simple_expr_parser_spec.rb b/spec/mm2ep_depend/simple_expr_parser_spec.rb index 4e2ef3b..ba2d340 100644 --- a/spec/mm2ep_depend/simple_expr_parser_spec.rb +++ b/spec/mm2ep_depend/simple_expr_parser_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' require 'mm2ep_depend' describe Mm2ep::Depend::Parser do - it 'has to apply not on expr' do line = File.read(testfile('simple_not_expr.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) @@ -13,7 +12,7 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate eq with bool expr and return true' do line = File.read(testfile('simple_eq_expr_boolexpr.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => 'true'} + parser.names = { 'truc_bidule' => 'true' } token = parser.parse(line.chomp) assert_equal(true, token.compute) end @@ -21,7 +20,7 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate eq with bool expr and return false' do line = File.read(testfile('simple_eq_expr_boolexpr.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => 'false'} + parser.names = { 'truc_bidule' => 'false' } token = parser.parse(line.chomp) assert_equal(false, token.compute) end @@ -29,7 +28,7 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate eq with number and return true' do line = File.read(testfile('simple_eq_expr_number.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => '10'} + parser.names = { 'truc_bidule' => '10' } token = parser.parse(line.chomp) assert_equal(true, token.compute) end @@ -37,7 +36,7 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate eq with number and return false' do line = File.read(testfile('simple_eq_expr_number.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => '11'} + parser.names = { 'truc_bidule' => '11' } token = parser.parse(line.chomp) assert_equal(false, token.compute) end @@ -45,7 +44,7 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate eq with string and return true' do line = File.read(testfile('simple_eq_expr_string.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => 'test'} + parser.names = { 'truc_bidule' => 'test' } token = parser.parse(line.chomp) assert_equal(true, token.compute) end @@ -53,7 +52,7 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate eq with string and return false' do line = File.read(testfile('simple_eq_expr_string.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => 'tes'} + parser.names = { 'truc_bidule' => 'tes' } token = parser.parse(line.chomp) assert_equal(false, token.compute) end @@ -61,9 +60,8 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate true OR true and return true' do line = File.read(testfile('simple_expr_or_expr.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => 'true', - 'machin' => 'true' - } + parser.names = { 'truc_bidule' => 'true', + 'machin' => 'true' } token = parser.parse(line.chomp) assert_equal(true, token.compute) end @@ -71,9 +69,8 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate true OR false and return true' do line = File.read(testfile('simple_expr_or_expr.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => 'true', - 'machin' => 'false' - } + parser.names = { 'truc_bidule' => 'true', + 'machin' => 'false' } token = parser.parse(line.chomp) assert_equal(true, token.compute) end @@ -81,9 +78,8 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate false OR true and return true' do line = File.read(testfile('simple_expr_or_expr.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => 'false', - 'machin' => 'true' - } + parser.names = { 'truc_bidule' => 'false', + 'machin' => 'true' } token = parser.parse(line.chomp) assert_equal(true, token.compute) end @@ -91,9 +87,8 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate false OR false and return false' do line = File.read(testfile('simple_expr_or_expr.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => 'false', - 'machin' => 'false' - } + parser.names = { 'truc_bidule' => 'false', + 'machin' => 'false' } token = parser.parse(line.chomp) assert_equal(false, token.compute) end @@ -101,9 +96,8 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate true AND true and return true' do line = File.read(testfile('simple_expr_and_expr.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => 'true', - 'machin' => 'true' - } + parser.names = { 'truc_bidule' => 'true', + 'machin' => 'true' } token = parser.parse(line.chomp) assert_equal(true, token.compute) end @@ -111,9 +105,8 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate true AND false and return false' do line = File.read(testfile('simple_expr_and_expr.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => 'true', - 'machin' => 'false' - } + parser.names = { 'truc_bidule' => 'true', + 'machin' => 'false' } token = parser.parse(line.chomp) assert_equal(false, token.compute) end @@ -121,9 +114,8 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate false AND true and return false' do line = File.read(testfile('simple_expr_and_expr.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => 'false', - 'machin' => 'true' - } + parser.names = { 'truc_bidule' => 'false', + 'machin' => 'true' } token = parser.parse(line.chomp) assert_equal(false, token.compute) end @@ -131,11 +123,9 @@ describe Mm2ep::Depend::Parser do it 'has to evaluate false AND false and return false' do line = File.read(testfile('simple_expr_and_expr.txt')).delete("\n") parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) - parser.names={'truc_bidule' => 'false', - 'machin' => 'false' - } + parser.names = { 'truc_bidule' => 'false', + 'machin' => 'false' } token = parser.parse(line.chomp) assert_equal(false, token.compute) end - end