rley 0.1.05 → 0.1.06
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 +8 -8
- data/CHANGELOG.md +4 -0
- data/lib/rley/constants.rb +1 -1
- data/lib/rley/formatter/debug.rb +0 -6
- data/lib/rley/formatter/json.rb +125 -0
- data/lib/rley/parser/parsing.rb +4 -6
- data/lib/rley/ptree/terminal_node.rb +1 -1
- data/spec/rley/formatter/debug_spec.rb +0 -1
- data/spec/rley/formatter/json_spec.rb +112 -0
- data/spec/rley/ptree/parse_tree_spec.rb +5 -6
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
!binary "U0hBMQ==":
|
|
3
3
|
metadata.gz: !binary |-
|
|
4
|
-
|
|
4
|
+
YzFjODYyODc0MDUzODcwNDlmYWI0ODhkNTAxNDJjZmVlNTUwMTdiNg==
|
|
5
5
|
data.tar.gz: !binary |-
|
|
6
|
-
|
|
6
|
+
N2QxZWZlODFjNTBlMzM4NzgzMWMwYzY4YWUzZDI4MTk1ODAwZmY4Nw==
|
|
7
7
|
!binary "U0hBNTEy":
|
|
8
8
|
metadata.gz: !binary |-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
ZDI3YjJmMjA0Mzg1NjhhNWJhMWZjNGIyNjE5OTg2NGYwMzNhNmUwMDA4ODM5
|
|
10
|
+
ZWI2M2Q5NjAyMGIyODlkOTYxZTMyMjg3NjdkMjgzZDJlNjJmYmJiNTc3MDli
|
|
11
|
+
OTcyZWIwOWFjY2UzMzRlMDA1OWU5ZTlhMDc4MGE0Yzc2MmRmYzE=
|
|
12
12
|
data.tar.gz: !binary |-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
NjMzOGViZTZmOTIwMTAwM2FjYTMyZjAyYjYzMmIyMjY0OTM4OTk0NDM3MzAw
|
|
14
|
+
YTEyNzE2NjA0OTA0NTVmZDRkYTJiNDAxMDY1NTE2NjlhM2M2YzNhZTA0OWIy
|
|
15
|
+
NWJkNTQ2M2RjMjAxZmUxMjQ3MmY5OGQ1ZmE2ZjMyYzUwMzhhNDA=
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
### 0.1.06 / 2014-12-13
|
|
2
|
+
* [NEW] New parse tree formatting class `JSON` for parse tree rendition in JSON.
|
|
3
|
+
* [FIX] Method `Parsing#parse_tree` now add link to Token object for last TerminalNode in tree.
|
|
4
|
+
|
|
1
5
|
### 0.1.05 / 2014-12-10
|
|
2
6
|
* [NEW] New parse tree formatting classes `BaseFormatter` and `Debug`
|
|
3
7
|
* [CHANGE] Method `Parsing#parse_tree` now add links to Token objects in TerminalNodes.
|
data/lib/rley/constants.rb
CHANGED
data/lib/rley/formatter/debug.rb
CHANGED
|
@@ -7,12 +7,6 @@ module Rley # This module is used as a namespace
|
|
|
7
7
|
|
|
8
8
|
# A formatter class that renders the visit notification events
|
|
9
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
10
|
class Debug < BaseFormatter
|
|
17
11
|
# Current indentation level
|
|
18
12
|
attr(:indentation)
|
|
@@ -0,0 +1,125 @@
|
|
|
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 a parse tree in JSON format
|
|
9
|
+
class Json < BaseFormatter
|
|
10
|
+
# Current indentation level
|
|
11
|
+
attr(:indentation)
|
|
12
|
+
|
|
13
|
+
# Array of booleans (one per indentation level).
|
|
14
|
+
# Set to true after first child was visited.
|
|
15
|
+
attr(:sibling_flags)
|
|
16
|
+
|
|
17
|
+
# Constructor.
|
|
18
|
+
# @param anIO [IO] The output stream to which the rendered grammar
|
|
19
|
+
# is written.
|
|
20
|
+
def initialize(anIO)
|
|
21
|
+
super(anIO)
|
|
22
|
+
@indentation = 0
|
|
23
|
+
@sibling_flags = [ false ]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
public
|
|
27
|
+
|
|
28
|
+
# Method called by a ParseTreeVisitor to which the formatter subscribed.
|
|
29
|
+
# Notification of a visit event: the visitor is about to visit the given
|
|
30
|
+
# parse tree
|
|
31
|
+
# @param _ptree [ParseTree]
|
|
32
|
+
def before_ptree(_ptree)
|
|
33
|
+
print_text('', "{\n")
|
|
34
|
+
indent
|
|
35
|
+
print_text('', "\"root\":")
|
|
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_node)
|
|
44
|
+
separator = sibling_flags[-1] ? ",\n" : "\n"
|
|
45
|
+
name = nonterm_node.symbol.name
|
|
46
|
+
print_text(separator, "{ \"#{name}\": ")
|
|
47
|
+
sibling_flags[-1] = true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Method called by a ParseTreeVisitor to which the formatter subscribed.
|
|
51
|
+
# Notification of a visit event: the visitor is about to visit
|
|
52
|
+
# the children of a non-terminal node
|
|
53
|
+
# @param _parent [NonTerminalNode]
|
|
54
|
+
# @param _children [Array] array of children nodes
|
|
55
|
+
def before_children(_parent, _children)
|
|
56
|
+
print_text('[', nil)
|
|
57
|
+
indent
|
|
58
|
+
sibling_flags.push(false)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Method called by a ParseTreeVisitor to which the formatter subscribed.
|
|
62
|
+
# Notification of a visit event: the visitor is about to visit
|
|
63
|
+
# a terminal node
|
|
64
|
+
# @param _term [TerminalNode]
|
|
65
|
+
def before_terminal(term_node)
|
|
66
|
+
separator = sibling_flags[-1] ? ",\n" : "\n"
|
|
67
|
+
name = term_node.symbol.name
|
|
68
|
+
lexeme = term_node.token.lexeme
|
|
69
|
+
print_text(separator, "{\"#{name}\": \"#{lexeme}\"}")
|
|
70
|
+
sibling_flags[-1] = true
|
|
71
|
+
end
|
|
72
|
+
|
|
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
|
+
# the children of a non-terminal node.
|
|
77
|
+
# @param _parent [NonTerminalNode]
|
|
78
|
+
# @param _children [Array] array of children nodes
|
|
79
|
+
def after_children(_parent, _children)
|
|
80
|
+
sibling_flags.pop
|
|
81
|
+
print_text("\n", ']')
|
|
82
|
+
dedent
|
|
83
|
+
print_text("\n", '}')
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# Method called by a ParseTreeVisitor to which the formatter subscribed.
|
|
88
|
+
# Notification of a visit event: the visitor completed the visit of
|
|
89
|
+
# a non-terminal node
|
|
90
|
+
# @param _nonterm [NonTerminalNode]
|
|
91
|
+
def after_non_terminal(_)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# Method called by a ParseTreeVisitor to which the formatter subscribed.
|
|
96
|
+
# Notification of a visit event: the visitor completed the visit
|
|
97
|
+
# of the given parse tree
|
|
98
|
+
# @param _ptree [ParseTree]
|
|
99
|
+
def after_ptree(_ptree)
|
|
100
|
+
dedent
|
|
101
|
+
#print_text("\n", ']')
|
|
102
|
+
dedent
|
|
103
|
+
print_text("\n", '}')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def indent()
|
|
109
|
+
@indentation += 1
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def dedent()
|
|
113
|
+
@indentation -= 1
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def print_text(aSeparator, aText)
|
|
117
|
+
output.print aSeparator
|
|
118
|
+
output.print "#{' ' * 2 * @indentation}#{aText}" unless aText.nil?
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
end # class
|
|
122
|
+
end # module
|
|
123
|
+
end # module
|
|
124
|
+
|
|
125
|
+
# End of file
|
data/lib/rley/parser/parsing.rb
CHANGED
|
@@ -57,6 +57,10 @@ module Rley # This module is used as a namespace
|
|
|
57
57
|
ptree.current_node.range = { low: parse_state.origin }
|
|
58
58
|
node_range = ptree.current_node.range
|
|
59
59
|
ptree.add_children(curr_dotted_item.production, node_range)
|
|
60
|
+
if ptree.current_node.is_a?(PTree::TerminalNode)
|
|
61
|
+
curr_node = ptree.current_node
|
|
62
|
+
curr_node.token = tokens[state_set_index-1] unless curr_node.token
|
|
63
|
+
end
|
|
60
64
|
|
|
61
65
|
when NilClass
|
|
62
66
|
lhs = curr_dotted_item.production.lhs
|
|
@@ -70,7 +74,6 @@ module Rley # This module is used as a namespace
|
|
|
70
74
|
break if ptree.root == ptree.current_node
|
|
71
75
|
end
|
|
72
76
|
end
|
|
73
|
-
|
|
74
77
|
return ptree
|
|
75
78
|
end
|
|
76
79
|
|
|
@@ -149,11 +152,6 @@ module Rley # This module is used as a namespace
|
|
|
149
152
|
candidate_states = last_chart_entry.states_for(start_production)
|
|
150
153
|
return candidate_states.find(&:complete?)
|
|
151
154
|
end
|
|
152
|
-
|
|
153
|
-
# Complete the generated parse tree.
|
|
154
|
-
# Link each terminal node to its corresponding token object.
|
|
155
|
-
def complete_ptree()
|
|
156
|
-
end
|
|
157
155
|
end # class
|
|
158
156
|
end # module
|
|
159
157
|
end # module
|
|
@@ -4,7 +4,7 @@ module Rley # This module is used as a namespace
|
|
|
4
4
|
module PTree # This module is used as a namespace
|
|
5
5
|
class TerminalNode < ParseTreeNode
|
|
6
6
|
# Link to the input token
|
|
7
|
-
|
|
7
|
+
attr(:token, true)
|
|
8
8
|
|
|
9
9
|
def initialize(aTerminalSymbol, aRange)
|
|
10
10
|
super(aTerminalSymbol, aRange)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
require_relative '../../spec_helper'
|
|
2
2
|
require 'stringio'
|
|
3
3
|
|
|
4
|
-
# require_relative '../../../lib/rley/dynamic_grammar'
|
|
5
4
|
require_relative '../support/grammar_abc_helper'
|
|
6
5
|
require_relative '../../../lib/rley/parser/token'
|
|
7
6
|
require_relative '../../../lib/rley/parser/earley_parser'
|
|
@@ -0,0 +1,112 @@
|
|
|
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/json'
|
|
12
|
+
|
|
13
|
+
module Rley # Re-open the module to get rid of qualified names
|
|
14
|
+
module Formatter
|
|
15
|
+
|
|
16
|
+
describe Json 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 { Json.new(StringIO.new('', 'w')) }.not_to raise_error
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'should know its output destination' do
|
|
70
|
+
instance = Json.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 render a parse tree in JSON' do
|
|
79
|
+
instance = Json.new(destination)
|
|
80
|
+
visitor = Rley::ParseTreeVisitor.new(grm_abc_ptree1)
|
|
81
|
+
instance.render(visitor)
|
|
82
|
+
expectations = <<-SNIPPET
|
|
83
|
+
{
|
|
84
|
+
"root":
|
|
85
|
+
{ "S": [
|
|
86
|
+
{ "A": [
|
|
87
|
+
{"a": "a"},
|
|
88
|
+
{ "A": [
|
|
89
|
+
{"a": "a"},
|
|
90
|
+
{ "A": [
|
|
91
|
+
{"b": "b"}
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
{"c": "c"}
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
{"c": "c"}
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
SNIPPET
|
|
104
|
+
expect(destination.string).to eq(expectations.chomp)
|
|
105
|
+
end
|
|
106
|
+
end # context
|
|
107
|
+
end # describe
|
|
108
|
+
|
|
109
|
+
end # module
|
|
110
|
+
end # module
|
|
111
|
+
|
|
112
|
+
# End of file
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
require_relative '../../spec_helper'
|
|
2
2
|
|
|
3
|
-
require_relative '
|
|
3
|
+
require_relative '../support/grammar_abc_helper'
|
|
4
|
+
|
|
4
5
|
# Load the class under test
|
|
5
6
|
require_relative '../../../lib/rley/ptree/parse_tree'
|
|
6
7
|
|
|
7
8
|
module Rley # Open this namespace to avoid module qualifier prefixes
|
|
8
9
|
module PTree # Open this namespace to avoid module qualifier prefixes
|
|
9
10
|
describe ParseTree do
|
|
11
|
+
include GrammarABCHelper # Mix-in module with builder for grammar abc
|
|
12
|
+
|
|
10
13
|
let(:sample_grammar) do
|
|
11
|
-
builder =
|
|
12
|
-
builder.add_terminals('a', 'b', 'c')
|
|
13
|
-
builder.add_production('S' => ['A'])
|
|
14
|
-
builder.add_production('A' => %w(a A c))
|
|
15
|
-
builder.add_production('A' => ['b'])
|
|
14
|
+
builder = grammar_abc_builder
|
|
16
15
|
builder.grammar
|
|
17
16
|
end
|
|
18
17
|
|
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.06
|
|
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-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|
|
@@ -91,6 +91,7 @@ files:
|
|
|
91
91
|
- lib/rley/constants.rb
|
|
92
92
|
- lib/rley/formatter/base_formatter.rb
|
|
93
93
|
- lib/rley/formatter/debug.rb
|
|
94
|
+
- lib/rley/formatter/json.rb
|
|
94
95
|
- lib/rley/parser/chart.rb
|
|
95
96
|
- lib/rley/parser/dotted_item.rb
|
|
96
97
|
- lib/rley/parser/earley_parser.rb
|
|
@@ -114,6 +115,7 @@ files:
|
|
|
114
115
|
- lib/rley/syntax/terminal.rb
|
|
115
116
|
- lib/rley/syntax/verbatim_symbol.rb
|
|
116
117
|
- spec/rley/formatter/debug_spec.rb
|
|
118
|
+
- spec/rley/formatter/json_spec.rb
|
|
117
119
|
- spec/rley/parser/chart_spec.rb
|
|
118
120
|
- spec/rley/parser/dotted_item_spec.rb
|
|
119
121
|
- spec/rley/parser/earley_parser_spec.rb
|
|
@@ -170,6 +172,7 @@ specification_version: 4
|
|
|
170
172
|
summary: Ruby implementation of the Earley's parsing algorithm
|
|
171
173
|
test_files:
|
|
172
174
|
- spec/rley/formatter/debug_spec.rb
|
|
175
|
+
- spec/rley/formatter/json_spec.rb
|
|
173
176
|
- spec/rley/parser/chart_spec.rb
|
|
174
177
|
- spec/rley/parser/dotted_item_spec.rb
|
|
175
178
|
- spec/rley/parser/earley_parser_spec.rb
|