spec/rley/parser/earley_parser_spec.rb in rley-0.2.01 vs spec/rley/parser/earley_parser_spec.rb in rley-0.2.02
- old
+ new
@@ -4,10 +4,11 @@
require_relative '../../../lib/rley/syntax/non_terminal'
require_relative '../../../lib/rley/syntax/production'
require_relative '../../../lib/rley/syntax/grammar_builder'
require_relative '../../../lib/rley/parser/token'
require_relative '../../../lib/rley/parser/dotted_item'
+require_relative '../support/ambiguous_grammar_helper'
# Load the class under test
require_relative '../../../lib/rley/parser/earley_parser'
module Rley # Open this namespace to avoid module qualifier prefixes
module Parser # Open this namespace to avoid module qualifier prefixes
@@ -36,13 +37,13 @@
=end
# Grammar 1: A very simple language
# (based on example in N. Wirth "Compiler Construction" book, p. 6)
- # S ::= A.
- # A ::= "a" A "c".
- # A ::= "b".
+ # S => A.
+ # A => "a" A "c".
+ # A => "b".
# Let's create the grammar piece by piece
let(:nt_S) { Syntax::NonTerminal.new('S') }
let(:nt_A) { Syntax::NonTerminal.new('A') }
let(:a_) { Syntax::VerbatimSymbol.new('a') }
let(:b_) { Syntax::VerbatimSymbol.new('b') }
@@ -331,11 +332,11 @@
"Ss => A A 'x' . | 0", # scan from S(0) 4
]
compare_state_texts(parse_result.chart[1], expected)
end
- it 'should parse an ambiguous grammar' do
+ it 'should parse an ambiguous grammar (I)' do
# Grammar 3: A ambiguous arithmetic expression language
# (based on example in article on Earley's algorithm in Wikipedia)
# P => S.
# S => S "+" S.
# S => S "*" S.
@@ -439,9 +440,81 @@
"S => S . '+' S | 0", # complete from (2) and S(0) 2
"S => S . '*' S | 0" # complete from (2) and S(0) 3
]
compare_state_texts(parse_result.chart[5], expected)
end
+
+ it 'should parse an ambiguous grammar (II)' do
+ self.extend(AmbiguousGrammarHelper)
+ grammar = grammar_builder.grammar
+ instance = EarleyParser.new(grammar)
+ tokens = tokenize('abc + def + ghi', grammar)
+ expect { instance.parse(tokens) }.not_to raise_error
+ parse_result = instance.parse(tokens)
+ expect(parse_result.success?).to eq(true)
+
+ ###################### S(0): . abc + def + ghi
+ # Expectation chart[0]:
+ expected = [
+ 'S => . E | 0', # Start rule
+ 'E => . E + E | 0', # predict from (1)
+ 'E => . id | 0' # predict from (1)
+ ]
+ compare_state_texts(parse_result.chart[0], expected)
+
+ ###################### S(1): abc . + def + ghi
+ # Expectation chart[1]:
+ expected = [
+ 'E => id . | 0', # scan from S(0) 3
+ 'S => E . | 0', # complete from (1) and S(0) 2
+ 'E => E . + E | 0' # complete from (1) and S(0) 3
+ ]
+ compare_state_texts(parse_result.chart[1], expected)
+
+ ###################### S(2): abc + . def + ghi
+ # Expectation chart[2]:
+ expected = [
+ 'E => E + . E | 0', # Scan from S(1) 3
+ 'E => . E + E | 2', # predict from (1)
+ 'E => . id | 2' # predict from (1)
+ ]
+ compare_state_texts(parse_result.chart[2], expected)
+
+ ###################### S(3): abc + def . + ghi
+ # Expectation chart[3]:
+ expected = [
+ 'E => id . | 2', # Scan from S(2) 3
+ 'E => E + E . | 0', # complete from (1) and S(2) 1
+ 'E => E . + E | 2', # complete from (1) and S(2) 2
+ 'S => E . | 0', # complete from (1) and S(0) 1
+ 'E => E . + E | 0' # complete from (1) and S(0) 2
+ ]
+ compare_state_texts(parse_result.chart[3], expected)
+
+ ###################### S(4): abc + def + . ghi
+ # Expectation chart[4]:
+ expected = [
+ 'E => E + . E | 2', # Scan from S(3) 3
+ 'E => E + . E | 0', # Scan from S(3) 5
+ 'E => . E + E | 4', # predict from (1)
+ 'E => . id | 4' # predict from (1)
+ ]
+ compare_state_texts(parse_result.chart[4], expected)
+
+ ###################### S(5): abc + def + ghi .
+ # Expectation chart[5]:
+ expected = [
+ 'E => id . | 4', # Scan from S(4) 4
+ 'E => E + E . | 2', # complete from (1) and S(4) 1
+ 'E => E + E . | 0', # complete from (1) and S(4) 2
+ 'E => E . + E | 4', # complete from (1) and S(4) 3
+ 'E => E . + E | 2', # complete from (1) and S(2) 2
+ 'S => E . | 0', # complete from (1) and S(0) 1
+ 'E => E . + E | 0', # complete from (1) and S(0) 2
+ ]
+ compare_state_texts(parse_result.chart[5], expected)
+ end
+
it 'should parse an invalid simple input' do
# Parse an erroneous input (b is missing)
wrong = [