Add verification for grammar
This commit is contained in:
parent
cc435be659
commit
b2d80874e6
11 changed files with 98 additions and 55 deletions
|
@ -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
|
||||||
|
|
6
lib/errors/invalid_grammar.rb
Normal file
6
lib/errors/invalid_grammar.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
module Mm2ep
|
||||||
|
module Depend
|
||||||
|
class InvalidGrammar < Depend::EvalError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -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
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
1
spec/files/grammar_completely_invalid.txt
Normal file
1
spec/files/grammar_completely_invalid.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
false = "Arya"
|
1
spec/files/grammar_partially_invalid.txt
Normal file
1
spec/files/grammar_partially_invalid.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
( a_girl_has_no_name = true ) ANDAND ( character = "Arya Stark" ) OR false AND true
|
46
spec/mm2ep_depend/parser_spec.rb
Normal file
46
spec/mm2ep_depend/parser_spec.rb
Normal 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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue