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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OTUxODY4MDAzOWE1NjFkYzc5NGFjYzNhZWIxMTRjMmY5NzA4Zjg3Yw==
4
+ YzFjODYyODc0MDUzODcwNDlmYWI0ODhkNTAxNDJjZmVlNTUwMTdiNg==
5
5
  data.tar.gz: !binary |-
6
- ZTRlN2M4ZjUyZDE2MTVkMzBlODdjNjdkZWFjMzk5NjI0ZDI1MjNkZA==
6
+ N2QxZWZlODFjNTBlMzM4NzgzMWMwYzY4YWUzZDI4MTk1ODAwZmY4Nw==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- MWE4NTFmODdjMjk3YTU0NjY5YTFmMmI3ZjRmYzNjMDdlYjYwN2FkOTE1YTc3
10
- ZmE1YjY2MTAwNGIwZTcyMThiOTQ5MjVjZWIzZDM4NTE3YzA4NWY5ZTMyM2Y2
11
- YTQ0YTdkZWE2YjVmYzA3MDE5MjJjNmM1YzE0YzUyMDY0NjBlNDc=
9
+ ZDI3YjJmMjA0Mzg1NjhhNWJhMWZjNGIyNjE5OTg2NGYwMzNhNmUwMDA4ODM5
10
+ ZWI2M2Q5NjAyMGIyODlkOTYxZTMyMjg3NjdkMjgzZDJlNjJmYmJiNTc3MDli
11
+ OTcyZWIwOWFjY2UzMzRlMDA1OWU5ZTlhMDc4MGE0Yzc2MmRmYzE=
12
12
  data.tar.gz: !binary |-
13
- YTFiMTNkZWVjYjVjYzNiMzg4N2E0ZDY0MWFkYWY5OWE0NGI1YjUyYTlkMjRj
14
- YTU2NWM0ZDIwYTE2YWU2MmVjOTg2OTRhZTU0Njk1YjNmNTA0NjVjNDIzNDI2
15
- NDkyMzBiYTc2MWI1ZmVhYTcyMjVkNzVjNTVjMTlmZjMyOTU5YjI=
13
+ NjMzOGViZTZmOTIwMTAwM2FjYTMyZjAyYjYzMmIyMjY0OTM4OTk0NDM3MzAw
14
+ YTEyNzE2NjA0OTA0NTVmZDRkYTJiNDAxMDY1NTE2NjlhM2M2YzNhZTA0OWIy
15
+ NWJkNTQ2M2RjMjAxZmUxMjQ3MmY5OGQ1ZmE2ZjMyYzUwMzhhNDA=
@@ -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.
@@ -3,7 +3,7 @@
3
3
 
4
4
  module Rley # Module used as a namespace
5
5
  # The version number of the gem.
6
- Version = '0.1.05'
6
+ Version = '0.1.06'
7
7
 
8
8
  # Brief description of the gem.
9
9
  Description = "Ruby implementation of the Earley's parsing algorithm"
@@ -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
@@ -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
- attr_writer(:token)
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 '../../../lib/rley/syntax/grammar_builder'
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 = Syntax::GrammarBuilder.new
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.05
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-10 00:00:00.000000000 Z
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