rley 0.7.06 → 0.8.01
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +362 -62
- data/.travis.yml +6 -6
- data/CHANGELOG.md +20 -4
- data/LICENSE.txt +1 -1
- data/README.md +7 -7
- data/examples/NLP/engtagger.rb +193 -190
- data/examples/NLP/nano_eng/nano_en_demo.rb +7 -11
- data/examples/NLP/nano_eng/nano_grammar.rb +21 -21
- data/examples/NLP/pico_en_demo.rb +2 -2
- data/examples/data_formats/JSON/cli_options.rb +1 -1
- data/examples/data_formats/JSON/json_ast_builder.rb +21 -27
- data/examples/data_formats/JSON/json_ast_nodes.rb +12 -21
- data/examples/data_formats/JSON/json_demo.rb +1 -2
- data/examples/data_formats/JSON/json_grammar.rb +13 -13
- data/examples/data_formats/JSON/json_lexer.rb +8 -8
- data/examples/data_formats/JSON/json_minifier.rb +1 -1
- data/examples/general/calc_iter1/calc_ast_builder.rb +13 -10
- data/examples/general/calc_iter1/calc_ast_nodes.rb +23 -37
- data/examples/general/calc_iter1/calc_grammar.rb +7 -6
- data/examples/general/calc_iter1/calc_lexer.rb +6 -4
- data/examples/general/calc_iter1/spec/calculator_spec.rb +5 -5
- data/examples/general/calc_iter2/calc_ast_builder.rb +5 -3
- data/examples/general/calc_iter2/calc_ast_nodes.rb +27 -43
- data/examples/general/calc_iter2/calc_grammar.rb +12 -12
- data/examples/general/calc_iter2/calc_lexer.rb +11 -10
- data/examples/general/calc_iter2/spec/calculator_spec.rb +26 -26
- data/examples/general/left.rb +2 -2
- data/examples/general/right.rb +2 -2
- data/lib/rley.rb +1 -1
- data/lib/rley/base/dotted_item.rb +28 -31
- data/lib/rley/base/grm_items_builder.rb +6 -0
- data/lib/rley/constants.rb +2 -2
- data/lib/rley/engine.rb +22 -25
- data/lib/rley/formatter/asciitree.rb +3 -3
- data/lib/rley/formatter/bracket_notation.rb +1 -8
- data/lib/rley/formatter/debug.rb +6 -6
- data/lib/rley/formatter/json.rb +2 -2
- data/lib/rley/gfg/call_edge.rb +1 -1
- data/lib/rley/gfg/edge.rb +5 -5
- data/lib/rley/gfg/end_vertex.rb +2 -6
- data/lib/rley/gfg/epsilon_edge.rb +1 -5
- data/lib/rley/gfg/grm_flow_graph.rb +27 -23
- data/lib/rley/gfg/item_vertex.rb +10 -10
- data/lib/rley/gfg/non_terminal_vertex.rb +4 -4
- data/lib/rley/gfg/scan_edge.rb +1 -1
- data/lib/rley/gfg/shortcut_edge.rb +2 -2
- data/lib/rley/gfg/start_vertex.rb +4 -8
- data/lib/rley/gfg/vertex.rb +43 -39
- data/lib/rley/interface.rb +16 -0
- data/lib/rley/lexical/token_range.rb +6 -6
- data/lib/rley/notation/all_notation_nodes.rb +2 -0
- data/lib/rley/notation/ast_builder.rb +191 -0
- data/lib/rley/notation/ast_node.rb +44 -0
- data/lib/rley/notation/ast_visitor.rb +113 -0
- data/lib/rley/notation/grammar.rb +49 -0
- data/lib/rley/notation/grammar_builder.rb +504 -0
- data/lib/rley/notation/grouping_node.rb +23 -0
- data/lib/rley/notation/parser.rb +56 -0
- data/lib/rley/notation/sequence_node.rb +35 -0
- data/lib/rley/notation/symbol_node.rb +29 -0
- data/lib/rley/notation/tokenizer.rb +192 -0
- data/lib/rley/parse_forest_visitor.rb +5 -5
- data/lib/rley/parse_rep/ast_base_builder.rb +48 -11
- data/lib/rley/parse_rep/cst_builder.rb +5 -6
- data/lib/rley/parse_rep/parse_forest_builder.rb +22 -18
- data/lib/rley/parse_rep/parse_forest_factory.rb +3 -3
- data/lib/rley/parse_rep/parse_rep_creator.rb +14 -16
- data/lib/rley/parse_rep/parse_tree_builder.rb +4 -4
- data/lib/rley/parse_rep/parse_tree_factory.rb +27 -27
- data/lib/rley/parse_tree_visitor.rb +1 -1
- data/lib/rley/parser/error_reason.rb +4 -5
- data/lib/rley/parser/gfg_chart.rb +118 -26
- data/lib/rley/parser/gfg_parsing.rb +22 -33
- data/lib/rley/parser/parse_entry.rb +25 -31
- data/lib/rley/parser/parse_entry_set.rb +19 -16
- data/lib/rley/parser/parse_entry_tracker.rb +4 -4
- data/lib/rley/parser/parse_tracer.rb +13 -13
- data/lib/rley/parser/parse_walker_factory.rb +23 -28
- data/lib/rley/ptree/non_terminal_node.rb +7 -5
- data/lib/rley/ptree/parse_tree.rb +3 -3
- data/lib/rley/ptree/parse_tree_node.rb +5 -5
- data/lib/rley/ptree/terminal_node.rb +7 -7
- data/lib/rley/rley_error.rb +12 -12
- data/lib/rley/sppf/alternative_node.rb +6 -6
- data/lib/rley/sppf/composite_node.rb +7 -7
- data/lib/rley/sppf/epsilon_node.rb +3 -3
- data/lib/rley/sppf/leaf_node.rb +3 -3
- data/lib/rley/sppf/parse_forest.rb +16 -16
- data/lib/rley/sppf/sppf_node.rb +7 -8
- data/lib/rley/sppf/token_node.rb +3 -3
- data/lib/rley/syntax/{grammar_builder.rb → base_grammar_builder.rb} +61 -23
- data/lib/rley/syntax/grammar.rb +5 -5
- data/lib/rley/syntax/grm_symbol.rb +7 -7
- data/lib/rley/syntax/match_closest.rb +43 -0
- data/lib/rley/syntax/non_terminal.rb +9 -15
- data/lib/rley/syntax/production.rb +16 -10
- data/lib/rley/syntax/symbol_seq.rb +7 -9
- data/lib/rley/syntax/terminal.rb +4 -5
- data/lib/rley/syntax/verbatim_symbol.rb +3 -3
- data/lib/support/base_tokenizer.rb +19 -18
- data/spec/rley/base/dotted_item_spec.rb +2 -2
- data/spec/rley/engine_spec.rb +23 -21
- data/spec/rley/formatter/asciitree_spec.rb +7 -7
- data/spec/rley/formatter/bracket_notation_spec.rb +13 -13
- data/spec/rley/formatter/json_spec.rb +1 -1
- data/spec/rley/gfg/end_vertex_spec.rb +5 -5
- data/spec/rley/gfg/grm_flow_graph_spec.rb +2 -2
- data/spec/rley/gfg/item_vertex_spec.rb +10 -10
- data/spec/rley/gfg/non_terminal_vertex_spec.rb +3 -3
- data/spec/rley/gfg/shortcut_edge_spec.rb +1 -1
- data/spec/rley/gfg/start_vertex_spec.rb +5 -5
- data/spec/rley/gfg/vertex_spec.rb +3 -3
- data/spec/rley/lexical/token_range_spec.rb +16 -16
- data/spec/rley/lexical/token_spec.rb +2 -2
- data/spec/rley/notation/grammar_builder_spec.rb +302 -0
- data/spec/rley/notation/parser_spec.rb +184 -0
- data/spec/rley/notation/tokenizer_spec.rb +370 -0
- data/spec/rley/parse_forest_visitor_spec.rb +165 -163
- data/spec/rley/parse_rep/ambiguous_parse_spec.rb +44 -44
- data/spec/rley/parse_rep/ast_builder_spec.rb +6 -7
- data/spec/rley/parse_rep/cst_builder_spec.rb +5 -5
- data/spec/rley/parse_rep/groucho_spec.rb +24 -26
- data/spec/rley/parse_rep/parse_forest_builder_spec.rb +27 -27
- data/spec/rley/parse_rep/parse_forest_factory_spec.rb +8 -8
- data/spec/rley/parse_rep/parse_tree_factory_spec.rb +3 -3
- data/spec/rley/parse_tree_visitor_spec.rb +10 -8
- data/spec/rley/parser/dangling_else_spec.rb +445 -0
- data/spec/rley/parser/error_reason_spec.rb +6 -6
- data/spec/rley/parser/gfg_earley_parser_spec.rb +120 -12
- data/spec/rley/parser/gfg_parsing_spec.rb +6 -13
- data/spec/rley/parser/parse_entry_spec.rb +19 -19
- data/spec/rley/parser/parse_walker_factory_spec.rb +10 -10
- data/spec/rley/ptree/non_terminal_node_spec.rb +5 -3
- data/spec/rley/ptree/parse_tree_node_spec.rb +4 -4
- data/spec/rley/ptree/terminal_node_spec.rb +6 -6
- data/spec/rley/sppf/alternative_node_spec.rb +6 -6
- data/spec/rley/sppf/non_terminal_node_spec.rb +3 -3
- data/spec/rley/sppf/token_node_spec.rb +4 -4
- data/spec/rley/support/ambiguous_grammar_helper.rb +4 -5
- data/spec/rley/support/grammar_abc_helper.rb +3 -5
- data/spec/rley/support/grammar_ambig01_helper.rb +5 -6
- data/spec/rley/support/grammar_arr_int_helper.rb +5 -6
- data/spec/rley/support/grammar_b_expr_helper.rb +5 -6
- data/spec/rley/support/grammar_int_seq_helper.rb +51 -0
- data/spec/rley/support/grammar_l0_helper.rb +14 -17
- data/spec/rley/support/grammar_pb_helper.rb +8 -7
- data/spec/rley/support/grammar_sppf_helper.rb +3 -3
- data/spec/rley/syntax/{grammar_builder_spec.rb → base_grammar_builder_spec.rb} +35 -16
- data/spec/rley/syntax/grammar_spec.rb +6 -6
- data/spec/rley/syntax/grm_symbol_spec.rb +1 -1
- data/spec/rley/syntax/match_closest_spec.rb +46 -0
- data/spec/rley/syntax/non_terminal_spec.rb +8 -8
- data/spec/rley/syntax/production_spec.rb +17 -13
- data/spec/rley/syntax/symbol_seq_spec.rb +2 -2
- data/spec/rley/syntax/terminal_spec.rb +5 -5
- data/spec/rley/syntax/verbatim_symbol_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -12
- data/spec/support/base_tokenizer_spec.rb +7 -2
- metadata +48 -74
- data/.simplecov +0 -7
- data/lib/rley/parser/parse_state.rb +0 -83
- data/lib/rley/parser/parse_state_tracker.rb +0 -59
- data/lib/rley/parser/state_set.rb +0 -101
- data/spec/rley/parser/parse_state_spec.rb +0 -125
- data/spec/rley/parser/parse_tracer_spec.rb +0 -200
- data/spec/rley/parser/state_set_spec.rb +0 -130
@@ -5,33 +5,33 @@ require 'rley' # Load the gem
|
|
5
5
|
|
6
6
|
########################################
|
7
7
|
# Define a grammar for basic arithmetical expressions
|
8
|
-
builder = Rley::
|
8
|
+
builder = Rley::grammar_builder do
|
9
9
|
add_terminals('NUMBER')
|
10
10
|
add_terminals('PLUS', 'MINUS') # For '+', '-' operators or sign
|
11
11
|
add_terminals('STAR', 'DIVIDE', 'POWER') # For '*', '/', '**' operators
|
12
|
-
add_terminals('LPAREN', 'RPAREN') # For '(', ')' delimiters
|
12
|
+
add_terminals('LPAREN', 'RPAREN') # For '(', ')' delimiters
|
13
13
|
add_terminals('PI', 'E') # For numeric constants
|
14
14
|
add_terminals('RESERVED') # Reserved identifiers
|
15
15
|
|
16
|
-
rule 'expression' =>
|
16
|
+
rule 'expression' => 'simple_expression'
|
17
17
|
rule 'simple_expression' => 'term'
|
18
|
-
rule 'simple_expression' =>
|
18
|
+
rule 'simple_expression' => 'simple_expression add_operator term'
|
19
19
|
rule 'term' => 'factor'
|
20
|
-
rule 'term' =>
|
20
|
+
rule 'term' => 'term mul_operator factor'
|
21
21
|
rule 'factor' => 'simple_factor'
|
22
|
-
rule 'factor' =>
|
23
|
-
rule 'simple_factor' =>
|
24
|
-
rule 'simple_factor' =>
|
25
|
-
rule 'simple_factor' =>
|
26
|
-
rule 'simple_factor' => 'in_parenthesis'
|
22
|
+
rule 'factor' => 'factor POWER simple_factor'
|
23
|
+
rule 'simple_factor' => 'sign scalar'
|
24
|
+
rule 'simple_factor' => 'unary_function in_parenthesis'
|
25
|
+
rule 'simple_factor' => 'MINUS in_parenthesis'
|
26
|
+
rule 'simple_factor' => 'in_parenthesis'
|
27
27
|
rule 'sign' => 'PLUS'
|
28
28
|
rule 'sign' => 'MINUS'
|
29
29
|
rule 'sign' => []
|
30
30
|
rule 'scalar' => 'NUMBER'
|
31
31
|
rule 'scalar' => 'PI'
|
32
|
-
rule 'scalar' => 'E'
|
32
|
+
rule 'scalar' => 'E'
|
33
33
|
rule 'unary_function' => 'RESERVED'
|
34
|
-
rule 'in_parenthesis' =>
|
34
|
+
rule 'in_parenthesis' => 'LPAREN expression RPAREN'
|
35
35
|
rule 'add_operator' => 'PLUS'
|
36
36
|
rule 'add_operator' => 'MINUS'
|
37
37
|
rule 'mul_operator' => 'STAR'
|
@@ -10,7 +10,6 @@ class CalcLexer
|
|
10
10
|
attr_reader(:lineno)
|
11
11
|
attr_reader(:line_start)
|
12
12
|
|
13
|
-
|
14
13
|
@@lexeme2name = {
|
15
14
|
'(' => 'LPAREN',
|
16
15
|
')' => 'RPAREN',
|
@@ -22,7 +21,7 @@ class CalcLexer
|
|
22
21
|
'PI' => 'PI',
|
23
22
|
'E' => 'E'
|
24
23
|
}.freeze
|
25
|
-
|
24
|
+
|
26
25
|
@@unary_functions = %w[
|
27
26
|
sin cos tan asin acos atan
|
28
27
|
sqrt cbrt exp ln log
|
@@ -35,7 +34,7 @@ class CalcLexer
|
|
35
34
|
@lineno = 1
|
36
35
|
end
|
37
36
|
|
38
|
-
def tokens
|
37
|
+
def tokens
|
39
38
|
@unary_f_pattern = Regexp.new(@@unary_functions.join('|'))
|
40
39
|
tok_sequence = []
|
41
40
|
until @scanner.eos?
|
@@ -48,11 +47,12 @@ class CalcLexer
|
|
48
47
|
|
49
48
|
private
|
50
49
|
|
51
|
-
|
50
|
+
# rubocop: disable Lint/DuplicateBranch
|
51
|
+
def _next_token
|
52
52
|
skip_whitespaces
|
53
53
|
curr_ch = scanner.peek(1)
|
54
54
|
return nil if curr_ch.nil?
|
55
|
-
|
55
|
+
|
56
56
|
token = nil
|
57
57
|
|
58
58
|
if '()+-/'.include? curr_ch
|
@@ -63,25 +63,26 @@ class CalcLexer
|
|
63
63
|
elsif (lexeme = scanner.scan(/\*|PI|E/))
|
64
64
|
token = build_token(@@lexeme2name[lexeme], lexeme)
|
65
65
|
elsif (lexeme = scanner.scan(@unary_f_pattern))
|
66
|
-
token = build_token('RESERVED', lexeme)
|
66
|
+
token = build_token('RESERVED', lexeme)
|
67
67
|
elsif (lexeme = scanner.scan(/[0-9]+(\.[0-9]+)?([eE][-+]?[0-9])?/))
|
68
68
|
token = build_token('NUMBER', lexeme)
|
69
69
|
else # Unknown token
|
70
70
|
erroneous = curr_ch.nil? ? '' : curr_ch
|
71
71
|
sequel = scanner.scan(/.{1,20}/)
|
72
72
|
erroneous += sequel unless sequel.nil?
|
73
|
-
raise ScanError
|
73
|
+
raise ScanError, "Unknown token #{erroneous}"
|
74
74
|
end
|
75
75
|
|
76
76
|
return token
|
77
77
|
end
|
78
|
-
|
78
|
+
# rubocop: enable Lint/DuplicateBranch
|
79
|
+
|
79
80
|
def build_token(aSymbolName, aLexeme)
|
80
81
|
pos = Rley::Lexical::Position.new(1, scanner.pos)
|
81
|
-
return Rley::Lexical::Token.new(aLexeme, aSymbolName, pos)
|
82
|
+
return Rley::Lexical::Token.new(aLexeme, aSymbolName, pos)
|
82
83
|
end
|
83
84
|
|
84
|
-
def skip_whitespaces
|
85
|
+
def skip_whitespaces
|
85
86
|
scanner.scan(/[ \t\f\n\r]+/)
|
86
87
|
end
|
87
88
|
end # class
|
@@ -17,13 +17,13 @@ describe 'Calculator' do
|
|
17
17
|
engine = Rley::Engine.new do |cfg|
|
18
18
|
cfg.repr_builder = CalcASTBuilder
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
engine.use_grammar(CalcGrammar)
|
22
22
|
raw_result = parse_expression(engine, anExpression)
|
23
23
|
ast = engine.to_ptree(raw_result)
|
24
24
|
return expect(ast.root.interpret)
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def parse_expression(anEngine, anExpression)
|
28
28
|
lexer = CalcLexer.new(anExpression)
|
29
29
|
result = anEngine.parse(lexer.tokens)
|
@@ -40,7 +40,7 @@ describe 'Calculator' do
|
|
40
40
|
|
41
41
|
context 'Parsing valid expressions' do
|
42
42
|
let(:epsilon) { 0.0000000001 }
|
43
|
-
|
43
|
+
|
44
44
|
it 'should evaluate simple integer literals' do
|
45
45
|
expect_expr('2').to eq(2)
|
46
46
|
end
|
@@ -72,18 +72,18 @@ describe 'Calculator' do
|
|
72
72
|
it 'should evaluate the pi constant' do
|
73
73
|
expect_expr('PI').to eq(3.141592653589793)
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
it 'should evaluate the negated pi constant' do
|
77
77
|
expect_expr('-PI').to eq(-3.141592653589793)
|
78
|
-
end
|
78
|
+
end
|
79
79
|
|
80
80
|
it "should evaluate Neper's e constant" do
|
81
81
|
expect_expr('E').to eq(2.718281828459045)
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
it "should evaluate negated Neper's e constant" do
|
85
85
|
expect_expr('-E').to eq(-2.718281828459045)
|
86
|
-
end
|
86
|
+
end
|
87
87
|
|
88
88
|
it 'should evaluate integer addition' do
|
89
89
|
expect_expr('2 + 2').to eq(4)
|
@@ -156,7 +156,7 @@ describe 'Calculator' do
|
|
156
156
|
it 'should evaluate multiple levels of parentheses' do
|
157
157
|
expect_expr('2*(1/(1+3))').to eq(0.5)
|
158
158
|
end
|
159
|
-
|
159
|
+
|
160
160
|
# Some special functions
|
161
161
|
it 'should evaluate square root of expressions' do
|
162
162
|
expect_expr('sqrt(0)').to eq(0)
|
@@ -170,69 +170,69 @@ describe 'Calculator' do
|
|
170
170
|
expect_expr('cbrt(1)').to eq(1)
|
171
171
|
expect_expr('cbrt(1 + 1)').to eq(Math.cbrt(2))
|
172
172
|
expect_expr('cbrt(5 * 5 * 5)').to eq(5)
|
173
|
-
end
|
173
|
+
end
|
174
174
|
|
175
175
|
it 'should evaluate exponential of expressions' do
|
176
|
-
expect_expr('exp(-1)').to eq(1 / Math::E)
|
176
|
+
expect_expr('exp(-1)').to eq(1 / Math::E)
|
177
177
|
expect_expr('exp(0)').to eq(1)
|
178
178
|
expect_expr('exp(1)').to eq(Math::E)
|
179
179
|
expect_expr('exp(2)').to be_within(epsilon).of(Math::E * Math::E)
|
180
180
|
end
|
181
181
|
|
182
182
|
it 'should evaluate natural logarithm of expressions' do
|
183
|
-
expect_expr('ln(1/E)').to eq(-1)
|
184
|
-
expect_expr('ln(1)').to eq(0)
|
183
|
+
expect_expr('ln(1/E)').to eq(-1)
|
184
|
+
expect_expr('ln(1)').to eq(0)
|
185
185
|
expect_expr('ln(E)').to eq(1)
|
186
186
|
expect_expr('ln(E * E)').to eq(2)
|
187
|
-
end
|
187
|
+
end
|
188
188
|
|
189
189
|
it 'should evaluate the logarithm base 10 of expressions' do
|
190
|
-
expect_expr('log(1/10)').to eq(-1)
|
191
|
-
expect_expr('log(1)').to eq(0)
|
190
|
+
expect_expr('log(1/10)').to eq(-1)
|
191
|
+
expect_expr('log(1)').to eq(0)
|
192
192
|
expect_expr('log(10)').to eq(1)
|
193
193
|
expect_expr('log(10 * 10 * 10)').to eq(3)
|
194
|
-
end
|
195
|
-
|
194
|
+
end
|
195
|
+
|
196
196
|
# Trigonometric functions
|
197
|
-
|
197
|
+
|
198
198
|
it 'should compute the sinus of an expression' do
|
199
199
|
expect_expr('sin(0)').to eq(0)
|
200
200
|
expect_expr('sin(PI/6)').to be_within(epsilon).of(0.5)
|
201
201
|
expect_expr('sin(PI/2)').to eq(1)
|
202
202
|
end
|
203
|
-
|
203
|
+
|
204
204
|
it 'should compute the cosinus of an expression' do
|
205
205
|
expect_expr('cos(0)').to eq(1)
|
206
206
|
expect_expr('cos(PI/3)').to be_within(epsilon).of(0.5)
|
207
207
|
expect_expr('cos(PI/2)').to be_within(epsilon).of(0)
|
208
|
-
end
|
208
|
+
end
|
209
209
|
|
210
210
|
it 'should compute the tangent of an expression' do
|
211
211
|
expect_expr('tan(0)').to eq(0)
|
212
212
|
expect_expr('tan(PI/4)').to be_within(epsilon).of(1)
|
213
213
|
expect_expr('tan(5*PI/12)').to be_within(epsilon).of(2 + Math.sqrt(3))
|
214
|
-
end
|
215
|
-
|
214
|
+
end
|
215
|
+
|
216
216
|
# Inverse trigonometric functions
|
217
|
-
|
217
|
+
|
218
218
|
it 'should compute the arcsinus of an expression' do
|
219
219
|
expect_expr('asin(0)').to eq(0)
|
220
220
|
expect_expr('asin(0.5)').to be_within(epsilon).of(Math::PI / 6)
|
221
221
|
expect_expr('asin(1)').to eq(Math::PI / 2)
|
222
222
|
end
|
223
|
-
|
223
|
+
|
224
224
|
it 'should compute the arccosinus of an expression' do
|
225
225
|
expect_expr('acos(1)').to eq(0)
|
226
226
|
expect_expr('acos(0.5)').to be_within(epsilon).of(Math::PI / 3)
|
227
227
|
expect_expr('acos(0)').to be_within(epsilon).of(Math::PI / 2)
|
228
|
-
end
|
228
|
+
end
|
229
229
|
|
230
230
|
it 'should compute the tangent of an expression' do
|
231
231
|
expect_expr('atan(0)').to eq(0)
|
232
232
|
pi = Math::PI
|
233
233
|
expect_expr('atan(1)').to be_within(epsilon).of(pi / 4)
|
234
234
|
expect_expr('atan(2 + sqrt(3))').to be_within(epsilon).of(5 * pi / 12)
|
235
|
-
end
|
235
|
+
end
|
236
236
|
end # context
|
237
237
|
end # describe
|
238
238
|
# End of file
|
data/examples/general/left.rb
CHANGED
@@ -8,10 +8,10 @@ builder = Rley::Syntax::GrammarBuilder.new do
|
|
8
8
|
# The grammar defines a language that consists in a sequence
|
9
9
|
# of 0 or more dots...
|
10
10
|
add_terminals('DOT')
|
11
|
-
|
11
|
+
|
12
12
|
# Grammar with left recursive rule.
|
13
13
|
rule 'l_dots' => []
|
14
|
-
rule 'l_dots' =>
|
14
|
+
rule 'l_dots' => 'l_dots DOT'
|
15
15
|
end
|
16
16
|
|
17
17
|
# And now, let's build the grammar...
|
data/examples/general/right.rb
CHANGED
@@ -8,10 +8,10 @@ builder = Rley::Syntax::GrammarBuilder.new do
|
|
8
8
|
# The grammar defines a language that consists in a sequence
|
9
9
|
# of 0 or more dots...
|
10
10
|
add_terminals('DOT')
|
11
|
-
|
11
|
+
|
12
12
|
# Grammar with right recursive rule.
|
13
13
|
rule 'r_dots' => []
|
14
|
-
rule 'r_dots' =>
|
14
|
+
rule 'r_dots' => 'DOT r_dots'
|
15
15
|
end
|
16
16
|
|
17
17
|
# And now, let's build the grammar...
|
data/lib/rley.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
# for a Rley client.
|
6
6
|
|
7
7
|
require_relative './rley/constants'
|
8
|
-
require_relative './rley/
|
8
|
+
require_relative './rley/interface'
|
9
9
|
require_relative './rley/lexical/token'
|
10
10
|
require_relative './rley/parser/gfg_earley_parser'
|
11
11
|
require_relative './rley/parse_rep/ast_base_builder'
|
@@ -19,14 +19,19 @@ module Rley # This module is used as a namespace
|
|
19
19
|
class DottedItem
|
20
20
|
# Production rule
|
21
21
|
# @return [Syntax::Production]
|
22
|
-
attr_reader
|
22
|
+
attr_reader :production
|
23
23
|
|
24
24
|
# Index of the next symbol (from the rhs) after the 'dot'.
|
25
25
|
# If the dot is at the end of the rhs (i.e.) there is no next
|
26
26
|
# symbol, then the position takes the value -1.
|
27
27
|
# It the rhs is empty, then the position is -2
|
28
28
|
# @return [Integer]
|
29
|
-
attr_reader
|
29
|
+
attr_reader :position
|
30
|
+
|
31
|
+
# A possible constraint between symbol on left of dot and
|
32
|
+
# the closest preceding given terminal
|
33
|
+
# @return [NilClass, Syntax::MatchClosest]
|
34
|
+
attr_accessor :constraint
|
30
35
|
|
31
36
|
# @param aProduction [Syntax::Production]
|
32
37
|
# @param aPosition [Integer] Position of the dot in rhs of production.
|
@@ -37,7 +42,7 @@ module Rley # This module is used as a namespace
|
|
37
42
|
|
38
43
|
# Return a String representation of the dotted item.
|
39
44
|
# @return [String]
|
40
|
-
def to_s
|
45
|
+
def to_s
|
41
46
|
prefix = "#{production.lhs} => "
|
42
47
|
text_values = production.rhs.map(&:to_s)
|
43
48
|
if position.negative?
|
@@ -47,13 +52,13 @@ module Rley # This module is used as a namespace
|
|
47
52
|
end
|
48
53
|
suffix = text_values.join(' ')
|
49
54
|
|
50
|
-
|
55
|
+
prefix + suffix
|
51
56
|
end
|
52
57
|
|
53
58
|
# Return true if the dot position is at the start of the rhs.
|
54
59
|
# @return [Boolean]
|
55
|
-
def at_start?
|
56
|
-
|
60
|
+
def at_start?
|
61
|
+
position.zero? || position == -2
|
57
62
|
end
|
58
63
|
|
59
64
|
# An item with the dot at the beginning is called
|
@@ -62,41 +67,35 @@ module Rley # This module is used as a namespace
|
|
62
67
|
|
63
68
|
# A dotted item is called a reduce item if the dot is at the end.
|
64
69
|
# @return [Boolean]
|
65
|
-
def reduce_item?
|
66
|
-
|
70
|
+
def reduce_item?
|
71
|
+
position.negative? # Either -1 or -2
|
67
72
|
end
|
68
73
|
|
69
74
|
# The non-terminal symbol that is on the left-side of the production
|
70
75
|
# @return [Syntax::NonTerminal]
|
71
|
-
def lhs
|
72
|
-
|
76
|
+
def lhs
|
77
|
+
production.lhs
|
73
78
|
end
|
74
79
|
|
75
80
|
# Return the symbol before the dot.
|
76
81
|
# nil is returned if the dot is at the start of the rhs
|
77
82
|
# @return [Syntax::GrmSymbol, NilClass]
|
78
|
-
def prev_symbol
|
83
|
+
def prev_symbol
|
79
84
|
before_position = prev_position
|
80
|
-
|
81
|
-
nil
|
82
|
-
else
|
83
|
-
production.rhs[before_position]
|
84
|
-
end
|
85
|
-
|
86
|
-
return result
|
85
|
+
before_position.nil? ? nil : production.rhs[before_position]
|
87
86
|
end
|
88
87
|
|
89
88
|
# Return the symbol after the dot.
|
90
89
|
# nil is returned if the dot is at the end
|
91
90
|
# @return [Syntax::GrmSymbol, NilClass]
|
92
|
-
def next_symbol
|
93
|
-
|
91
|
+
def next_symbol
|
92
|
+
position.negative? ? nil : production.rhs[position]
|
94
93
|
end
|
95
94
|
|
96
95
|
# Calculate the position of the dot if were moved by
|
97
96
|
# one step on the left.
|
98
97
|
# @return [Integer]
|
99
|
-
def prev_position
|
98
|
+
def prev_position
|
100
99
|
unless @k_prev_position
|
101
100
|
case position
|
102
101
|
when -2, 0
|
@@ -122,7 +121,7 @@ module Rley # This module is used as a namespace
|
|
122
121
|
to_the_left = prev_position
|
123
122
|
return false if to_the_left.nil?
|
124
123
|
|
125
|
-
|
124
|
+
to_the_left == another.position
|
126
125
|
end
|
127
126
|
|
128
127
|
|
@@ -135,15 +134,13 @@ module Rley # This module is used as a namespace
|
|
135
134
|
raise StandardError, 'Out of bound index'
|
136
135
|
end
|
137
136
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
return index
|
137
|
+
if rhs_size.zero?
|
138
|
+
-2 # Minus 2 at start/end of empty production
|
139
|
+
elsif aPosition == rhs_size
|
140
|
+
-1 # Minus 1 at end of non-empty production
|
141
|
+
else
|
142
|
+
aPosition
|
143
|
+
end
|
147
144
|
end
|
148
145
|
end # class
|
149
146
|
end # module
|
@@ -12,12 +12,18 @@ module Rley # This module is used as a namespace
|
|
12
12
|
def build_dotted_items(aGrammar)
|
13
13
|
items = []
|
14
14
|
aGrammar.rules.each do |prod|
|
15
|
+
index_prev = items.size
|
15
16
|
rhs_size = prod.rhs.size
|
16
17
|
if rhs_size.zero?
|
17
18
|
items << DottedItem.new(prod, 0)
|
18
19
|
else
|
19
20
|
items += (0..rhs_size).map { |i| DottedItem.new(prod, i) }
|
20
21
|
end
|
22
|
+
|
23
|
+
prod.constraints.each do |cs|
|
24
|
+
# Attach constraint to dotted item n + 1
|
25
|
+
items[index_prev + cs.idx_symbol + 1].constraint = cs
|
26
|
+
end
|
21
27
|
end
|
22
28
|
|
23
29
|
return items
|