diff --git a/spec/propane/grammar_spec.rb b/spec/propane/grammar_spec.rb new file mode 100644 index 0000000..823d36a --- /dev/null +++ b/spec/propane/grammar_spec.rb @@ -0,0 +1,145 @@ +class Propane + describe Grammar do + it "parses a user grammar" do + input = <> + +tokenid token_with_no_pattern; + +drop \\s+; + +A -> B << + a = 42; +>> +B -> C while id; +B -> << + b = 0; +>> +EOF + grammar = Grammar.new(input) + expect(grammar.classname).to eq "Foobar" + expect(grammar.modulename).to eq "a.b" + + o = grammar.tokens.find {|token| token.name == "while"} + expect(o).to_not be_nil + expect(o.line_number).to eq 6 + expect(o.id).to eq 0 + + o = grammar.patterns.find {|pattern| pattern.token == o} + expect(o).to_not be_nil + expect(o.pattern).to eq "while" + expect(o.line_number).to eq 6 + expect(o.code_id).to be_nil + expect(o.code).to be_nil + + o = grammar.tokens.find {|token| token.name == "id"} + expect(o).to_not be_nil + expect(o.line_number).to eq 8 + expect(o.id).to eq 1 + + o = grammar.patterns.find {|pattern| pattern.token == o} + expect(o).to_not be_nil + expect(o.pattern).to eq "[a-zA-Z_][a-zA-Z_0-9]*" + expect(o.line_number).to eq 8 + expect(o.code_id).to be_nil + expect(o.code).to be_nil + + o = grammar.tokens.find {|token| token.name == "token_with_code"} + expect(o).to_not be_nil + expect(o.line_number).to eq 11 + expect(o.id).to eq 2 + + o = grammar.patterns.find {|pattern| pattern.token == o} + expect(o).to_not be_nil + expect(o.pattern).to eq "token_with_code" + expect(o.line_number).to eq 11 + expect(o.code_id).to eq 0 + expect(o.code).to eq "Code for the token\n" + + o = grammar.tokens.find {|token| token.name == "token_with_no_pattern"} + expect(o).to_not be_nil + expect(o.line_number).to eq 15 + + o = grammar.patterns.find {|pattern| pattern.token == o} + expect(o).to be_nil + + o = grammar.patterns.find {|pattern| pattern.pattern == "\\s+"} + expect(o).to_not be_nil + expect(o.line_number).to eq 17 + expect(o.token).to be_nil + expect(o.code_id).to be_nil + expect(o.code).to be_nil + + expect(grammar.rules.size).to eq 3 + + o = grammar.rules[0] + expect(o.name).to eq "A" + expect(o.components).to eq %w[B] + expect(o.id).to eq 1 + expect(o.line_number).to eq 19 + expect(o.code).to eq " a = 42;\n" + + o = grammar.rules[1] + expect(o.name).to eq "B" + expect(o.components).to eq %w[C while id] + expect(o.id).to eq 2 + expect(o.line_number).to eq 22 + expect(o.code).to be_nil + + o = grammar.rules[2] + expect(o.name).to eq "B" + expect(o.components).to eq [] + expect(o.id).to eq 3 + expect(o.line_number).to eq 23 + expect(o.code).to eq " b = 0;\n" + end + + it "parses code segments with semicolons" do + input = <> + +token code2 << + writeln("Hello there"); +>> + +tokenid token_with_no_pattern; +EOF + grammar = Grammar.new(input) + + o = grammar.tokens.find {|token| token.name == "code1"} + expect(o).to_not be_nil + expect(o.id).to eq 0 + expect(o.line_number).to eq 1 + + o = grammar.patterns.find {|pattern| pattern.token == o} + expect(o).to_not be_nil + expect(o.code_id).to eq 0 + expect(o.code).to eq " a = b;\n return c;\n" + + o = grammar.tokens.find {|token| token.name == "code2"} + expect(o).to_not be_nil + expect(o.id).to eq 1 + expect(o.line_number).to eq 6 + + o = grammar.patterns.find {|pattern| pattern.token == o} + expect(o).to_not be_nil + expect(o.code_id).to eq 1 + expect(o.code).to eq %[ writeln("Hello there");\n] + end + end +end