Add verification for grammar

This commit is contained in:
Roguelearg 2017-09-15 12:52:29 +02:00
parent cc435be659
commit b2d80874e6
11 changed files with 98 additions and 55 deletions

View file

@ -20,7 +20,7 @@ module Mm2ep
vars.each do |var| vars.each do |var|
tab_vars[var.split('=')[0]] = var.split('=')[1] tab_vars[var.split('=')[0]] = var.split('=')[1]
end end
# Give vars name and value from shell command to parser # Give vars name and value from shell command to parser
parser.names=tab_vars parser.names=tab_vars
@ -28,8 +28,11 @@ module Mm2ep
pp token pp token
puts "RAW : #{line}" puts "RAW : #{line}"
puts "EVAL: #{token.to_s}" 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}" puts "RESULT: #{token.compute}"
end end
end end
end end

View file

@ -0,0 +1,6 @@
module Mm2ep
module Depend
class InvalidGrammar < Depend::EvalError
end
end
end

View file

@ -1,7 +1,6 @@
module Mm2ep module Mm2ep
module Depend module Depend
class VarNotDefined < Depend::EvalError class VarNotDefined < Depend::EvalError
end end
end end
end end

View file

@ -10,3 +10,4 @@ require 'mm2ep_depend/lexer'
require 'mm2ep_depend/parser' require 'mm2ep_depend/parser'
require 'mm2ep_depend/eval_error' require 'mm2ep_depend/eval_error'
require 'errors/var_not_defined' require 'errors/var_not_defined'
require 'errors/invalid_grammar'

View file

@ -12,7 +12,6 @@ module Mm2ep
@message = hash[:message] @message = hash[:message]
@var = hash[:var] @var = hash[:var]
end end
end end
end end
end end

View file

@ -1,17 +1,13 @@
module Mm2ep module Mm2ep
module Depend module Depend
class TreeExpr class TreeExpr
def compute def compute
raise NotImplementedError raise NotImplementedError
end end
end end
class TreeValue class TreeValue
attr_reader :value
def value
@value
end
def to_s def to_s
raise NotImplementedError raise NotImplementedError
@ -29,12 +25,11 @@ module Mm2ep
when /false/i then false when /false/i then false
else value else value
end end
if @value.nil? return unless @value.nil?
@errors << VarNotDefined.new( @errors << VarNotDefined.new(
message:"No value for #{@name}", message: "No value for #{@name}",
var: @name var: @name
) )
end
end end
def compute def compute
@ -167,7 +162,6 @@ module Mm2ep
@errors.concat rval.errors @errors.concat rval.errors
@lval = lval @lval = lval
@rval = rval @rval = rval
end end
def compute def compute
@ -181,10 +175,16 @@ module Mm2ep
class Parser < Rly::Yacc class Parser < Rly::Yacc
attr_writer :names attr_writer :names
attr_reader :errors
# def names(tab) def check_grammar(line, tokens)
# @names = tab grammar = tokens.to_s.split(/=|AND|OR/)
# end 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, :OR_OP
precedence :left, :AND_OP precedence :left, :AND_OP
@ -232,7 +232,6 @@ module Mm2ep
end end
rule 'expr : VAR EQ_OP bool_expr' do |ex, v, _eq, n| rule 'expr : VAR EQ_OP bool_expr' do |ex, v, _eq, n|
# binding.pry
ex.value = EqOp.new( ex.value = EqOp.new(
VarValue.new(v.value.to_s, @names[v.value]), VarValue.new(v.value.to_s, @names[v.value]),
BoolValue.new(n.value) BoolValue.new(n.value)

View file

@ -0,0 +1 @@
false = "Arya"

View file

@ -0,0 +1 @@
( a_girl_has_no_name = true ) ANDAND ( character = "Arya Stark" ) OR false AND true

View file

@ -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

View file

@ -2,7 +2,6 @@ require 'spec_helper'
require 'mm2ep_depend' require 'mm2ep_depend'
describe Mm2ep::Depend::Parser do describe Mm2ep::Depend::Parser do
it 'has to do not before or' do it 'has to do not before or' do
line = File.read(testfile('priority_not_or.txt')).delete("\n") line = File.read(testfile('priority_not_or.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
@ -30,5 +29,4 @@ describe Mm2ep::Depend::Parser do
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(true, token.compute) assert_equal(true, token.compute)
end end
end end

View file

@ -2,7 +2,6 @@ require 'spec_helper'
require 'mm2ep_depend' require 'mm2ep_depend'
describe Mm2ep::Depend::Parser do describe Mm2ep::Depend::Parser do
it 'has to apply not on expr' do it 'has to apply not on expr' do
line = File.read(testfile('simple_not_expr.txt')).delete("\n") line = File.read(testfile('simple_not_expr.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) 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 it 'has to evaluate eq with bool expr and return true' do
line = File.read(testfile('simple_eq_expr_boolexpr.txt')).delete("\n") line = File.read(testfile('simple_eq_expr_boolexpr.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => 'true'} parser.names = { 'truc_bidule' => 'true' }
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(true, token.compute) assert_equal(true, token.compute)
end end
@ -21,7 +20,7 @@ describe Mm2ep::Depend::Parser do
it 'has to evaluate eq with bool expr and return false' do it 'has to evaluate eq with bool expr and return false' do
line = File.read(testfile('simple_eq_expr_boolexpr.txt')).delete("\n") line = File.read(testfile('simple_eq_expr_boolexpr.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => 'false'} parser.names = { 'truc_bidule' => 'false' }
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(false, token.compute) assert_equal(false, token.compute)
end end
@ -29,7 +28,7 @@ describe Mm2ep::Depend::Parser do
it 'has to evaluate eq with number and return true' do it 'has to evaluate eq with number and return true' do
line = File.read(testfile('simple_eq_expr_number.txt')).delete("\n") line = File.read(testfile('simple_eq_expr_number.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => '10'} parser.names = { 'truc_bidule' => '10' }
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(true, token.compute) assert_equal(true, token.compute)
end end
@ -37,7 +36,7 @@ describe Mm2ep::Depend::Parser do
it 'has to evaluate eq with number and return false' do it 'has to evaluate eq with number and return false' do
line = File.read(testfile('simple_eq_expr_number.txt')).delete("\n") line = File.read(testfile('simple_eq_expr_number.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => '11'} parser.names = { 'truc_bidule' => '11' }
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(false, token.compute) assert_equal(false, token.compute)
end end
@ -45,7 +44,7 @@ describe Mm2ep::Depend::Parser do
it 'has to evaluate eq with string and return true' do it 'has to evaluate eq with string and return true' do
line = File.read(testfile('simple_eq_expr_string.txt')).delete("\n") line = File.read(testfile('simple_eq_expr_string.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => 'test'} parser.names = { 'truc_bidule' => 'test' }
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(true, token.compute) assert_equal(true, token.compute)
end end
@ -53,7 +52,7 @@ describe Mm2ep::Depend::Parser do
it 'has to evaluate eq with string and return false' do it 'has to evaluate eq with string and return false' do
line = File.read(testfile('simple_eq_expr_string.txt')).delete("\n") line = File.read(testfile('simple_eq_expr_string.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => 'tes'} parser.names = { 'truc_bidule' => 'tes' }
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(false, token.compute) assert_equal(false, token.compute)
end end
@ -61,9 +60,8 @@ describe Mm2ep::Depend::Parser do
it 'has to evaluate true OR true and return true' do it 'has to evaluate true OR true and return true' do
line = File.read(testfile('simple_expr_or_expr.txt')).delete("\n") line = File.read(testfile('simple_expr_or_expr.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => 'true', parser.names = { 'truc_bidule' => 'true',
'machin' => 'true' 'machin' => 'true' }
}
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(true, token.compute) assert_equal(true, token.compute)
end end
@ -71,9 +69,8 @@ describe Mm2ep::Depend::Parser do
it 'has to evaluate true OR false and return true' do it 'has to evaluate true OR false and return true' do
line = File.read(testfile('simple_expr_or_expr.txt')).delete("\n") line = File.read(testfile('simple_expr_or_expr.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => 'true', parser.names = { 'truc_bidule' => 'true',
'machin' => 'false' 'machin' => 'false' }
}
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(true, token.compute) assert_equal(true, token.compute)
end end
@ -81,9 +78,8 @@ describe Mm2ep::Depend::Parser do
it 'has to evaluate false OR true and return true' do it 'has to evaluate false OR true and return true' do
line = File.read(testfile('simple_expr_or_expr.txt')).delete("\n") line = File.read(testfile('simple_expr_or_expr.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => 'false', parser.names = { 'truc_bidule' => 'false',
'machin' => 'true' 'machin' => 'true' }
}
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(true, token.compute) assert_equal(true, token.compute)
end end
@ -91,9 +87,8 @@ describe Mm2ep::Depend::Parser do
it 'has to evaluate false OR false and return false' do it 'has to evaluate false OR false and return false' do
line = File.read(testfile('simple_expr_or_expr.txt')).delete("\n") line = File.read(testfile('simple_expr_or_expr.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => 'false', parser.names = { 'truc_bidule' => 'false',
'machin' => 'false' 'machin' => 'false' }
}
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(false, token.compute) assert_equal(false, token.compute)
end end
@ -101,9 +96,8 @@ describe Mm2ep::Depend::Parser do
it 'has to evaluate true AND true and return true' do it 'has to evaluate true AND true and return true' do
line = File.read(testfile('simple_expr_and_expr.txt')).delete("\n") line = File.read(testfile('simple_expr_and_expr.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => 'true', parser.names = { 'truc_bidule' => 'true',
'machin' => 'true' 'machin' => 'true' }
}
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(true, token.compute) assert_equal(true, token.compute)
end end
@ -111,9 +105,8 @@ describe Mm2ep::Depend::Parser do
it 'has to evaluate true AND false and return false' do it 'has to evaluate true AND false and return false' do
line = File.read(testfile('simple_expr_and_expr.txt')).delete("\n") line = File.read(testfile('simple_expr_and_expr.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => 'true', parser.names = { 'truc_bidule' => 'true',
'machin' => 'false' 'machin' => 'false' }
}
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(false, token.compute) assert_equal(false, token.compute)
end end
@ -121,9 +114,8 @@ describe Mm2ep::Depend::Parser do
it 'has to evaluate false AND true and return false' do it 'has to evaluate false AND true and return false' do
line = File.read(testfile('simple_expr_and_expr.txt')).delete("\n") line = File.read(testfile('simple_expr_and_expr.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => 'false', parser.names = { 'truc_bidule' => 'false',
'machin' => 'true' 'machin' => 'true' }
}
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(false, token.compute) assert_equal(false, token.compute)
end end
@ -131,11 +123,9 @@ describe Mm2ep::Depend::Parser do
it 'has to evaluate false AND false and return false' do it 'has to evaluate false AND false and return false' do
line = File.read(testfile('simple_expr_and_expr.txt')).delete("\n") line = File.read(testfile('simple_expr_and_expr.txt')).delete("\n")
parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new) parser = Mm2ep::Depend::Parser.new(Mm2ep::Depend::Lexer.new)
parser.names={'truc_bidule' => 'false', parser.names = { 'truc_bidule' => 'false',
'machin' => 'false' 'machin' => 'false' }
}
token = parser.parse(line.chomp) token = parser.parse(line.chomp)
assert_equal(false, token.compute) assert_equal(false, token.compute)
end end
end end