require 'test/unit' require 'rockit/grammar' include Rockit class UTestGrammar < Test::Unit::TestCase def test_01_creation g = Rockit::Grammar.new assert_kind_of(Rockit::Grammar, g) end TestGrammar1 = Rockit::Grammar.new do rule :A, [["1", :B, :C]] rule :B, [["2", :D]] term :C, "a" term :D, "b" end def symbols_as_strings(symbols) symbols.map {|s| s.to_s}.sort end def assert_symbols(expected, actual, msg = "") assert_equal(symbols_as_strings(expected), symbols_as_strings(actual), msg) end def test_02_simple_grammar assert_kind_of(Rockit::Grammar, TestGrammar1) assert_equal(2, TestGrammar1.rules.length) assert_symbols([:A, :B], TestGrammar1.nonterminals) assert_equal(2, TestGrammar1.terms.length) assert_symbols([:C, :D], TestGrammar1.terms.keys) assert_kind_of(Rule, ra = TestGrammar1.rules.first) assert_kind_of(Rule, rb = TestGrammar1.rules.last) assert_kind_of(Terminal, TestGrammar1.terms[:C]) assert_kind_of(Terminal, TestGrammar1.terms[:D]) assert_equal(:A, ra.name) assert_equal(3, (rarhs = ra.right_hand_side).length) rarhs1, rarhs2, rarhs3 = rarhs assert_kind_of(StringTerminal, rarhs1) assert_kind_of(NonTerminal, rarhs2) assert_kind_of(NonTerminal, rarhs3) assert_equal("1", rarhs1.string) assert_equal(:B, rarhs2.symbol) assert_equal(:C, rarhs3.symbol) assert_equal(:B, rb.name) assert_equal(2, (rbrhs = rb.right_hand_side).length) rbrhs1, rbrhs2 = rbrhs assert_kind_of(StringTerminal, rbrhs1) assert_kind_of(NonTerminal, rbrhs2) assert_equal("2", rbrhs1.string) assert_equal(:D, rbrhs2.symbol) end Arithmetic = Rockit::Grammar.new do # Additive <- Multitive '+' Additive # / Multitive # Multitive <- Primary '*' Multitive # / Primary # Primary <- '(' Additive ')' # / Decimal # Decimal <- '0' / '1' / '2' / '3' / '4' / '5' / '6' / '7' / '8' / '9' start :Additive, [ [:Multitive, '+', :Additive], [:Multitive], ] rule :Multitive, [ [:Primary, '*', :Multitive], [:Primary] ] rule :Primary, [ ['(', :Additive, ')'], [:Decimal] ] term :Decimal, /[0-9]/ end def test_03_arithmetic_grammar assert_equal(6, Arithmetic.rules.length) assert_symbols([:Additive, :Multitive, :Primary], Arithmetic.nonterminals) assert_equal(1, Arithmetic.terms.length) assert_symbols([:Decimal], Arithmetic.terms.keys) assert_equal(:Additive, Arithmetic.start_symbol) assert_raise(NotImplementedError) {Arithmetic.new_parser.parse("2")} ras = Arithmetic.find_rules(:Additive) assert_equal(2, ras.length) ra1, ra2 = ras assert_equal(:Additive, ra1.name) assert_equal(3, (ra1rhs = ra1.right_hand_side).length) assert_kind_of(NonTerminal, ra1rhs[0]) assert_kind_of(StringTerminal, ra1rhs[1]) assert_kind_of(NonTerminal, ra1rhs[2]) assert_equal(:Multitive, ra1rhs[0].symbol) assert_equal("+", ra1rhs[1].string) assert_equal(:Additive, ra1rhs[2].symbol) assert_equal(:Additive, ra2.name) assert_equal(1, (ra2rhs = ra2.right_hand_side).length) assert_kind_of(NonTerminal, ra2rhs[0]) assert_equal(:Multitive, ra2rhs[0].symbol) td = Arithmetic.terms[:Decimal] assert_equal(:Decimal, td.name) rdrhs1 = td.right_hand_side assert_equal(1, rdrhs1.length) assert_kind_of(RegexpTerminal, rdrhs1[0]) end Operators = Rockit::Grammar.new do start :Number, [ [plus(:Digit), maybe(/e|E/), maybe("-")], [:Dummy] ] rule :Dummy, [[mult("a"), rep("b", 3, 6)]] term :Digit, /[0-9]/ end def test_04_operators assert_equal(3, Operators.rules.length) assert_symbols([:Number, :Dummy], Operators.nonterminals) assert_equal(1, Operators.terms.length) assert_symbols([:Digit], Operators.terms.keys) assert_equal(:Number, Operators.start_symbol) rn1, rn2 = Operators.find_rules(:Number) assert_equal(:Number, rn1.name) assert_equal(3, (rn1rhs = rn1.right_hand_side).length) assert_kind_of(Plus, rn1rhs[0]) assert_kind_of(Maybe, rn1rhs[1]) assert_kind_of(Maybe, rn1rhs[2]) assert_kind_of(NonTerminal, rn1rhs[0].symbol) assert_kind_of(RegexpTerminal, rn1rhs[1].symbol) assert_kind_of(StringTerminal, rn1rhs[2].symbol) end end