dendroid 0.2.00 → 0.2.02
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 +3 -0
- data/CHANGELOG.md +16 -0
- data/lib/dendroid/formatters/ascii_tree.rb +142 -142
- data/lib/dendroid/formatters/base_formatter.rb +24 -25
- data/lib/dendroid/formatters/bracket_notation.rb +50 -50
- data/lib/dendroid/grm_analysis/dotted_item.rb +0 -1
- data/lib/dendroid/grm_analysis/grm_analyzer.rb +9 -1
- data/lib/dendroid/grm_analysis/rule_items.rb +1 -1
- data/lib/dendroid/parsing/and_node.rb +54 -56
- data/lib/dendroid/parsing/chart_walker.rb +301 -293
- data/lib/dendroid/parsing/composite_parse_node.rb +20 -21
- data/lib/dendroid/parsing/empty_rule_node.rb +28 -28
- data/lib/dendroid/parsing/or_node.rb +46 -51
- data/lib/dendroid/parsing/parse_node.rb +26 -26
- data/lib/dendroid/parsing/parse_tree_visitor.rb +127 -127
- data/lib/dendroid/parsing/terminal_node.rb +32 -32
- data/lib/dendroid/parsing/walk_progress.rb +121 -117
- data/lib/dendroid/recognizer/chart.rb +1 -6
- data/lib/dendroid/recognizer/recognizer.rb +12 -6
- data/lib/dendroid/syntax/grammar.rb +3 -5
- data/lib/dendroid/syntax/rule.rb +1 -1
- data/lib/dendroid.rb +13 -0
- data/spec/dendroid/grm_analysis/dotted_item_spec.rb +1 -1
- data/spec/dendroid/parsing/chart_walker_spec.rb +250 -223
- data/spec/dendroid/parsing/terminal_node_spec.rb +36 -36
- data/spec/dendroid/recognizer/recognizer_spec.rb +0 -1
- data/spec/dendroid/support/sample_grammars.rb +0 -2
- data/version.txt +1 -1
- metadata +3 -4
- data/lib/dendroid/parsing/parser.rb +0 -185
@@ -1,117 +1,121 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'and_node'
|
4
|
-
require_relative 'or_node'
|
5
|
-
require_relative 'terminal_node'
|
6
|
-
require_relative 'empty_rule_node'
|
7
|
-
|
8
|
-
module Dendroid
|
9
|
-
module Parsing
|
10
|
-
class WalkProgress
|
11
|
-
attr_accessor :state
|
12
|
-
attr_accessor :curr_rank
|
13
|
-
attr_reader :curr_item
|
14
|
-
attr_accessor :predecessor
|
15
|
-
attr_reader :parents
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
@
|
22
|
-
@
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
@
|
31
|
-
@
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
node
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
node
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
#
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
next unless node.match(ent)
|
101
|
-
|
102
|
-
matching << [ent, offset]
|
103
|
-
break if stop_at_first
|
104
|
-
end
|
105
|
-
first_iteration = false
|
106
|
-
break if stop_at_first && !matching.empty?
|
107
|
-
|
108
|
-
# Stop loop when parent.origin < min(entries.origin)
|
109
|
-
break if node.range[0] < min_origin
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'and_node'
|
4
|
+
require_relative 'or_node'
|
5
|
+
require_relative 'terminal_node'
|
6
|
+
require_relative 'empty_rule_node'
|
7
|
+
|
8
|
+
module Dendroid
|
9
|
+
module Parsing
|
10
|
+
class WalkProgress
|
11
|
+
attr_accessor :state
|
12
|
+
attr_accessor :curr_rank
|
13
|
+
attr_reader :curr_item
|
14
|
+
attr_accessor :predecessor
|
15
|
+
attr_reader :parents
|
16
|
+
|
17
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
18
|
+
# rubocop: disable Metrics/PerceivedComplexity
|
19
|
+
|
20
|
+
def initialize(start_rank, start_item, parents)
|
21
|
+
@state = :New
|
22
|
+
@curr_rank = start_rank
|
23
|
+
@curr_item = start_item
|
24
|
+
@predecessor = nil
|
25
|
+
@parents = parents
|
26
|
+
end
|
27
|
+
|
28
|
+
# Factory method.
|
29
|
+
def initialize_copy(orig)
|
30
|
+
@state = orig.state
|
31
|
+
@curr_rank = orig.curr_rank
|
32
|
+
@curr_item = orig.curr_item
|
33
|
+
@predecessor = nil
|
34
|
+
@parents = orig.parents.dup
|
35
|
+
end
|
36
|
+
|
37
|
+
def fork(thePredecessor)
|
38
|
+
@state = :Forking
|
39
|
+
@predecessor = thePredecessor
|
40
|
+
end
|
41
|
+
|
42
|
+
def curr_item=(anEntry)
|
43
|
+
raise StandardError if anEntry.nil?
|
44
|
+
|
45
|
+
@curr_item = anEntry
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_node_empty(anEntry)
|
49
|
+
node_empty = EmptyRuleNode.new(anEntry, curr_rank)
|
50
|
+
add_child_node(node_empty)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Add a terminal node for terminal at current rank as a child of last parent
|
54
|
+
def add_terminal_node(token)
|
55
|
+
@curr_rank -= 1
|
56
|
+
term_node = TerminalNode.new(curr_item.prev_symbol, token, curr_rank)
|
57
|
+
add_child_node(term_node)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Add an AND node for given entry as a child of last parent
|
61
|
+
def push_and_node(anEntry)
|
62
|
+
node = ANDNode.new(anEntry, curr_rank)
|
63
|
+
raise StandardError unless anEntry.rule == node.rule # Fails
|
64
|
+
|
65
|
+
add_child_node(node)
|
66
|
+
parents.push(node)
|
67
|
+
|
68
|
+
node
|
69
|
+
end
|
70
|
+
|
71
|
+
def push_or_node(origin, arity)
|
72
|
+
node = OrNode.new(curr_item.prev_symbol, origin, curr_rank, arity)
|
73
|
+
add_child_node(node)
|
74
|
+
parents.push(node)
|
75
|
+
|
76
|
+
node
|
77
|
+
end
|
78
|
+
|
79
|
+
def add_child_node(aNode)
|
80
|
+
parents.last.add_child(aNode, curr_item.position - 1)
|
81
|
+
aNode
|
82
|
+
end
|
83
|
+
|
84
|
+
# Do the given EItems match one of the parent?
|
85
|
+
# Matching = corresponds to the same rule and range
|
86
|
+
# @return [Array<EItem>]
|
87
|
+
def match_parent?(entries, stop_at_first)
|
88
|
+
matching = []
|
89
|
+
min_origin = entries[0].origin
|
90
|
+
first_iteration = true
|
91
|
+
offset = 0
|
92
|
+
|
93
|
+
parents.reverse_each do |node|
|
94
|
+
if node.is_a?(OrNode)
|
95
|
+
offset += 1
|
96
|
+
next
|
97
|
+
end
|
98
|
+
entries.each do |ent|
|
99
|
+
min_origin = ent.origin if first_iteration && ent.origin < min_origin
|
100
|
+
next unless node.match(ent)
|
101
|
+
|
102
|
+
matching << [ent, offset]
|
103
|
+
break if stop_at_first
|
104
|
+
end
|
105
|
+
first_iteration = false
|
106
|
+
break if stop_at_first && !matching.empty?
|
107
|
+
|
108
|
+
# Stop loop when parent.origin < min(entries.origin)
|
109
|
+
break if node.range[0] < min_origin
|
110
|
+
|
111
|
+
offset += 1
|
112
|
+
end
|
113
|
+
|
114
|
+
matching
|
115
|
+
end
|
116
|
+
end # class
|
117
|
+
|
118
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
119
|
+
# rubocop: enable Metrics/PerceivedComplexity
|
120
|
+
end # module
|
121
|
+
end # module
|
@@ -16,7 +16,7 @@ module Dendroid
|
|
16
16
|
attr_reader :item_sets
|
17
17
|
|
18
18
|
# @return [Array<Dendroid::Lexical::Token>] The input tokens
|
19
|
-
|
19
|
+
attr_accessor :tokens
|
20
20
|
|
21
21
|
# @return [Boolean] Indicates whether the recognizer successfully processed the whole input
|
22
22
|
attr_writer :success
|
@@ -48,11 +48,6 @@ module Dendroid
|
|
48
48
|
item_sets.last.add_item(e_item)
|
49
49
|
end
|
50
50
|
|
51
|
-
# @param input_tokens [Array<Dendroid::Lexical::Token>] The input tokens
|
52
|
-
def tokens=(input_tokens)
|
53
|
-
@tokens = input_tokens
|
54
|
-
end
|
55
|
-
|
56
51
|
# Return true if the input text is valid according to the grammar.
|
57
52
|
# @return [Boolean]
|
58
53
|
def successful?
|
@@ -5,7 +5,7 @@ require_relative 'e_item'
|
|
5
5
|
require_relative 'chart'
|
6
6
|
|
7
7
|
module Dendroid
|
8
|
-
# This module host classes needed to implement an Earley recognizer
|
8
|
+
# This module host classes needed to implement an Earley recognizer.
|
9
9
|
module Recognizer
|
10
10
|
# A recognizer determines whether the input text complies to the grammar (syntax) rules.
|
11
11
|
# This class implements the Earley recognition algorithm.
|
@@ -16,6 +16,10 @@ module Dendroid
|
|
16
16
|
# @return [Object]
|
17
17
|
attr_reader :tokenizer
|
18
18
|
|
19
|
+
# rubocop: disable Metrics/AbcSize
|
20
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
21
|
+
# rubocop: disable Metrics/PerceivedComplexity
|
22
|
+
|
19
23
|
# @param grammar [Dendroid::Syntax::Grammar]
|
20
24
|
# @param tokenizer [Object]
|
21
25
|
def initialize(grammar, tokenizer)
|
@@ -120,7 +124,7 @@ module Dendroid
|
|
120
124
|
# Assuming next symbol is a non-terminal
|
121
125
|
#
|
122
126
|
# Error case: next actual token matches none of the expected tokens.
|
123
|
-
def predictor(chart, item, rank, tokens, mode,
|
127
|
+
def predictor(chart, item, rank, tokens, mode, _predicted_symbols)
|
124
128
|
next_symbol = item.next_symbol
|
125
129
|
# if mode == :genuine
|
126
130
|
# predicted_symbols << Set.new if rank == predicted_symbols.size
|
@@ -149,9 +153,7 @@ module Dendroid
|
|
149
153
|
next_item = grm_analysis.next_item(item.dotted_item)
|
150
154
|
return unless next_item
|
151
155
|
|
152
|
-
|
153
|
-
# special = add_item(curr_set, next_item, item.origin, added.shift, :predictor)
|
154
|
-
# added.each { |e| special.add_predecessor(e) }
|
156
|
+
add_item(curr_set, next_item, item.origin, nil, :predictor)
|
155
157
|
end
|
156
158
|
|
157
159
|
# procedure SCANNER((A → α•aβ, j), k, words)
|
@@ -263,7 +265,7 @@ module Dendroid
|
|
263
265
|
|
264
266
|
def expected_terminals(chart)
|
265
267
|
last_set = chart.last
|
266
|
-
terminals = last_set.items.
|
268
|
+
terminals = last_set.items.each_with_object([]) do |ent, result|
|
267
269
|
result << ent.next_symbol if ent.pre_scan?
|
268
270
|
result
|
269
271
|
end
|
@@ -282,5 +284,9 @@ module Dendroid
|
|
282
284
|
end
|
283
285
|
end
|
284
286
|
end # class
|
287
|
+
|
288
|
+
# rubocop: enable Metrics/AbcSize
|
289
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
290
|
+
# rubocop: enable Metrics/PerceivedComplexity
|
285
291
|
end # module
|
286
292
|
end # module
|
@@ -39,6 +39,8 @@ module Dendroid
|
|
39
39
|
add_terminals(terminals)
|
40
40
|
end
|
41
41
|
|
42
|
+
# rubocop: disable Style/IfUnlessModifier
|
43
|
+
|
42
44
|
# Add a rule to the grammar.
|
43
45
|
# @param rule [Dendroid::Syntax::Rule]
|
44
46
|
def add_rule(rule)
|
@@ -55,6 +57,7 @@ module Dendroid
|
|
55
57
|
rules << rule
|
56
58
|
nonterm2production[rule.head] = rule
|
57
59
|
end
|
60
|
+
# rubocop: enable Style/IfUnlessModifier
|
58
61
|
|
59
62
|
# Return the start symbol for the language, that is,
|
60
63
|
# the non-terminal symbol used to denote the top-level
|
@@ -267,11 +270,6 @@ module Dendroid
|
|
267
270
|
end
|
268
271
|
end
|
269
272
|
|
270
|
-
# symbols.each do |sym|
|
271
|
-
# next if sym.terminal?
|
272
|
-
#
|
273
|
-
# sym.nullable = false if sym.nullable.nil?
|
274
|
-
# end
|
275
273
|
symbols.each do |sym|
|
276
274
|
next if sym.terminal? || sym.nullable?
|
277
275
|
|
data/lib/dendroid/syntax/rule.rb
CHANGED
@@ -106,7 +106,7 @@ module Dendroid
|
|
106
106
|
def valid_alternatives(alt)
|
107
107
|
raise StandardError, "Expecting an Array, found a #{rhs.class} instead." unless alt.is_a?(Array)
|
108
108
|
|
109
|
-
if alt.
|
109
|
+
if alt.empty?
|
110
110
|
# A choice must have at least two alternatives
|
111
111
|
raise StandardError, "The choice for `#{head}` must have at least one alternative."
|
112
112
|
end
|
data/lib/dendroid.rb
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# File: dendroid.rb
|
4
|
+
|
3
5
|
# Namespace for all modules, classes and constants from Dendroid library.
|
4
6
|
module Dendroid
|
5
7
|
end # module
|
8
|
+
|
9
|
+
|
10
|
+
# This file acts as a jumping-off point for loading dependencies expected
|
11
|
+
# for a Dendroid client.
|
12
|
+
|
13
|
+
require_relative './dendroid/grm_dsl/base_grm_builder'
|
14
|
+
require_relative './dendroid/utils/base_tokenizer'
|
15
|
+
require_relative './dendroid/recognizer/recognizer'
|
16
|
+
require_relative './dendroid/parsing/chart_walker'
|
17
|
+
require_relative './dendroid/parsing/parse_tree_visitor'
|
18
|
+
require_relative './dendroid//formatters/ascii_tree'
|
@@ -61,7 +61,7 @@ describe Dendroid::GrmAnalysis::DottedItem do
|
|
61
61
|
expect(described_class.new(choice, 0, 1)).not_to be_final_pos
|
62
62
|
expect(described_class.new(choice, 2, 1)).not_to be_final_pos
|
63
63
|
expect(described_class.new(choice, 3, 1)).to be_final_pos
|
64
|
-
expect(described_class.new(choice, 3,1)).to be_completed
|
64
|
+
expect(described_class.new(choice, 3, 1)).to be_completed
|
65
65
|
|
66
66
|
# Case of an empty alternative
|
67
67
|
expect(described_class.new(choice, 0, 2)).to be_final_pos
|