rley 0.1.04 → 0.1.05
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +4 -0
- data/lib/rley/constants.rb +1 -1
- data/lib/rley/formatter/base_formatter.rb +33 -0
- data/lib/rley/formatter/debug.rb +121 -0
- data/lib/rley/parser/parsing.rb +8 -1
- data/spec/rley/formatter/debug_spec.rb +120 -0
- data/spec/rley/parse_tree_visitor_spec.rb +5 -6
- data/spec/rley/support/grammar_abc_helper.rb +19 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OTUxODY4MDAzOWE1NjFkYzc5NGFjYzNhZWIxMTRjMmY5NzA4Zjg3Yw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZTRlN2M4ZjUyZDE2MTVkMzBlODdjNjdkZWFjMzk5NjI0ZDI1MjNkZA==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MWE4NTFmODdjMjk3YTU0NjY5YTFmMmI3ZjRmYzNjMDdlYjYwN2FkOTE1YTc3
|
10
|
+
ZmE1YjY2MTAwNGIwZTcyMThiOTQ5MjVjZWIzZDM4NTE3YzA4NWY5ZTMyM2Y2
|
11
|
+
YTQ0YTdkZWE2YjVmYzA3MDE5MjJjNmM1YzE0YzUyMDY0NjBlNDc=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YTFiMTNkZWVjYjVjYzNiMzg4N2E0ZDY0MWFkYWY5OWE0NGI1YjUyYTlkMjRj
|
14
|
+
YTU2NWM0ZDIwYTE2YWU2MmVjOTg2OTRhZTU0Njk1YjNmNTA0NjVjNDIzNDI2
|
15
|
+
NDkyMzBiYTc2MWI1ZmVhYTcyMjVkNzVjNTVjMTlmZjMyOTU5YjI=
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
### 0.1.05 / 2014-12-10
|
2
|
+
* [NEW] New parse tree formatting classes `BaseFormatter` and `Debug`
|
3
|
+
* [CHANGE] Method `Parsing#parse_tree` now add links to Token objects in TerminalNodes.
|
4
|
+
|
1
5
|
### 0.1.04 / 2014-12-08
|
2
6
|
* [CHANGE] File `parse_tree_visitor_spec.rb`. Added step-by-step test of a parse tree visit.
|
3
7
|
|
data/lib/rley/constants.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Rley # This module is used as a namespace
|
2
|
+
|
3
|
+
# Namespace dedicated to parse tree formatters.
|
4
|
+
module Formatter
|
5
|
+
|
6
|
+
# Superclass for parse tree formatters.
|
7
|
+
class BaseFormatter
|
8
|
+
# The IO output stream in which the formatter's result will be sent.
|
9
|
+
attr(:output)
|
10
|
+
|
11
|
+
# Constructor.
|
12
|
+
# @param anIO [IO] an output IO where the formatter's result will
|
13
|
+
# be placed.
|
14
|
+
def initialize(anIO)
|
15
|
+
@output = anIO
|
16
|
+
end
|
17
|
+
|
18
|
+
public
|
19
|
+
|
20
|
+
# Given a parse tree visitor, perform the visit
|
21
|
+
# and render the visit events in the output stream.
|
22
|
+
# @param aVisitor [ParseTreeVisitor]
|
23
|
+
def render(aVisitor)
|
24
|
+
aVisitor.subscribe(self)
|
25
|
+
aVisitor.start
|
26
|
+
aVisitor.unsubscribe(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
end # class
|
30
|
+
end # module
|
31
|
+
end # module
|
32
|
+
|
33
|
+
# End of file
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require_relative 'base_formatter'
|
2
|
+
|
3
|
+
|
4
|
+
module Rley # This module is used as a namespace
|
5
|
+
# Namespace dedicated to parse tree formatters.
|
6
|
+
module Formatter
|
7
|
+
|
8
|
+
# A formatter class that renders the visit notification events
|
9
|
+
# from a parse tree visitor
|
10
|
+
# @example
|
11
|
+
# some_grammar = ... # Points to a DynamicGrammar-like object
|
12
|
+
# # Output the result to the standard console output
|
13
|
+
# formatter = Sequitur::Formatter::Debug.new(STDOUT)
|
14
|
+
# # Render the visit notifications
|
15
|
+
# formatter.run(some_grammar.visitor)
|
16
|
+
class Debug < BaseFormatter
|
17
|
+
# Current indentation level
|
18
|
+
attr(:indentation)
|
19
|
+
|
20
|
+
# Constructor.
|
21
|
+
# @param anIO [IO] The output stream to which the rendered grammar
|
22
|
+
# is written.
|
23
|
+
def initialize(anIO)
|
24
|
+
super(anIO)
|
25
|
+
@indentation = 0
|
26
|
+
end
|
27
|
+
|
28
|
+
public
|
29
|
+
|
30
|
+
# Method called by a ParseTreeVisitor to which the formatter subscribed.
|
31
|
+
# Notification of a visit event: the visitor is about to visit the given
|
32
|
+
# parse tree
|
33
|
+
# @param _ptree [ParseTree]
|
34
|
+
def before_ptree(_ptree)
|
35
|
+
output_event(__method__, indentation)
|
36
|
+
indent
|
37
|
+
end
|
38
|
+
|
39
|
+
# Method called by a ParseTreeVisitor to which the formatter subscribed.
|
40
|
+
# Notification of a visit event: the visitor is about to visit
|
41
|
+
# a non-terminal node
|
42
|
+
# @param _nonterm [NonTerminalNode]
|
43
|
+
def before_non_terminal(_nonterm)
|
44
|
+
output_event(__method__, indentation)
|
45
|
+
indent
|
46
|
+
end
|
47
|
+
|
48
|
+
# Method called by a ParseTreeVisitor to which the formatter subscribed.
|
49
|
+
# Notification of a visit event: the visitor is about to visit
|
50
|
+
# the children of a non-terminal node
|
51
|
+
# @param _parent [NonTerminalNode]
|
52
|
+
# @param _children [Array] array of children nodes
|
53
|
+
def before_children(_parent, _children)
|
54
|
+
output_event(__method__, indentation)
|
55
|
+
indent
|
56
|
+
end
|
57
|
+
|
58
|
+
# Method called by a ParseTreeVisitor to which the formatter subscribed.
|
59
|
+
# Notification of a visit event: the visitor is about to visit
|
60
|
+
# a terminal node
|
61
|
+
# @param _term [TerminalNode]
|
62
|
+
def before_terminal(_term)
|
63
|
+
output_event(__method__, indentation)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Method called by a ParseTreeVisitor to which the formatter subscribed.
|
67
|
+
# Notification of a visit event: the visitor completed the visit of
|
68
|
+
# a terminal node.
|
69
|
+
# @param _term [TerminalNode]
|
70
|
+
def after_terminal(_term)
|
71
|
+
output_event(__method__, indentation)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Method called by a ParseTreeVisitor to which the formatter subscribed.
|
75
|
+
# Notification of a visit event: the visitor completed the visit of
|
76
|
+
# a non-terminal node
|
77
|
+
# @param _nonterm [NonTerminalNode]
|
78
|
+
def after_non_terminal(_)
|
79
|
+
dedent
|
80
|
+
output_event(__method__, indentation)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Method called by a ParseTreeVisitor to which the formatter subscribed.
|
84
|
+
# Notification of a visit event: the visitor completed the visit of
|
85
|
+
# the children of a non-terminal node.
|
86
|
+
# @param _parent [NonTerminalNode]
|
87
|
+
# @param _children [Array] array of children nodes
|
88
|
+
def after_children(_parent, _children)
|
89
|
+
dedent
|
90
|
+
output_event(__method__, indentation)
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
# Method called by a ParseTreeVisitor to which the formatter subscribed.
|
95
|
+
# Notification of a visit event: the visitor completed the visit
|
96
|
+
# of the given parse tree
|
97
|
+
# @param _ptree [ParseTree]
|
98
|
+
def after_ptree(_ptree)
|
99
|
+
dedent
|
100
|
+
output_event(__method__, indentation)
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def indent()
|
106
|
+
@indentation += 1
|
107
|
+
end
|
108
|
+
|
109
|
+
def dedent()
|
110
|
+
@indentation -= 1
|
111
|
+
end
|
112
|
+
|
113
|
+
def output_event(anEvent, indentationLevel)
|
114
|
+
output.puts "#{' ' * 2 * indentationLevel}#{anEvent}"
|
115
|
+
end
|
116
|
+
|
117
|
+
end # class
|
118
|
+
end # module
|
119
|
+
end # module
|
120
|
+
|
121
|
+
# End of file
|
data/lib/rley/parser/parsing.rb
CHANGED
@@ -42,7 +42,9 @@ module Rley # This module is used as a namespace
|
|
42
42
|
when Syntax::Terminal
|
43
43
|
state_set_index -= 1
|
44
44
|
ptree.step_back(state_set_index)
|
45
|
-
|
45
|
+
if ptree.current_node.is_a?(PTree::TerminalNode)
|
46
|
+
ptree.current_node.token = tokens[state_set_index]
|
47
|
+
end
|
46
48
|
parse_state = chart[state_set_index].predecessor_state(parse_state)
|
47
49
|
curr_dotted_item = parse_state.dotted_rule
|
48
50
|
|
@@ -147,6 +149,11 @@ module Rley # This module is used as a namespace
|
|
147
149
|
candidate_states = last_chart_entry.states_for(start_production)
|
148
150
|
return candidate_states.find(&:complete?)
|
149
151
|
end
|
152
|
+
|
153
|
+
# Complete the generated parse tree.
|
154
|
+
# Link each terminal node to its corresponding token object.
|
155
|
+
def complete_ptree()
|
156
|
+
end
|
150
157
|
end # class
|
151
158
|
end # module
|
152
159
|
end # module
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
# require_relative '../../../lib/rley/dynamic_grammar'
|
5
|
+
require_relative '../support/grammar_abc_helper'
|
6
|
+
require_relative '../../../lib/rley/parser/token'
|
7
|
+
require_relative '../../../lib/rley/parser/earley_parser'
|
8
|
+
require_relative '../../../lib/rley/ptree/parse_tree'
|
9
|
+
require_relative '../../../lib/rley/parse_tree_visitor'
|
10
|
+
# Load the class under test
|
11
|
+
require_relative '../../../lib/rley/formatter/debug'
|
12
|
+
|
13
|
+
module Rley # Re-open the module to get rid of qualified names
|
14
|
+
module Formatter
|
15
|
+
|
16
|
+
describe Debug do
|
17
|
+
include GrammarABCHelper # Mix-in module with builder for grammar abc
|
18
|
+
|
19
|
+
# Factory method. Build a production with the given sequence
|
20
|
+
# of symbols as its rhs.
|
21
|
+
let(:grammar_abc) do
|
22
|
+
builder = grammar_abc_builder
|
23
|
+
builder.grammar
|
24
|
+
end
|
25
|
+
|
26
|
+
# Variables for the terminal symbols
|
27
|
+
let(:a_) { grammar_abc.name2symbol['a'] }
|
28
|
+
let(:b_) { grammar_abc.name2symbol['b'] }
|
29
|
+
let(:c_) { grammar_abc.name2symbol['c'] }
|
30
|
+
|
31
|
+
# Helper method that mimicks the output of a tokenizer
|
32
|
+
# for the language specified by gramma_abc
|
33
|
+
let(:grm_abc_tokens1) do
|
34
|
+
[
|
35
|
+
Parser::Token.new('a', a_),
|
36
|
+
Parser::Token.new('a', a_),
|
37
|
+
Parser::Token.new('b', b_),
|
38
|
+
Parser::Token.new('c', c_),
|
39
|
+
Parser::Token.new('c', c_)
|
40
|
+
]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Factory method that builds a sample parse tree.
|
44
|
+
# Generated tree has the following structure:
|
45
|
+
# S[0,5]
|
46
|
+
# +- A[0,5]
|
47
|
+
# +- a[0,0]
|
48
|
+
# +- A[1,4]
|
49
|
+
# | +- a[1,1]
|
50
|
+
# | +- A[2,3]
|
51
|
+
# | | +- b[2,3]
|
52
|
+
# | +- c[3,4]
|
53
|
+
# +- c[4,5]
|
54
|
+
# Capital letters represent non-terminal nodes
|
55
|
+
let(:grm_abc_ptree1) do
|
56
|
+
parser = Parser::EarleyParser.new(grammar_abc)
|
57
|
+
parse_result = parser.parse(grm_abc_tokens1)
|
58
|
+
parse_result.parse_tree
|
59
|
+
end
|
60
|
+
|
61
|
+
let(:destination) { StringIO.new('', 'w') }
|
62
|
+
|
63
|
+
context 'Standard creation & initialization:' do
|
64
|
+
|
65
|
+
it 'should be initialized with an IO argument' do
|
66
|
+
expect { Debug.new(StringIO.new('', 'w')) }.not_to raise_error
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should know its output destination' do
|
70
|
+
instance = Debug.new(destination)
|
71
|
+
expect(instance.output).to eq(destination)
|
72
|
+
end
|
73
|
+
end # context
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
context 'Formatting events:' do
|
78
|
+
it 'should support visit events of a parse tree' do
|
79
|
+
instance = Debug.new(destination)
|
80
|
+
visitor = Rley::ParseTreeVisitor.new(grm_abc_ptree1)
|
81
|
+
instance.render(visitor)
|
82
|
+
expectations = <<-SNIPPET
|
83
|
+
before_ptree
|
84
|
+
before_non_terminal
|
85
|
+
before_children
|
86
|
+
before_non_terminal
|
87
|
+
before_children
|
88
|
+
before_terminal
|
89
|
+
after_terminal
|
90
|
+
before_non_terminal
|
91
|
+
before_children
|
92
|
+
before_terminal
|
93
|
+
after_terminal
|
94
|
+
before_non_terminal
|
95
|
+
before_children
|
96
|
+
before_terminal
|
97
|
+
after_terminal
|
98
|
+
after_children
|
99
|
+
after_non_terminal
|
100
|
+
before_terminal
|
101
|
+
after_terminal
|
102
|
+
after_children
|
103
|
+
after_non_terminal
|
104
|
+
before_terminal
|
105
|
+
after_terminal
|
106
|
+
after_children
|
107
|
+
after_non_terminal
|
108
|
+
after_children
|
109
|
+
after_non_terminal
|
110
|
+
after_ptree
|
111
|
+
SNIPPET
|
112
|
+
expect(destination.string).to eq(expectations)
|
113
|
+
end
|
114
|
+
end # context
|
115
|
+
end # describe
|
116
|
+
|
117
|
+
end # module
|
118
|
+
end # module
|
119
|
+
|
120
|
+
# End of file
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require_relative '../spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
|
4
|
+
require_relative './support/grammar_abc_helper'
|
4
5
|
require_relative '../../lib/rley/parser/token'
|
5
6
|
require_relative '../../lib/rley/parser/earley_parser'
|
6
7
|
# Load the class under test
|
@@ -8,12 +9,10 @@ require_relative '../../lib/rley/parse_tree_visitor'
|
|
8
9
|
|
9
10
|
module Rley # Open this namespace to avoid module qualifier prefixes
|
10
11
|
describe ParseTreeVisitor do
|
12
|
+
include GrammarABCHelper # Mix-in module with builder for grammar abc
|
13
|
+
|
11
14
|
let(:grammar_abc) do
|
12
|
-
builder =
|
13
|
-
builder.add_terminals('a', 'b', 'c')
|
14
|
-
builder.add_production('S' => ['A'])
|
15
|
-
builder.add_production('A' => %w(a A c))
|
16
|
-
builder.add_production('A' => ['b'])
|
15
|
+
builder = grammar_abc_builder
|
17
16
|
builder.grammar
|
18
17
|
end
|
19
18
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Load the builder class
|
2
|
+
require_relative '../../../lib/rley/syntax/grammar_builder'
|
3
|
+
|
4
|
+
|
5
|
+
module GrammarABCHelper
|
6
|
+
|
7
|
+
# Factory method. Creates a grammar builder for a simple grammar.
|
8
|
+
# (based on example in N. Wirth "Compiler Construction" book, p. 6)
|
9
|
+
def grammar_abc_builder()
|
10
|
+
builder = Rley::Syntax::GrammarBuilder.new
|
11
|
+
builder.add_terminals('a', 'b', 'c')
|
12
|
+
builder.add_production('S' => ['A'])
|
13
|
+
builder.add_production('A' => %w(a A c))
|
14
|
+
builder.add_production('A' => ['b'])
|
15
|
+
|
16
|
+
return builder
|
17
|
+
end
|
18
|
+
end # module
|
19
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rley
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.05
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -89,6 +89,8 @@ files:
|
|
89
89
|
- examples/grammars/grammar_L0.rb
|
90
90
|
- lib/rley.rb
|
91
91
|
- lib/rley/constants.rb
|
92
|
+
- lib/rley/formatter/base_formatter.rb
|
93
|
+
- lib/rley/formatter/debug.rb
|
92
94
|
- lib/rley/parser/chart.rb
|
93
95
|
- lib/rley/parser/dotted_item.rb
|
94
96
|
- lib/rley/parser/earley_parser.rb
|
@@ -111,6 +113,7 @@ files:
|
|
111
113
|
- lib/rley/syntax/symbol_seq.rb
|
112
114
|
- lib/rley/syntax/terminal.rb
|
113
115
|
- lib/rley/syntax/verbatim_symbol.rb
|
116
|
+
- spec/rley/formatter/debug_spec.rb
|
114
117
|
- spec/rley/parser/chart_spec.rb
|
115
118
|
- spec/rley/parser/dotted_item_spec.rb
|
116
119
|
- spec/rley/parser/earley_parser_spec.rb
|
@@ -123,6 +126,7 @@ files:
|
|
123
126
|
- spec/rley/ptree/parse_tree_node_spec.rb
|
124
127
|
- spec/rley/ptree/parse_tree_spec.rb
|
125
128
|
- spec/rley/ptree/token_range_spec.rb
|
129
|
+
- spec/rley/support/grammar_abc_helper.rb
|
126
130
|
- spec/rley/syntax/grammar_builder_spec.rb
|
127
131
|
- spec/rley/syntax/grammar_spec.rb
|
128
132
|
- spec/rley/syntax/grm_symbol_spec.rb
|
@@ -165,6 +169,7 @@ signing_key:
|
|
165
169
|
specification_version: 4
|
166
170
|
summary: Ruby implementation of the Earley's parsing algorithm
|
167
171
|
test_files:
|
172
|
+
- spec/rley/formatter/debug_spec.rb
|
168
173
|
- spec/rley/parser/chart_spec.rb
|
169
174
|
- spec/rley/parser/dotted_item_spec.rb
|
170
175
|
- spec/rley/parser/earley_parser_spec.rb
|