rley 0.8.03 → 0.8.05

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +28 -8
  3. data/CHANGELOG.md +10 -0
  4. data/examples/data_formats/JSON/README.md +34 -0
  5. data/examples/data_formats/JSON/sample01.json +3 -0
  6. data/examples/data_formats/JSON/sample01.svg +36 -0
  7. data/examples/data_formats/JSON/sample02.json +6 -0
  8. data/examples/data_formats/JSON/sample02.svg +128 -0
  9. data/examples/data_formats/JSON/sample03.json +88 -0
  10. data/examples/general/calc_iter1/README.md +26 -0
  11. data/examples/general/calc_iter2/README.md +55 -0
  12. data/examples/general/general_examples.md +37 -0
  13. data/examples/tokenizer/README.md +46 -0
  14. data/examples/tokenizer/loxxy_raw_scanner.rex +98 -0
  15. data/examples/tokenizer/loxxy_raw_scanner.rex.rb +256 -0
  16. data/examples/tokenizer/loxxy_tokenizer.rb +94 -0
  17. data/examples/tokenizer/run_tokenizer.rb +29 -0
  18. data/lib/rley/constants.rb +1 -1
  19. data/lib/rley/lexical/literal.rb +29 -0
  20. data/lib/rley/lexical/token.rb +7 -4
  21. data/lib/rley/syntax/base_grammar_builder.rb +0 -2
  22. data/lib/rley.rb +1 -1
  23. data/spec/rley/lexical/literal_spec.rb +33 -0
  24. data/spec/rley/lexical/token_spec.rb +15 -4
  25. data/spec/rley/notation/grammar_builder_spec.rb +2 -2
  26. data/spec/rley/parser/dangling_else_spec.rb +5 -7
  27. data/spec/rley/parser/gfg_chart_spec.rb +0 -1
  28. data/spec/rley/parser/gfg_earley_parser_spec.rb +131 -134
  29. data/spec/rley/parser/gfg_parsing_spec.rb +1 -2
  30. data/spec/rley/syntax/base_grammar_builder_spec.rb +7 -7
  31. data/spec/rley/syntax/grammar_spec.rb +6 -9
  32. metadata +19 -9
  33. data/lib/rley/parser/parse_tracer.rb +0 -103
  34. data/lib/rley/syntax/literal.rb +0 -20
  35. data/lib/rley/syntax/verbatim_symbol.rb +0 -27
  36. data/spec/rley/syntax/literal_spec.rb +0 -31
  37. data/spec/rley/syntax/verbatim_symbol_spec.rb +0 -38
@@ -0,0 +1,98 @@
1
+ # rubocop: disable Style/MutableConstant
2
+ # rubocop: disable Layout/SpaceBeforeSemicolon
3
+ # rubocop: disable Style/Alias
4
+ # rubocop: disable Style/AndOr
5
+ # rubocop: disable Style/MultilineIfModifier
6
+ # rubocop: disable Style/StringLiterals
7
+ # rubocop: disable Style/MethodDefParentheses
8
+ # rubocop: disable Security/Open
9
+ # rubocop: disable Style/TrailingCommaInArrayLiteral
10
+ # rubocop: disable Layout/EmptyLinesAroundMethodBody
11
+ # rubocop: disable Style/WhileUntilDo
12
+ # rubocop: disable Style/MultilineWhenThen
13
+ # rubocop: disable Layout/ExtraSpacing
14
+ # rubocop: disable Layout/SpaceInsideRangeLiteral
15
+ # rubocop: disable Style/CaseEquality
16
+ # rubocop: disable Style/EmptyCaseCondition
17
+ # rubocop: disable Style/SymbolArray
18
+ # rubocop: disable Lint/DuplicateBranch
19
+ # rubocop: disable Layout/EmptyLineBetweenDefs
20
+ # rubocop: disable Layout/IndentationConsistency
21
+
22
+ class LoxxyRawScanner
23
+ option
24
+ lineno
25
+ column
26
+
27
+ macro
28
+ DIGIT /\d/
29
+ ALPHA /[a-zA-Z_]/
30
+
31
+ rule
32
+ # Delimiters, punctuators, operators
33
+ /[ \t]+/
34
+ /\/\/[^\r\n]*/
35
+ /\r|\n/ newline
36
+ /[!=<>]=?/ { [:SPECIAL, text] }
37
+ /[(){},;.\-+\/*]/ { [:SPECIAL, text] }
38
+
39
+ # Literals & identifiers
40
+ /#{DIGIT}+(\.#{DIGIT}+)?/ { [:NUMBER, text] }
41
+ /nil/ { [:NIL, text] }
42
+ /false/ { [:FALSE, text] }
43
+ /true/ { [:TRUE, text] }
44
+ /#{ALPHA}(#{ALPHA}|#{DIGIT})*/ { [:IDENTIFIER, text] }
45
+ /""/ { [:STRING, '""'] }
46
+ /"/ :IN_STRING
47
+
48
+ :IN_STRING /[^"]+/ { [:STRING, "\"#{text}\""] }
49
+ :IN_STRING /"/ nil
50
+
51
+ inner
52
+
53
+ def do_parse
54
+ tokens = []
55
+ while (tok = next_token) do
56
+ (type, lexeme) = tok
57
+ if type == :state
58
+ self.state = lexeme
59
+ next
60
+ else
61
+ tokens << [type, lexeme, lineno, column]
62
+ end
63
+ end
64
+
65
+ tokens
66
+ end
67
+
68
+ def newline(txt)
69
+ if txt == '\r'
70
+ ss.skip(/\n/) # CR LF sequence
71
+
72
+ self.lineno += 1
73
+ self.start_of_current_line_pos = ss.pos + 1
74
+ end
75
+
76
+ nil
77
+ end
78
+ end
79
+ # rubocop: enable Style/MutableConstant
80
+ # rubocop: enable Layout/SpaceBeforeSemicolon
81
+ # rubocop: enable Style/Alias
82
+ # rubocop: enable Style/AndOr
83
+ # rubocop: enable Style/MultilineIfModifier
84
+ # rubocop: enable Style/StringLiterals
85
+ # rubocop: enable Style/MethodDefParentheses
86
+ # rubocop: enable Security/Open
87
+ # rubocop: enable Style/TrailingCommaInArrayLiteral
88
+ # rubocop: enable Layout/EmptyLinesAroundMethodBody
89
+ # rubocop: enable Style/WhileUntilDo
90
+ # rubocop: enable Style/MultilineWhenThen
91
+ # rubocop: enable Layout/ExtraSpacing
92
+ # rubocop: enable Layout/SpaceInsideRangeLiteral
93
+ # rubocop: enable Style/CaseEquality
94
+ # rubocop: enable Style/EmptyCaseCondition
95
+ # rubocop: enable Style/SymbolArray
96
+ # rubocop: enable Lint/DuplicateBranch
97
+ # rubocop: enable Layout/EmptyLineBetweenDefs
98
+ # rubocop: enable Layout/IndentationConsistency
@@ -0,0 +1,256 @@
1
+ # frozen_string_literal: true
2
+
3
+ # encoding: UTF-8
4
+ #--
5
+ # This file is automatically generated. Do not modify it.
6
+ # Generated by: oedipus_lex version 2.5.3.
7
+ # Source: loxxy_raw_scanner.rex
8
+ #++
9
+
10
+ # rubocop: disable Style/MutableConstant
11
+ # rubocop: disable Layout/SpaceBeforeSemicolon
12
+ # rubocop: disable Style/Alias
13
+ # rubocop: disable Style/AndOr
14
+ # rubocop: disable Style/MultilineIfModifier
15
+ # rubocop: disable Style/StringLiterals
16
+ # rubocop: disable Style/MethodDefParentheses
17
+ # rubocop: disable Security/Open
18
+ # rubocop: disable Style/TrailingCommaInArrayLiteral
19
+ # rubocop: disable Layout/EmptyLinesAroundMethodBody
20
+ # rubocop: disable Style/WhileUntilDo
21
+ # rubocop: disable Style/MultilineWhenThen
22
+ # rubocop: disable Layout/ExtraSpacing
23
+ # rubocop: disable Layout/SpaceInsideRangeLiteral
24
+ # rubocop: disable Style/CaseEquality
25
+ # rubocop: disable Style/EmptyCaseCondition
26
+ # rubocop: disable Style/SymbolArray
27
+ # rubocop: disable Lint/DuplicateBranch
28
+ # rubocop: disable Layout/EmptyLineBetweenDefs
29
+ # rubocop: disable Layout/IndentationConsistency
30
+
31
+
32
+ ##
33
+ # The generated lexer LoxxyRawScanner
34
+
35
+ class LoxxyRawScanner
36
+ require 'strscan'
37
+
38
+ # :stopdoc:
39
+ DIGIT = /\d/
40
+ ALPHA = /[a-zA-Z_]/
41
+ # :startdoc:
42
+ # :stopdoc:
43
+ class LexerError < StandardError ; end
44
+ class ScanError < LexerError ; end
45
+ # :startdoc:
46
+
47
+ ##
48
+ # The current line number.
49
+
50
+ attr_accessor :lineno
51
+ ##
52
+ # The file name / path
53
+
54
+ attr_accessor :filename
55
+
56
+ ##
57
+ # The StringScanner for this lexer.
58
+
59
+ attr_accessor :ss
60
+
61
+ ##
62
+ # The current lexical state.
63
+
64
+ attr_accessor :state
65
+
66
+ alias :match :ss
67
+
68
+ ##
69
+ # The match groups for the current scan.
70
+
71
+ def matches
72
+ m = (1..9).map { |i| ss[i] }
73
+ m.pop until m[-1] or m.empty?
74
+ m
75
+ end
76
+
77
+ ##
78
+ # Yields on the current action.
79
+
80
+ def action
81
+ yield
82
+ end
83
+
84
+ ##
85
+ # The previous position. Only available if the :column option is on.
86
+
87
+ attr_accessor :old_pos
88
+
89
+ ##
90
+ # The position of the start of the current line. Only available if the
91
+ # :column option is on.
92
+
93
+ attr_accessor :start_of_current_line_pos
94
+
95
+ ##
96
+ # The current column, starting at 0. Only available if the
97
+ # :column option is on.
98
+ def column
99
+ old_pos - start_of_current_line_pos
100
+ end
101
+
102
+
103
+ ##
104
+ # The current scanner class. Must be overridden in subclasses.
105
+
106
+ def scanner_class
107
+ StringScanner
108
+ end unless instance_methods(false).map(&:to_s).include?("scanner_class")
109
+
110
+ ##
111
+ # Parse the given string.
112
+
113
+ def parse str
114
+ self.ss = scanner_class.new str
115
+ self.lineno = 1
116
+ self.start_of_current_line_pos = 0
117
+ self.state ||= nil
118
+
119
+ do_parse
120
+ end
121
+
122
+ ##
123
+ # Read in and parse the file at +path+.
124
+
125
+ def parse_file path
126
+ self.filename = path
127
+ open path do |f|
128
+ parse f.read
129
+ end
130
+ end
131
+
132
+ ##
133
+ # The current location in the parse.
134
+
135
+ def location
136
+ [
137
+ (filename || "<input>"),
138
+ lineno,
139
+ column,
140
+ ].compact.join(":")
141
+ end
142
+
143
+ ##
144
+ # Lex the next token.
145
+
146
+ def next_token
147
+
148
+ token = nil
149
+
150
+ until ss.eos? or token do
151
+ if ss.peek(1) == "\n"
152
+ self.lineno += 1
153
+ # line starts 1 position after the newline
154
+ self.start_of_current_line_pos = ss.pos + 1
155
+ end
156
+ self.old_pos = ss.pos
157
+ token =
158
+ case state
159
+ when nil then
160
+ case
161
+ when ss.skip(/[ \t]+/) then
162
+ # do nothing
163
+ when ss.skip(/\/\/[^\r\n]*/) then
164
+ # do nothing
165
+ when text = ss.scan(/\r|\n/) then
166
+ newline text
167
+ when text = ss.scan(/[!=<>]=?/) then
168
+ action { [:SPECIAL, text] }
169
+ when text = ss.scan(/[(){},;.\-+\/*]/) then
170
+ action { [:SPECIAL, text] }
171
+ when text = ss.scan(/#{DIGIT}+(\.#{DIGIT}+)?/) then
172
+ action { [:NUMBER, text] }
173
+ when text = ss.scan(/nil/) then
174
+ action { [:NIL, text] }
175
+ when text = ss.scan(/false/) then
176
+ action { [:FALSE, text] }
177
+ when text = ss.scan(/true/) then
178
+ action { [:TRUE, text] }
179
+ when text = ss.scan(/#{ALPHA}(#{ALPHA}|#{DIGIT})*/) then
180
+ action { [:IDENTIFIER, text] }
181
+ when ss.skip(/""/) then
182
+ action { [:STRING, '""'] }
183
+ when ss.skip(/"/) then
184
+ [:state, :IN_STRING]
185
+ else
186
+ text = ss.string[ss.pos .. -1]
187
+ raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'"
188
+ end
189
+ when :IN_STRING then
190
+ case
191
+ when text = ss.scan(/[^"]+/) then
192
+ action { [:STRING, "\"#{text}\""] }
193
+ when ss.skip(/"/) then
194
+ [:state, nil]
195
+ else
196
+ text = ss.string[ss.pos .. -1]
197
+ raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'"
198
+ end
199
+ else
200
+ raise ScanError, "undefined state at #{location}: '#{state}'"
201
+ end # token = case state
202
+
203
+ next unless token # allow functions to trigger redo w/ nil
204
+ end # while
205
+
206
+ raise LexerError, "bad lexical result at #{location}: #{token.inspect}" unless
207
+ token.nil? || (Array === token && token.size >= 2)
208
+
209
+ # auto-switch state
210
+ self.state = token.last if token && token.first == :state
211
+
212
+ token
213
+ end # def next_token
214
+ def do_parse
215
+ tokens = []
216
+ while (tok = next_token) do
217
+ (type, lexeme) = tok
218
+ if type == :state
219
+ self.state = lexeme
220
+ next
221
+ else
222
+ tokens << [type, lexeme, lineno, column]
223
+ end
224
+ end
225
+ tokens
226
+ end
227
+ def newline(txt)
228
+ if txt == '\r'
229
+ ss.skip(/\n/) # CR LF sequence
230
+ self.lineno += 1
231
+ self.start_of_current_line_pos = ss.pos + 1
232
+ end
233
+ nil
234
+ end
235
+ end # class
236
+
237
+ # rubocop: enable Style/MutableConstant
238
+ # rubocop: enable Layout/SpaceBeforeSemicolon
239
+ # rubocop: enable Style/Alias
240
+ # rubocop: enable Style/AndOr
241
+ # rubocop: enable Style/MultilineIfModifier
242
+ # rubocop: enable Style/StringLiterals
243
+ # rubocop: enable Style/MethodDefParentheses
244
+ # rubocop: enable Security/Open
245
+ # rubocop: enable Style/TrailingCommaInArrayLiteral
246
+ # rubocop: enable Layout/EmptyLinesAroundMethodBody
247
+ # rubocop: enable Style/WhileUntilDo
248
+ # rubocop: enable Style/MultilineWhenThen
249
+ # rubocop: enable Layout/ExtraSpacing
250
+ # rubocop: enable Layout/SpaceInsideRangeLiteral
251
+ # rubocop: enable Style/CaseEquality
252
+ # rubocop: enable Style/EmptyCaseCondition
253
+ # rubocop: enable Style/SymbolArray
254
+ # rubocop: enable Lint/DuplicateBranch
255
+ # rubocop: enable Layout/EmptyLineBetweenDefs
256
+ # rubocop: enable Layout/IndentationConsistency
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rley'
4
+ require_relative 'loxxy_raw_scanner.rex'
5
+
6
+ class LoxxyTokenizer
7
+ # @return [LoxxyRawScanner] Scanner generated by `oedipus_lex`gem.
8
+ attr_reader :scanner
9
+
10
+ # @return [String] Input text to tokenize
11
+ attr_reader :input
12
+
13
+ Keyword2name = begin
14
+ lookup = %w[
15
+ and class else false fun for if nil or
16
+ print return super this true var while
17
+ ].map { |x| [x, x.upcase] }.to_h
18
+ lookup.default = 'IDENTIFIER'
19
+ lookup.freeze
20
+ end
21
+
22
+ Special2name = {
23
+ '(' => 'LEFT_PAREN',
24
+ ')' => 'RIGHT_PAREN',
25
+ '{' => 'LEFT_BRACE',
26
+ '}' => 'RIGHT_BRACE',
27
+ ',' => 'COMMA',
28
+ '.' => 'DOT',
29
+ '-' => 'MINUS',
30
+ '+' => 'PLUS',
31
+ ';' => 'SEMICOLON',
32
+ '/' => 'SLASH',
33
+ '*' => 'STAR',
34
+ '!' => 'BANG',
35
+ '!=' => 'BANG_EQUAL',
36
+ '=' => 'EQUAL',
37
+ '==' => 'EQUAL_EQUAL',
38
+ '>' => 'GREATER',
39
+ '>=' => 'GREATER_EQUAL',
40
+ '<' => 'LESS',
41
+ '<=' => 'LESS_EQUAL'
42
+ }.freeze
43
+
44
+ def initialize(source = nil)
45
+ @scanner = LoxxyRawScanner.new
46
+ start_with(source)
47
+ end
48
+
49
+ def start_with(source)
50
+ @input = source
51
+ end
52
+
53
+ def tokens
54
+ raw_tokens = scanner.parse(input)
55
+ cooked = raw_tokens.map do |(raw_type, raw_text, line, col)|
56
+ pos = Rley::Lexical::Position.new(line, col + 1)
57
+ convert(raw_type, raw_text, pos)
58
+ end
59
+ forelast = cooked.last
60
+ last_col = forelast.position.column + forelast.lexeme.length
61
+ last_pos = Rley::Lexical::Position.new(forelast.position.line, last_col)
62
+ cooked << Rley::Lexical::Token.new(nil, 'EOF', last_pos)
63
+ cooked
64
+ end
65
+
66
+ private
67
+
68
+ def convert(token_kind, token_text, pos)
69
+ result = case token_kind
70
+ when :SPECIAL
71
+ Rley::Lexical::Token.new(token_text, Special2name[token_text])
72
+ when :FALSE
73
+ Rley::Lexical::Literal.new(false, token_text, 'FALSE')
74
+ when :NUMBER
75
+ num_val = token_text =~ /\.\d+$/ ? token_text.to_f : token_text.to_i
76
+ Rley::Lexical::Literal.new(num_val, token_text, 'NUMBER')
77
+ when :NIL
78
+ Rley::Lexical::Literal.new(nil, token_text, 'NIL')
79
+ when :STRING
80
+ str_val = token_text[1..-2]
81
+ pos.column = pos.column - 1 unless str_val.empty?
82
+ Rley::Lexical::Literal.new(str_val, token_text, 'STRING')
83
+ when :TRUE
84
+ Rley::Lexical::Literal.new(true, token_text, 'TRUE')
85
+ when :IDENTIFIER
86
+ Rley::Lexical::Token.new(token_text, Keyword2name[token_text])
87
+ else
88
+ raise ScanError, "Error: [line #{pos.line}:#{column}]: Unexpected token #{token_text}"
89
+ end
90
+
91
+ result.position = pos
92
+ result
93
+ end
94
+ end # class
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require_relative 'loxxy_tokenizer'
5
+
6
+ lox_source = <<LOX_END
7
+ class Base {
8
+ foo() {
9
+ print "Base.foo()";
10
+ }
11
+ }
12
+
13
+ class Derived < Base {
14
+ foo() {
15
+ print "Derived.foo()";
16
+ super.foo();
17
+ }
18
+ }
19
+
20
+ Derived().foo();
21
+ // expect: Derived.foo()
22
+ // expect: Base.foo()
23
+ LOX_END
24
+
25
+ loxxy_tokenizer = LoxxyTokenizer.new
26
+ loxxy_tokenizer.start_with(lox_source)
27
+ tokens = loxxy_tokenizer.tokens
28
+ File::open('tokens.yaml', 'w') { |f| YAML.dump(tokens, f) }
29
+ puts 'Done: tokenizer results saved in YAML.'
@@ -5,7 +5,7 @@
5
5
 
6
6
  module Rley # Module used as a namespace
7
7
  # The version number of the gem.
8
- Version = '0.8.03'
8
+ Version = '0.8.05'
9
9
 
10
10
  # Brief description of the gem.
11
11
  Description = "Ruby implementation of the Earley's parsing algorithm"
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'token'
4
+
5
+ module Rley # This module is used as a namespace
6
+ module Lexical # This module is used as a namespace
7
+ # A literal (value) is a token that represents a data value in the parsed
8
+ # language. For instance, in Ruby data values such as strings, numbers,
9
+ # regular expression,... can appear directly in the source code. These are
10
+ # examples of literal values. One responsibility of a tokenizer/lexer is
11
+ # to convert the text representation into a corresponding value in a
12
+ # convenient format for the interpreter/compiler.
13
+ class Literal < Token
14
+ # @return [Object] The value expressed in one of the target datatype.
15
+ attr_reader(:value)
16
+
17
+ # Constructor.
18
+ # @param aValue [Object] value of the token in internal representation
19
+ # @param theLexeme [String] the lexeme (= piece of text from input)
20
+ # @param aTerminal [Syntax::Terminal, String]
21
+ # @param aPosition [Rley::Lexical::Position] line, column position pf token
22
+ def initialize(aValue, theLexeme, aTerminal, aPosition = nil)
23
+ super(theLexeme, aTerminal, aPosition)
24
+ @value = aValue
25
+ end
26
+ end # class
27
+ end # module
28
+ end # module
29
+ # End of file
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rley # This module is used as a namespace
4
- module Lexical # This module is used as a namespace
4
+ # This module hosts classes that a Rley parser expects
5
+ # as return values from a tokenizer / lexer.
6
+ module Lexical
5
7
  # A Position is the location of a lexeme within a source file.
6
8
  Position = Struct.new(:line, :column) do
7
9
  def to_s
@@ -28,14 +30,15 @@ module Rley # This module is used as a namespace
28
30
  # @return [String] The name of terminal symbol matching the lexeme.
29
31
  attr_reader(:terminal)
30
32
 
31
- # @return [Position] The position of the lexeme in the source file.
32
- attr_reader(:position)
33
+ # @return [Position] The position -in "editor" coordinates- of the lexeme in the source file.
34
+ attr_accessor(:position)
33
35
 
34
36
  # Constructor.
35
37
  # @param theLexeme [String] the lexeme (= piece of text from input)
36
38
  # @param aTerminal [Syntax::Terminal, String]
37
39
  # The terminal symbol corresponding to the lexeme.
38
- def initialize(theLexeme, aTerminal, aPosition)
40
+ # @param aPositiçon [Rley::Lexical::Position] position of the token in source file
41
+ def initialize(theLexeme, aTerminal, aPosition = nil)
39
42
  raise 'Internal error: nil terminal symbol detected' if aTerminal.nil?
40
43
 
41
44
  @lexeme = theLexeme
@@ -3,8 +3,6 @@
3
3
  require 'set'
4
4
  require_relative 'terminal'
5
5
  require_relative 'non_terminal'
6
- require_relative 'literal'
7
- require_relative 'verbatim_symbol'
8
6
  require_relative 'production'
9
7
  require_relative 'grammar'
10
8
 
data/lib/rley.rb CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  require_relative './rley/constants'
8
8
  require_relative './rley/interface'
9
- require_relative './rley/lexical/token'
9
+ require_relative './rley/lexical/literal'
10
10
  require_relative './rley/parser/gfg_earley_parser'
11
11
  require_relative './rley/parse_rep/ast_base_builder'
12
12
  require_relative './rley/parse_tree_visitor'
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../spec_helper'
4
+
5
+ require_relative '../../../lib/rley/syntax/terminal'
6
+
7
+ # Load the class under test
8
+ require_relative '../../../lib/rley/lexical/literal'
9
+
10
+ module Rley # Open this namespace to avoid module qualifier prefixes
11
+ module Lexical # Open this namespace to avoid module qualifier prefixes
12
+ describe Literal do
13
+ let(:lexeme) { '12.34' }
14
+ let(:a_terminal) { Syntax::Terminal.new('NUMBER') }
15
+ let(:a_pos) { Position.new(3, 4) }
16
+
17
+ context 'Initialization:' do
18
+ # Default instantiation rule
19
+ subject { Literal.new(lexeme.to_f, lexeme, a_terminal, a_pos) }
20
+
21
+ it 'should be created with a value, lexeme, terminal and position' do
22
+ expect { Literal.new(lexeme.to_f, lexeme, a_terminal, a_pos) }.not_to raise_error
23
+ end
24
+
25
+ it 'should know its value' do
26
+ expect(subject.value).to eq(lexeme.to_f)
27
+ end
28
+ end # context
29
+ end # describe
30
+ end # module
31
+ end # module
32
+
33
+ # End of file
@@ -13,12 +13,15 @@ module Rley # Open this namespace to avoid module qualifier prefixes
13
13
  let(:lexeme) { '"some text"' }
14
14
  let(:a_terminal) { Syntax::Terminal.new('if') }
15
15
  let(:a_pos) { Position.new(3, 4) }
16
+ # Default instantiation rule
17
+ subject { Token.new(lexeme, a_terminal, a_pos) }
16
18
 
17
19
  context 'Initialization:' do
18
- # Default instantiation rule
19
- subject { Token.new(lexeme, a_terminal, a_pos) }
20
+ it 'could be created with a lexeme and a terminal ' do
21
+ expect { Token.new(lexeme, a_terminal) }.not_to raise_error
22
+ end
20
23
 
21
- it 'should be created with a lexeme, a terminal and position' do
24
+ it 'could be created with a lexeme, a terminal and position' do
22
25
  expect { Token.new(lexeme, a_terminal, a_pos) }.not_to raise_error
23
26
  end
24
27
 
@@ -30,7 +33,15 @@ module Rley # Open this namespace to avoid module qualifier prefixes
30
33
  expect(subject.terminal).to eq(a_terminal)
31
34
  end
32
35
 
33
- it 'should know its terminal' do
36
+ it 'should know its position' do
37
+ new_pos = Position.new(5, 7)
38
+ subject.position = new_pos
39
+ expect(subject.position).to eq(new_pos)
40
+ end
41
+ end # context
42
+
43
+ context 'Initialization:' do
44
+ it 'should accept a new position' do
34
45
  expect(subject.position).to eq(a_pos)
35
46
  end
36
47
  end # context
@@ -55,8 +55,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
55
55
 
56
56
  it 'should accept already built terminals' do
57
57
  a = Syntax::Terminal.new('a')
58
- b = Syntax::VerbatimSymbol.new('b')
59
- c = Syntax::Literal.new('c', /c/)
58
+ b = Syntax::Terminal.new('b')
59
+ c = Syntax::Terminal.new('c')
60
60
 
61
61
  subject.add_terminals(a, b, c)
62
62
  expect(subject.symbols.size).to eq(3)