oedipus_lex 2.2.1 → 2.3.0

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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f7fe436e528415763cca7067c30307dbff6e9793
4
- data.tar.gz: e5ebf8486d367d3a5d98741eb5a06a6ac9db6cac
3
+ metadata.gz: e4d847d43454e2e7497b7737efea33c3ac3639d2
4
+ data.tar.gz: 94c532557bd692ed547f901b40667befe44fe39a
5
5
  SHA512:
6
- metadata.gz: a0b1887372dbb69a6e74de3b5343f314583ff5c18b1c5fb338d6dccc5dda19ada9de8fb1b85d4750e919385b055f61e1e6cab75a0f903e1e4f1f230f26c40e1f
7
- data.tar.gz: b4859b2af69385f7c78cb6f2fd3906d2cc4cd6d7dec65f0dbd1d48153b61240a97bbfd304fc144650685c718a83cf0584fecabb4ba8fdf26b862bf34e7852bbd
6
+ metadata.gz: 7d8ed1a67c28ca5ffafcf7d48abac036d6d3ccb88254bfd11e953d646f35b08a27e3c246f40317e13127961c6ca77f98a71b0eaa9aded873ae5d4f207176efe2
7
+ data.tar.gz: 473a2296045308dec98b4a9355d4f1dd89168f2fae68cdea7f70efa6c4249f630fccf4b3be02d96478f343e995cdd61f96ce766f523ccaa9d7f59123b93ab4e9
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/History.rdoc CHANGED
@@ -1,3 +1,12 @@
1
+ === 2.3.0 / 2014-05-16
2
+
3
+ * 4 minor enhancements:
4
+
5
+ * Added == method to lexer.
6
+ * Added pretty_print methods to lexer+rule+group.
7
+ * Added structural test so I can later make optimization changes cleanly.
8
+ * Refactored to (mostly) use an AST for code generation. Nukes 2 ERB templates.
9
+
1
10
  === 2.2.1 / 2014-04-02
2
11
 
3
12
  * 1 bug fix:
data/lib/oedipus_lex.rb CHANGED
@@ -4,7 +4,7 @@ require "erb"
4
4
  require "oedipus_lex.rex"
5
5
 
6
6
  class OedipusLex
7
- VERSION = "2.2.1"
7
+ VERSION = "2.3.0"
8
8
 
9
9
  attr_accessor :class_name
10
10
  attr_accessor :header
@@ -23,6 +23,109 @@ class OedipusLex
23
23
  :stub => false,
24
24
  }
25
25
 
26
+ class Rule < Struct.new :start_state, :regexp, :action
27
+ attr_accessor :group
28
+ alias :group? :group
29
+
30
+ def self.[] start, regexp, action
31
+ new start, regexp.inspect, action
32
+ end
33
+
34
+ def initialize start_state, regexp, action
35
+ super
36
+ self.group = nil
37
+ end
38
+
39
+ undef_method :to_a
40
+
41
+ def to_ruby state, predicates, exclusive
42
+ return unless group? or
43
+ start_state == state or
44
+ (state.nil? and predicates.include? start_state)
45
+
46
+ cond =
47
+ if exclusive or not start_state then
48
+ "when text = ss.scan(#{regexp}) then"
49
+ elsif start_state =~ /^:/ then
50
+ "when (state == #{start_state}) && (text = ss.scan(#{regexp})) then"
51
+ else
52
+ "when #{start_state} && (text = ss.scan(#{regexp})) then"
53
+ end
54
+
55
+ body =
56
+ case action
57
+ when nil, false then
58
+ " # do nothing"
59
+ when /^\{/ then
60
+ " action #{action}"
61
+ when /^:/, "nil" then
62
+ " [:state, #{action}]"
63
+ else
64
+ " #{action} text"
65
+ end
66
+
67
+ [cond, body]
68
+ end
69
+
70
+ def pretty_print pp
71
+ pp.text "Rule"
72
+ pp.group 2, "[", "]" do
73
+ pp.pp start_state
74
+ pp.text ", "
75
+ pp.text regexp
76
+ pp.text ", "
77
+ pp.send(action ? :text : :pp, action)
78
+ end
79
+ end
80
+ end
81
+
82
+ class Group < Struct.new :regex, :rules
83
+ alias :start_state :regex
84
+
85
+ def self.[] start, *subrules
86
+ r = new start.inspect
87
+ r.rules.concat subrules
88
+ r
89
+ end
90
+
91
+ def initialize start
92
+ super(start, [])
93
+ end
94
+
95
+ def << rule
96
+ rules << rule
97
+ nil
98
+ end
99
+
100
+ def to_ruby state, predicates, exclusive
101
+ [
102
+ "when ss.check(#{regex}) then",
103
+ " case",
104
+ rules.map { |subrule|
105
+ s = subrule.to_ruby(state, predicates, exclusive)
106
+ s && s.join("\n").gsub(/^/, " ")
107
+ }.compact,
108
+ " end # group #{regex}"
109
+ ]
110
+ end
111
+
112
+ def pretty_print pp
113
+ pp.text "Group"
114
+ pp.group 2, "[", "]" do
115
+ pp.seplist([regex] + rules, lambda { pp.comma_breakable }, :each) { |v|
116
+ pp.send(String === v ? :text : :pp, v)
117
+ }
118
+ end
119
+ end
120
+ end
121
+
122
+ def self.[](name, *rules)
123
+ r = new
124
+ r.class_name = name
125
+ r.rules.concat rules
126
+ r
127
+ end
128
+
26
129
  def initialize opts = {}
27
130
  self.option = DEFAULTS.merge opts
28
131
  self.class_name = nil
@@ -36,6 +139,26 @@ class OedipusLex
36
139
  self.group = nil
37
140
  end
38
141
 
142
+ def == o
143
+ (o.class == self.class and
144
+ o.class_name == self.class_name and
145
+ o.header == self.header and
146
+ o.ends == self.ends and
147
+ o.inners == self.inners and
148
+ o.macros == self.macros and
149
+ o.rules == self.rules and
150
+ o.starts == self.starts)
151
+ end
152
+
153
+ def pretty_print pp
154
+ commas = lambda { pp.comma_breakable }
155
+
156
+ pp.text "Lexer"
157
+ pp.group 2, "[", "]" do
158
+ pp.seplist([class_name] + rules, commas, :each) { |v| pp.pp v }
159
+ end
160
+ end
161
+
39
162
  def lex_class prefix, name
40
163
  header.concat prefix.split(/\n/)
41
164
  self.class_name = name
@@ -66,17 +189,19 @@ class OedipusLex
66
189
  end
67
190
 
68
191
  def lex_rule start_state, regexp, action = nil
69
- rules << [start_state, regexp, action]
192
+ rules << Rule.new(start_state, regexp, action)
70
193
  end
71
194
 
72
- def lex_grouphead(*vals)
195
+ def lex_grouphead re
73
196
  end_group if group
74
197
  self.state = :group
75
- self.group = vals
198
+ self.group = Group.new re
76
199
  end
77
200
 
78
201
  def lex_group start_state, regexp, action = nil
79
- self.group << [start_state, regexp, action]
202
+ rule = Rule.new(start_state, regexp, action)
203
+ rule.group = group
204
+ self.group << rule
80
205
  end
81
206
 
82
207
  def end_group
@@ -96,7 +221,7 @@ class OedipusLex
96
221
  end
97
222
 
98
223
  def generate
99
- filter = lambda { |r| Array === r.last ? nil : r.first }
224
+ filter = lambda { |r| Rule === r && r.start_state || nil }
100
225
  _mystates = rules.map(&filter).flatten.compact.uniq
101
226
  exclusives, inclusives = _mystates.partition { |s| s =~ /^:[A-Z]/ }
102
227
 
@@ -110,38 +235,7 @@ class OedipusLex
110
235
  ERB.new(TEMPLATE, nil, "%").result binding
111
236
  end
112
237
 
113
- rule = <<-'END_RULE'.chomp
114
- % start_state, rule_expr, rule_action = *rule
115
- % if start_state == state or (state.nil? and predicates.include? start_state) then
116
- % if start_state and not exclusive then
117
- % if start_state =~ /^:/ then
118
- when (state == <%= start_state %>) && (text = ss.scan(<%= rule_expr %>)) then
119
- % else
120
- when <%= start_state %> && (text = ss.scan(<%= rule_expr %>)) then
121
- % end
122
- % else
123
- when text = ss.scan(<%= rule_expr %>) then
124
- % end
125
- % if rule_action then
126
- % case rule_action
127
- % when /^\{/ then
128
- action <%= rule_action %>
129
- % when /^:/, "nil" then
130
- [:state, <%= rule_action %>]
131
- % else
132
- <%= rule_action %> text
133
- % end
134
- % else
135
- # do nothing
136
- % end
137
- % end # start_state == state
138
- END_RULE
139
-
140
- subrule = rule.gsub(/^ /, " ").
141
- sub(/\*rule/, "*subrule"). # use subrules, not top level rules
142
- sub(/start_state == state or/, "true or") # hack to prevent state checks
143
-
144
- TEMPLATE = <<-'REX'.sub(/SUBRULE/, subrule).sub(/RULE/, rule).gsub(/^ {6}/, '\1')
238
+ TEMPLATE = <<-'REX'.gsub(/^ {6}/, '')
145
239
  #--
146
240
  # This file is automatically generated. Do not modify it.
147
241
  # Generated by: oedipus_lex version <%= VERSION %>.
@@ -233,19 +327,8 @@ class OedipusLex
233
327
  when <%= the_states.map { |s| s || "nil" }.join ", " %> then
234
328
  case
235
329
  % the_states.each do |state|
236
- % rules.each do |rule|
237
- % if Array === rule.last then
238
- % group_re, *subrules = rule
239
- when ss.check(<%= group_re %>) then
240
- case
241
- % subrules.each do |subrule|
242
- SUBRULE
243
- % end
244
- end # group <%= group_re %>
245
- % else # rule or group
246
- RULE
247
- % end # rule or group
248
- % end # rules.each
330
+ % lines = rules.map { |r| r.to_ruby state, predicates, exclusive }.compact
331
+ <%= lines.join("\n").gsub(/^/, " " * 10) %>
249
332
  % end # the_states.each
250
333
  else
251
334
  text = ss.string[ss.pos .. -1]
@@ -468,6 +468,42 @@ class TestOedipusLex < Minitest::Test
468
468
  assert_match "end # group /\\d/", ruby
469
469
  end
470
470
 
471
+ def test_scanner_inspect_slash_structure
472
+ src = <<-'REX'
473
+ class Calculator
474
+ rules
475
+
476
+ : /\d/
477
+ | /\d+\.\d+/ { [:float, text.to_f] }
478
+ | /\d+/ { [:int, text.to_i] }
479
+ : /\+/
480
+ | xx? /\+whatever/ { [:x, text] }
481
+ | :x /\+\d+/ { [:y, text] }
482
+ | :x /\+\w+/ { [:z, text] }
483
+ /\s+/
484
+ end
485
+ REX
486
+
487
+ rex = OedipusLex.new option
488
+ rex.parse cleanup src
489
+
490
+ lex = OedipusLex
491
+ group, rule = lex::Group, lex::Rule
492
+ expected = lex["Calculator",
493
+ group[/\d/,
494
+ rule[nil, /\d+\.\d+/, "{ [:float, text.to_f] }"],
495
+ rule[nil, /\d+/, "{ [:int, text.to_i] }"]],
496
+ group[/\+/,
497
+ rule["xx?", /\+whatever/, "{ [:x, text] }"],
498
+ rule[":x", /\+\d+/, "{ [:y, text] }"],
499
+ rule[":x", /\+\w+/, "{ [:z, text] }"]],
500
+ rule[nil, /\s+/, nil]]
501
+
502
+ assert_equal expected, rex
503
+ end
504
+
505
+ make_my_diffs_pretty!
506
+
471
507
  def test_generator_start
472
508
  src = <<-'REX'
473
509
  class Calculator
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oedipus_lex
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Davis
@@ -29,7 +29,7 @@ cert_chain:
29
29
  Y4evBVezr3SjXz08vPqRO5YRdO3zfeMT8gBjRqZjWJGMZ2lD4XNfrs7eky74CyZw
30
30
  xx3n58i0lQkBE1EpKE0lFu/y
31
31
  -----END CERTIFICATE-----
32
- date: 2014-04-02 00:00:00.000000000 Z
32
+ date: 2014-05-16 00:00:00.000000000 Z
33
33
  dependencies:
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: minitest
@@ -65,14 +65,14 @@ dependencies:
65
65
  requirements:
66
66
  - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: '3.9'
68
+ version: '3.12'
69
69
  type: :development
70
70
  prerelease: false
71
71
  version_requirements: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ~>
74
74
  - !ruby/object:Gem::Version
75
- version: '3.9'
75
+ version: '3.12'
76
76
  description: |-
77
77
  Oedipus Lex is a lexer generator in the same family as Rexical and
78
78
  Rex. Oedipus Lex is my independent lexer fork of Rexical. Rexical was
@@ -155,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
155
  - !ruby/object:Gem::Version
156
156
  version: '0'
157
157
  requirements: []
158
- rubyforge_project: oedipus_lex
158
+ rubyforge_project:
159
159
  rubygems_version: 2.2.1
160
160
  signing_key:
161
161
  specification_version: 4
metadata.gz.sig CHANGED
Binary file