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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/History.rdoc +9 -0
- data/lib/oedipus_lex.rb +134 -51
- data/test/test_oedipus_lex.rb +36 -0
- metadata +5 -5
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4d847d43454e2e7497b7737efea33c3ac3639d2
|
4
|
+
data.tar.gz: 94c532557bd692ed547f901b40667befe44fe39a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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 <<
|
192
|
+
rules << Rule.new(start_state, regexp, action)
|
70
193
|
end
|
71
194
|
|
72
|
-
def lex_grouphead
|
195
|
+
def lex_grouphead re
|
73
196
|
end_group if group
|
74
197
|
self.state = :group
|
75
|
-
self.group =
|
198
|
+
self.group = Group.new re
|
76
199
|
end
|
77
200
|
|
78
201
|
def lex_group start_state, regexp, action = nil
|
79
|
-
|
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|
|
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
|
-
|
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.
|
237
|
-
|
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]
|
data/test/test_oedipus_lex.rb
CHANGED
@@ -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.
|
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-
|
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.
|
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.
|
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:
|
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
|