rley 0.5.02 → 0.5.03

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,10 +6,12 @@ require 'coveralls'
6
6
 
7
7
  Coveralls.wear!
8
8
 
9
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
10
- SimpleCov::Formatter::HTMLFormatter,
11
- Coveralls::SimpleCov::Formatter
12
- ])
9
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
10
+ [
11
+ SimpleCov::Formatter::HTMLFormatter,
12
+ Coveralls::SimpleCov::Formatter
13
+ ]
14
+ )
13
15
 
14
16
  require 'pp' # Use pretty-print for debugging purposes
15
17
  require 'rspec' # Use the RSpec framework
@@ -25,5 +27,4 @@ RSpec.configure do |config|
25
27
  config.full_backtrace = true
26
28
  end
27
29
 
28
-
29
30
  # End of file
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.5.02
4
+ version: 0.5.03
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-08 00:00:00.000000000 Z
11
+ date: 2017-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coveralls
@@ -146,12 +146,6 @@ files:
146
146
  - examples/general/calc_iter1/calc_lexer.rb
147
147
  - examples/general/calc_iter1/calc_parser.rb
148
148
  - examples/general/calc_iter1/spec/calculator_spec.rb
149
- - examples/general/calc_iter2/calc_ast_builder.rb
150
- - examples/general/calc_iter2/calc_ast_nodes.rb
151
- - examples/general/calc_iter2/calc_demo.rb
152
- - examples/general/calc_iter2/calc_grammar.rb
153
- - examples/general/calc_iter2/calc_lexer.rb
154
- - examples/general/calc_iter2/calc_parser.rb
155
149
  - lib/rley.rb
156
150
  - lib/rley/constants.rb
157
151
  - lib/rley/formatter/asciitree.rb
@@ -1,186 +0,0 @@
1
- require_relative 'calc_ast_nodes'
2
-
3
- # The purpose of a CalcASTBuilder is to build piece by piece an AST
4
- # (Abstract Syntax Tree) from a sequence of input tokens and
5
- # visit events produced by walking over a GFGParsing object.
6
- # Uses the Builder GoF pattern.
7
- # The Builder pattern creates a complex object
8
- # (say, a parse tree) from simpler objects (terminal and non-terminal
9
- # nodes) and using a step by step approach.
10
- class CalcASTBuilder < Rley::Parser::ParseTreeBuilder
11
- Terminal2NodeClass = {
12
- # Plus sign character is ambiguous. It can represent an operator
13
- # or a positive value
14
- '+' => { 'add_operator[0]' => CalcAddNode, 'sign[0]' => PTree::TerminalNode },
15
- # Minus sign character is ambiguous. It can represent an operator
16
- # or a negative value
17
- '-' => { 'add_operator[1]' => CalcSubtractNode, 'sign[1]' => CalcNegateNode },
18
- '*' => CalcMultiplyNode,
19
- '/' => CalcDivideNode,
20
- 'number' => CalcNumberNode
21
- }
22
-
23
- protected
24
-
25
- def return_first_child(_range, _tokens, theChildren)
26
- return theChildren[0]
27
- end
28
-
29
- def return_second_child(_range, _tokens, theChildren)
30
- return theChildren[1]
31
- end
32
-
33
- def return_last_child(_range, _tokens, theChildren)
34
- return theChildren[-1]
35
- end
36
-
37
- # Overriding method.
38
- # Create a parse tree object with given
39
- # node as root node.
40
- def create_tree(aRootNode)
41
- return Rley::PTree::ParseTree.new(aRootNode)
42
- end
43
-
44
- # Overriding method.
45
- # Factory method for creating a node object for the given
46
- # input token.
47
- # @param aTerminal [Terminal] Terminal symbol associated with the token
48
- # @param aTokenPosition [Integer] Position of token in the input stream
49
- # @param aToken [Token] The input token
50
- def new_leaf_node(aProduction, aTerminal, aTokenPosition, aToken)
51
- klass = Terminal2NodeClass.fetch(aTerminal.name, CalcTerminalNode)
52
- klass = klass[aProduction.name] if klass.is_a?(Hash) # Lexical ambiguity
53
- return klass.new(aToken, aTokenPosition)
54
- end
55
-
56
-
57
- # Method to override.
58
- # Factory method for creating a parent node object.
59
- # @param aProduction [Production] Production rule
60
- # @param aRange [Range] Range of tokens matched by the rule
61
- # @param theTokens [Array] The input tokens
62
- # @param theChildren [Array] Children nodes (one per rhs symbol)
63
- def new_parent_node(aProduction, aRange, theTokens, theChildren)
64
- node = case aProduction.name
65
- when 'expression[0]' # rule 'expression' => %w[sign simple_expression]
66
- reduce_expression_0(aProduction, aRange, theTokens, theChildren)
67
-
68
- # when /value\[\d\]/
69
- # return_first_child(aRange, theTokens, theChildren)
70
-
71
- # when 'object[0]'
72
- # reduce_object_0(aProduction, aRange, theTokens, theChildren)
73
-
74
- # when 'object[1]'
75
- # reduce_object_1(aRange, theTokens, theChildren)
76
-
77
- # when 'member-list[0]'
78
- # reduce_member_list_0(aRange, theTokens, theChildren)
79
-
80
- # when 'member-list[1]'
81
- # reduce_member_list_1(aProduction, aRange, theTokens, theChildren)
82
-
83
- # when 'member[0]'
84
- # reduce_member_0(aProduction, aRange, theTokens, theChildren)
85
-
86
- # when 'array[0]'
87
- # reduce_array_0(aProduction, aRange, theTokens, theChildren)
88
-
89
- # when 'array[1]'
90
- # reduce_array_1(aRange, theTokens, theChildren)
91
-
92
- # when 'array-items[0]'
93
- # reduce_array_items_0(aRange, theTokens, theChildren)
94
-
95
- when 'sign[0]' # rule 'sign' => 'PLUS'
96
- return_first_child(aRange, theTokens, theChildren)
97
-
98
- when 'sign[1]' # rule 'sign' => 'MINUS'
99
- return_first_child(aRange, theTokens, theChildren)
100
-
101
- when 'sign[2]' #rule 'sign' => []
102
- reduce_sign_2(aProduction, aRange, theTokens, theChildren)
103
- else
104
- raise StandardError, "Don't know production #{aProduction.name}"
105
- end
106
-
107
- return node
108
- end
109
-
110
- # rule 'expression' => %w[sign simple_expression]
111
- def reduce_expression_0(aProduction, aRange, theTokens, theChildren)
112
- sign = theChildren[0]
113
- # Check type of sign
114
- node = if sign && sign.kind_of?(CalcNegateNode)
115
- sign.members << theChildren.last
116
- else
117
- theChildren.last
118
- end
119
-
120
- return node
121
- end
122
-
123
- # rule 'sign' => []
124
- def reduce_sign_2(aProduction, aRange, theTokens, theChildren)
125
- return nil # TODO; check whether this make sense
126
- end
127
- =begin
128
- second_child = theChildren[1]
129
- second_child.symbol = aProduction.lhs
130
- return second_child
131
- end
132
-
133
- # rule 'object' => %w[begin-object end-object]
134
- def reduce_object_1(aRange, theTokens, theChildren)
135
- return CalcObjectNode.new(aProduction.lhs)
136
- end
137
-
138
- # rule 'member-list' => %w[member-list value-separator member]
139
- def reduce_member_list_0(aRange, theTokens, theChildren)
140
- node = theChildren[0]
141
- node.members << theChildren.last
142
- return node
143
- end
144
-
145
- # rule 'member-list' => 'member'
146
- def reduce_member_list_1(aProduction, aRange, theTokens, theChildren)
147
- node = CalcObjectNode.new(aProduction.lhs)
148
- node.members << theChildren[0]
149
- return node
150
- end
151
-
152
- # rule 'member' => %w[string name-separator value]
153
- def reduce_member_0(aProduction, aRange, theTokens, theChildren)
154
- return CalcPair.new(theChildren[0], theChildren[2], aProduction.lhs)
155
- end
156
-
157
- # rule 'object' => %w[begin-object member-list end-object]
158
- def reduce_array_0(aProduction, aRange, theTokens, theChildren)
159
- second_child = theChildren[1]
160
- second_child.symbol = aProduction.lhs
161
- return second_child
162
- end
163
-
164
-
165
- # rule 'array' => %w[begin-array end-array]
166
- def reduce_array_1(aRange, theTokens, theChildren)
167
- return CalcArrayNode.new
168
- end
169
-
170
- # rule 'array-items' => %w[array-items value-separator value]
171
- def reduce_array_items_0(aRange, theTokens, theChildren)
172
- node = theChildren[0]
173
- node.children << theChildren[2]
174
- return node
175
- end
176
-
177
-
178
-
179
- # rule 'array-items' => %w[value]
180
- def reduce_array_items_1(aProduction, aRange, theTokens, theChildren)
181
- node = CalcArrayNode.new(aProduction.lhs)
182
- node.children << theChildren[0]
183
- return node
184
- end
185
- =end
186
- end # class
@@ -1,151 +0,0 @@
1
- # Classes that implement nodes of Abstract Syntax Trees (AST) representing
2
- # calculator parse results.
3
-
4
-
5
- CalcTerminalNode = Struct.new(:token, :value, :position) do
6
- def initialize(aToken, aPosition)
7
- self.token = aToken
8
- self.position = aPosition
9
- init_value(aToken.lexeme)
10
- end
11
-
12
- # This method can be overriden
13
- def init_value(aLiteral)
14
- self.value = aLiteral.dup
15
- end
16
-
17
- def symbol()
18
- self.token.terminal
19
- end
20
-
21
- def to_ruby()
22
- return value
23
- end
24
-
25
- # Part of the 'visitee' role in Visitor design pattern.
26
- # @param aVisitor[ParseTreeVisitor] the visitor
27
- def accept(aVisitor)
28
- aVisitor.visit_terminal(self)
29
- end
30
- end
31
-
32
- class CalcNumberNode < CalcTerminalNode
33
- def init_value(aLiteral)
34
- case aLiteral
35
- when /^[+-]?\d+$/
36
- self.value = aLiteral.to_i
37
-
38
- when /^[+-]?\d+(\.\d+)?([eE][+-]?\d+)?$/
39
- self.value = aLiteral.to_f
40
- end
41
- end
42
- end
43
-
44
- class CalcCompositeNode
45
- attr_accessor(:children)
46
- attr_accessor(:symbol)
47
-
48
- def initialize(aSymbol)
49
- @symbol = aSymbol
50
- @children = []
51
- end
52
-
53
- # Part of the 'visitee' role in Visitor design pattern.
54
- # @param aVisitor[ParseTreeVisitor] the visitor
55
- def accept(aVisitor)
56
- aVisitor.visit_nonterminal(self)
57
- end
58
-
59
- alias subnodes children
60
-
61
- end # class
62
-
63
- class CalcUnaryOpNode < CalcCompositeNode
64
- def initialize(aSymbol)
65
- super(aSymbol)
66
- end
67
-
68
- # Convert this tree node in a simpler Ruby representation.
69
- # Basically a Calc object corresponds to a Ruhy Hash
70
- def to_ruby()
71
- rep = {}
72
- members.each do |pair|
73
- rep[pair.name.to_ruby] = pair.value.to_ruby
74
- end
75
-
76
- return rep
77
- end
78
-
79
- alias members children
80
- end # class
81
-
82
- class CalcNegateNode CalcUnaryOpNode
83
- end # class
84
-
85
- class CalcBinaryOpNode < CalcCompositeNode
86
- def initialize(aSymbol)
87
- super(aSymbol)
88
- end
89
-
90
- end # class
91
-
92
- class CalcAddNode < CalcBinaryOpNode
93
-
94
- # Convert this tree node in a simpler Ruby representation.
95
- # Basically a Calc object corresponds to a Ruhy Hash
96
- def to_ruby()
97
- rep = []
98
- children.each do |child|
99
- rep << child.to_ruby
100
- end
101
-
102
- return rep
103
- end
104
- end # class
105
-
106
-
107
- class CalcSubtractNode < CalcBinaryOpNode
108
-
109
- # Convert this tree node in a simpler Ruby representation.
110
- # Basically a Calc object corresponds to a Ruhy Hash
111
- def to_ruby()
112
- rep = []
113
- children.each do |child|
114
- rep << child.to_ruby
115
- end
116
-
117
- return rep
118
- end
119
- end # class
120
-
121
- class CalcMultiplyNode < CalcBinaryOpNode
122
-
123
- # Convert this tree node in a simpler Ruby representation.
124
- # Basically a Calc object corresponds to a Ruhy Hash
125
- def to_ruby()
126
- rep = []
127
- children.each do |child|
128
- rep << child.to_ruby
129
- end
130
-
131
- return rep
132
- end
133
- end # class
134
-
135
- class CalcDivideNode < CalcBinaryOpNode
136
-
137
- # Convert this tree node in a simpler Ruby representation.
138
- # Basically a Calc object corresponds to a Ruhy Hash
139
- def to_ruby()
140
- rep = []
141
- children.each do |child|
142
- rep << child.to_ruby
143
- end
144
-
145
- return rep
146
- end
147
- end # class
148
-
149
-
150
-
151
-
@@ -1,40 +0,0 @@
1
- require_relative 'calc_parser'
2
-
3
- # Create a calculator parser object
4
- parser = CalcParser.new
5
-
6
- # Parse the input expression in command-line
7
- if ARGV.empty?
8
- my_name = File.basename(__FILE__)
9
- msg = <<-END_MSG
10
- Command-line symtax:
11
- ruby #{my_name} "arithmetic expression"
12
- where:
13
- the arithmetic expression is enclosed between double quotes (")
14
-
15
- Example:
16
- ruby #{my_name} "2 * 3 + (4 - 1)"
17
- END_MSG
18
- puts msg
19
- exit(1)
20
- end
21
- puts ARGV[0]
22
- result = parser.parse_expression(ARGV[0])
23
-
24
- unless result.success?
25
- # Stop if the parse failed...
26
- puts "Parsing of '#{ARGV[0]}' failed"
27
- puts "Reason: #{result.failure_reason.message}"
28
- exit(1)
29
- end
30
-
31
- # Generate a parse tree from the parse result
32
- ptree = result.parse_tree
33
-
34
- # Let's create a parse tree visitor
35
- visitor = Rley::ParseTreeVisitor.new(ptree)
36
-
37
- # Now output formatted parse tree
38
- renderer = Rley::Formatter::Asciitree.new($stdout)
39
- renderer.render(visitor)
40
- # End of file
@@ -1,28 +0,0 @@
1
- # Grammar for simple arithmetical expressions
2
- require 'rley' # Load the gem
3
-
4
- ########################################
5
- # Define a grammar for basic arithmetical expressions
6
- builder = Rley::Syntax::GrammarBuilder.new do
7
- add_terminals('NUMBER')
8
- add_terminals('LPAREN', 'RPAREN') # For '(', ')' delimiters
9
- add_terminals('PLUS', 'MINUS') # For '+', '-' operators or sign
10
- add_terminals('STAR', 'DIVIDE') # For '*', '/' operators
11
- rule 'expression' => %w[sign simple_expression]
12
- rule 'simple_expression' => 'term'
13
- rule 'simple_expression' => %w[simple_expression add_operator term]
14
- rule 'term' => 'factor'
15
- rule 'term' => %w[term mul_operator factor]
16
- rule 'factor' => 'NUMBER'
17
- rule 'factor' => %w[LPAREN expression RPAREN]
18
- rule 'sign' => 'PLUS'
19
- rule 'sign' => 'MINUS'
20
- rule 'sign' => []
21
- rule 'add_operator' => 'PLUS'
22
- rule 'add_operator' => 'MINUS'
23
- rule 'mul_operator' => 'STAR'
24
- rule 'mul_operator' => 'DIVIDE'
25
- end
26
-
27
- # And now build the grammar...
28
- CalcGrammar = builder.grammar