oedipus_lex 2.2.1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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