ruby-ll 1.0.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 +7 -0
- data/.yardopts +13 -0
- data/LICENSE +19 -0
- data/README.md +380 -0
- data/bin/ruby-ll +5 -0
- data/doc/DCO.md +25 -0
- data/doc/changelog.md +8 -0
- data/doc/css/common.css +77 -0
- data/ext/c/driver.c +258 -0
- data/ext/c/driver.h +28 -0
- data/ext/c/driver_config.c +209 -0
- data/ext/c/driver_config.h +53 -0
- data/ext/c/extconf.rb +13 -0
- data/ext/c/khash.h +619 -0
- data/ext/c/kvec.h +90 -0
- data/ext/c/libll.c +7 -0
- data/ext/c/libll.h +9 -0
- data/ext/c/macros.h +6 -0
- data/ext/java/Libll.java +12 -0
- data/ext/java/org/libll/Driver.java +247 -0
- data/ext/java/org/libll/DriverConfig.java +193 -0
- data/lib/ll.rb +26 -0
- data/lib/ll/ast/node.rb +13 -0
- data/lib/ll/branch.rb +57 -0
- data/lib/ll/cli.rb +118 -0
- data/lib/ll/code_generator.rb +32 -0
- data/lib/ll/compiled_configuration.rb +35 -0
- data/lib/ll/compiled_grammar.rb +167 -0
- data/lib/ll/configuration_compiler.rb +204 -0
- data/lib/ll/driver.rb +46 -0
- data/lib/ll/driver_config.rb +36 -0
- data/lib/ll/driver_template.erb +51 -0
- data/lib/ll/epsilon.rb +23 -0
- data/lib/ll/erb_context.rb +23 -0
- data/lib/ll/grammar_compiler.rb +359 -0
- data/lib/ll/lexer.rb +582 -0
- data/lib/ll/message.rb +102 -0
- data/lib/ll/parser.rb +280 -0
- data/lib/ll/parser_error.rb +8 -0
- data/lib/ll/rule.rb +53 -0
- data/lib/ll/setup.rb +11 -0
- data/lib/ll/source_line.rb +46 -0
- data/lib/ll/terminal.rb +29 -0
- data/lib/ll/token.rb +30 -0
- data/lib/ll/version.rb +3 -0
- data/ruby-ll.gemspec +47 -0
- metadata +217 -0
data/lib/ll/message.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
module LL
|
2
|
+
##
|
3
|
+
# A warning/error generated during the compilation of a grammar.
|
4
|
+
#
|
5
|
+
class Message
|
6
|
+
attr_reader :type, :message, :source_line
|
7
|
+
|
8
|
+
##
|
9
|
+
# The colours to use for the various message types.
|
10
|
+
#
|
11
|
+
# @return [Hash]
|
12
|
+
#
|
13
|
+
COLORS = {
|
14
|
+
:error => :red,
|
15
|
+
:warning => :yellow
|
16
|
+
}
|
17
|
+
|
18
|
+
##
|
19
|
+
# @param [Symbol] type
|
20
|
+
# @param [String] message
|
21
|
+
# @param [LL::SourceLine] source_line
|
22
|
+
#
|
23
|
+
def initialize(type, message, source_line)
|
24
|
+
@type = type
|
25
|
+
@message = message
|
26
|
+
@source_line = source_line
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Returns a String containing details of the message, complete with ANSI
|
31
|
+
# colour sequences.
|
32
|
+
#
|
33
|
+
# @return [String]
|
34
|
+
#
|
35
|
+
def to_s
|
36
|
+
location = ANSI.ansi("#{determine_path}:#{line}:#{column}", :white, :bold)
|
37
|
+
|
38
|
+
type_label = ANSI.ansi(type.to_s, COLORS[type], :bold)
|
39
|
+
msg_line = "#{location}:#{type_label}: #{message}"
|
40
|
+
|
41
|
+
return "#{msg_line}\n#{source_line.source}\n#{marker}"
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# @return [String]
|
46
|
+
#
|
47
|
+
def inspect
|
48
|
+
return "Message(type: #{type.inspect}, message: #{message.inspect}, " \
|
49
|
+
"file: #{determine_path.inspect}, line: #{line}, column: #{column})"
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Returns the path to the source of the message. If the path resides in the
|
54
|
+
# current working directory (or a child directory) the path is relative,
|
55
|
+
# otherwise it's absolute.
|
56
|
+
#
|
57
|
+
# @return [String]
|
58
|
+
#
|
59
|
+
def determine_path
|
60
|
+
if source_line.file == SourceLine::DEFAULT_FILE
|
61
|
+
return source_line.file
|
62
|
+
end
|
63
|
+
|
64
|
+
full_path = File.expand_path(source_line.file)
|
65
|
+
pwd = Dir.pwd
|
66
|
+
|
67
|
+
if full_path.start_with?(pwd)
|
68
|
+
from = Pathname.new(full_path)
|
69
|
+
to = Pathname.new(pwd)
|
70
|
+
|
71
|
+
return from.relative_path_from(to).to_s
|
72
|
+
else
|
73
|
+
return full_path
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# @return [Fixnum]
|
79
|
+
#
|
80
|
+
def line
|
81
|
+
return source_line.line
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# @return [Fixnum]
|
86
|
+
#
|
87
|
+
def column
|
88
|
+
return source_line.column
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
##
|
94
|
+
# @return [String]
|
95
|
+
#
|
96
|
+
def marker
|
97
|
+
padding = ' ' * (column - 1)
|
98
|
+
|
99
|
+
return padding + ANSI.ansi('^', :magenta, :bold)
|
100
|
+
end
|
101
|
+
end # Message
|
102
|
+
end # LL
|
data/lib/ll/parser.rb
ADDED
@@ -0,0 +1,280 @@
|
|
1
|
+
# This file is automatically generated by ruby-ll. Manually changing this file
|
2
|
+
# is not recommended as any changes will be lost the next time this parser is
|
3
|
+
# re-generated.
|
4
|
+
|
5
|
+
module LL
|
6
|
+
class Parser < LL::Driver
|
7
|
+
CONFIG = LL::DriverConfig.new
|
8
|
+
|
9
|
+
CONFIG.terminals = [
|
10
|
+
:$EOF, # 0
|
11
|
+
:T_RUBY, # 1
|
12
|
+
:T_NAME, # 2
|
13
|
+
:T_TERMINALS, # 3
|
14
|
+
:T_INNER, # 4
|
15
|
+
:T_HEADER, # 5
|
16
|
+
:T_IDENT, # 6
|
17
|
+
:T_EQUALS, # 7
|
18
|
+
:T_COLON, # 8
|
19
|
+
:T_PIPE, # 9
|
20
|
+
:T_EPSILON, # 10
|
21
|
+
:T_SEMICOLON, # 11
|
22
|
+
].freeze
|
23
|
+
|
24
|
+
CONFIG.rules = [
|
25
|
+
[3, 0, 0, 1], # 0
|
26
|
+
[3, 1, 2, 0], # 1
|
27
|
+
[3, 2, 0, 1, 0, 2], # 2
|
28
|
+
[3, 3, 2, 0], # 3
|
29
|
+
[3, 4, 0, 18], # 4
|
30
|
+
[3, 5, 0, 3], # 5
|
31
|
+
[3, 6, 0, 5], # 6
|
32
|
+
[3, 7, 0, 6], # 7
|
33
|
+
[3, 8, 0, 7], # 8
|
34
|
+
[3, 9, 1, 11, 0, 4, 0, 10, 1, 2], # 9
|
35
|
+
[3, 10, 0, 4, 0, 10, 1, 8, 1, 8], # 10
|
36
|
+
[3, 11, 2, 0], # 11
|
37
|
+
[3, 12, 1, 11, 0, 8, 1, 3], # 12
|
38
|
+
[3, 13, 0, 15, 1, 4], # 13
|
39
|
+
[3, 14, 0, 15, 1, 5], # 14
|
40
|
+
[3, 15, 0, 9, 0, 10], # 15
|
41
|
+
[3, 16, 0, 8], # 16
|
42
|
+
[3, 17, 2, 0], # 17
|
43
|
+
[3, 18, 1, 6], # 18
|
44
|
+
[3, 19, 0, 8], # 19
|
45
|
+
[3, 20, 0, 12], # 20
|
46
|
+
[3, 21, 1, 10], # 21
|
47
|
+
[3, 22, 0, 14, 0, 11], # 22
|
48
|
+
[3, 23, 0, 15], # 23
|
49
|
+
[3, 24, 2, 0], # 24
|
50
|
+
[3, 25, 1, 1], # 25
|
51
|
+
[3, 26, 0, 17, 0, 13], # 26
|
52
|
+
[3, 27, 0, 16, 1, 9], # 27
|
53
|
+
[3, 28, 2, 0], # 28
|
54
|
+
[3, 29, 1, 11, 0, 16, 1, 7, 0, 10], # 29
|
55
|
+
].freeze
|
56
|
+
|
57
|
+
CONFIG.table = [
|
58
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], # 0
|
59
|
+
[3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3], # 1
|
60
|
+
[-1, -1, 5, 6, 7, 8, 4, -1, -1, -1, -1, -1], # 2
|
61
|
+
[-1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 3
|
62
|
+
[11, 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 11], # 4
|
63
|
+
[-1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1], # 5
|
64
|
+
[-1, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1], # 6
|
65
|
+
[-1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1], # 7
|
66
|
+
[-1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1], # 8
|
67
|
+
[17, 17, 17, 17, 17, 17, 16, 17, 17, 17, 17, 17], # 9
|
68
|
+
[-1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1], # 10
|
69
|
+
[-1, -1, -1, -1, -1, -1, 19, -1, -1, -1, 20, -1], # 11
|
70
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, -1], # 12
|
71
|
+
[-1, -1, -1, -1, -1, -1, 22, -1, -1, -1, 22, -1], # 13
|
72
|
+
[24, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24], # 14
|
73
|
+
[-1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 15
|
74
|
+
[-1, -1, -1, -1, -1, -1, 26, -1, -1, -1, 26, -1], # 16
|
75
|
+
[28, 28, 28, 28, 28, 28, 28, 28, 28, 27, 28, 28], # 17
|
76
|
+
[-1, -1, -1, -1, -1, -1, 29, -1, -1, -1, -1, -1], # 18
|
77
|
+
].freeze
|
78
|
+
|
79
|
+
CONFIG.actions = [
|
80
|
+
[:_rule_0, 1], # 0
|
81
|
+
[:_rule_1, 0], # 1
|
82
|
+
[:_rule_2, 2], # 2
|
83
|
+
[:_rule_3, 0], # 3
|
84
|
+
[:_rule_4, 1], # 4
|
85
|
+
[:_rule_5, 1], # 5
|
86
|
+
[:_rule_6, 1], # 6
|
87
|
+
[:_rule_7, 1], # 7
|
88
|
+
[:_rule_8, 1], # 8
|
89
|
+
[:_rule_9, 4], # 9
|
90
|
+
[:_rule_10, 4], # 10
|
91
|
+
[:_rule_11, 0], # 11
|
92
|
+
[:_rule_12, 3], # 12
|
93
|
+
[:_rule_13, 2], # 13
|
94
|
+
[:_rule_14, 2], # 14
|
95
|
+
[:_rule_15, 2], # 15
|
96
|
+
[:_rule_16, 1], # 16
|
97
|
+
[:_rule_17, 0], # 17
|
98
|
+
[:_rule_18, 1], # 18
|
99
|
+
[:_rule_19, 1], # 19
|
100
|
+
[:_rule_20, 1], # 20
|
101
|
+
[:_rule_21, 1], # 21
|
102
|
+
[:_rule_22, 2], # 22
|
103
|
+
[:_rule_23, 1], # 23
|
104
|
+
[:_rule_24, 0], # 24
|
105
|
+
[:_rule_25, 1], # 25
|
106
|
+
[:_rule_26, 2], # 26
|
107
|
+
[:_rule_27, 2], # 27
|
108
|
+
[:_rule_28, 0], # 28
|
109
|
+
[:_rule_29, 4], # 29
|
110
|
+
].freeze
|
111
|
+
|
112
|
+
##
|
113
|
+
# @see [LL::Lexer#initialize]
|
114
|
+
#
|
115
|
+
def initialize(*args)
|
116
|
+
@lexer = Lexer.new(*args)
|
117
|
+
end
|
118
|
+
|
119
|
+
##
|
120
|
+
# @yieldparam [Symbol] type
|
121
|
+
# @yieldparam [String] value
|
122
|
+
#
|
123
|
+
def each_token
|
124
|
+
@lexer.advance do |token|
|
125
|
+
yield [token.type, token]
|
126
|
+
end
|
127
|
+
|
128
|
+
yield [-1, -1]
|
129
|
+
end
|
130
|
+
|
131
|
+
##
|
132
|
+
# @see [LL::AST::Node#initialize]
|
133
|
+
#
|
134
|
+
def s(*args)
|
135
|
+
return AST::Node.new(*args)
|
136
|
+
end
|
137
|
+
|
138
|
+
def _rule_0(val)
|
139
|
+
s(:grammar, val[0])
|
140
|
+
end
|
141
|
+
|
142
|
+
def _rule_1(val)
|
143
|
+
s(:grammar)
|
144
|
+
end
|
145
|
+
|
146
|
+
def _rule_2(val)
|
147
|
+
val[0] + val[1]
|
148
|
+
end
|
149
|
+
|
150
|
+
def _rule_3(val)
|
151
|
+
val
|
152
|
+
end
|
153
|
+
|
154
|
+
def _rule_4(val)
|
155
|
+
val
|
156
|
+
end
|
157
|
+
|
158
|
+
def _rule_5(val)
|
159
|
+
val
|
160
|
+
end
|
161
|
+
|
162
|
+
def _rule_6(val)
|
163
|
+
val
|
164
|
+
end
|
165
|
+
|
166
|
+
def _rule_7(val)
|
167
|
+
val
|
168
|
+
end
|
169
|
+
|
170
|
+
def _rule_8(val)
|
171
|
+
val
|
172
|
+
end
|
173
|
+
|
174
|
+
def _rule_9(val)
|
175
|
+
|
176
|
+
s(:name, [val[1], *val[2]], :source_line => val[0].source_line)
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
def _rule_10(val)
|
181
|
+
[val[2]] + val[3]
|
182
|
+
end
|
183
|
+
|
184
|
+
def _rule_11(val)
|
185
|
+
val
|
186
|
+
end
|
187
|
+
|
188
|
+
def _rule_12(val)
|
189
|
+
|
190
|
+
s(:terminals, val[1], :source_line => val[0].source_line)
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
def _rule_13(val)
|
195
|
+
|
196
|
+
s(:inner, [val[1]], :source_line => val[0].source_line)
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
def _rule_14(val)
|
201
|
+
|
202
|
+
s(:header, [val[1]], :source_line => val[0].source_line)
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
def _rule_15(val)
|
207
|
+
[val[0]] + val[1]
|
208
|
+
end
|
209
|
+
|
210
|
+
def _rule_16(val)
|
211
|
+
val[0]
|
212
|
+
end
|
213
|
+
|
214
|
+
def _rule_17(val)
|
215
|
+
val
|
216
|
+
end
|
217
|
+
|
218
|
+
def _rule_18(val)
|
219
|
+
|
220
|
+
s(:ident, [val[0].value], :source_line => val[0].source_line)
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
def _rule_19(val)
|
225
|
+
|
226
|
+
s(:steps, val[0], :source_line => val[0][0].source_line)
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
def _rule_20(val)
|
231
|
+
|
232
|
+
s(:steps, [val[0]], :source_line => val[0].source_line)
|
233
|
+
|
234
|
+
end
|
235
|
+
|
236
|
+
def _rule_21(val)
|
237
|
+
s(:epsilon, [], :source_line => val[0].source_line)
|
238
|
+
end
|
239
|
+
|
240
|
+
def _rule_22(val)
|
241
|
+
|
242
|
+
steps = [val[0]]
|
243
|
+
|
244
|
+
steps << val[1] if val[1]
|
245
|
+
|
246
|
+
s(:branch, steps, :source_line => val[0].source_line)
|
247
|
+
|
248
|
+
end
|
249
|
+
|
250
|
+
def _rule_23(val)
|
251
|
+
val[0]
|
252
|
+
end
|
253
|
+
|
254
|
+
def _rule_24(val)
|
255
|
+
nil
|
256
|
+
end
|
257
|
+
|
258
|
+
def _rule_25(val)
|
259
|
+
s(:ruby, [val[0].value], :source_line => val[0].source_line)
|
260
|
+
end
|
261
|
+
|
262
|
+
def _rule_26(val)
|
263
|
+
[val[0]] + val[1]
|
264
|
+
end
|
265
|
+
|
266
|
+
def _rule_27(val)
|
267
|
+
val[1]
|
268
|
+
end
|
269
|
+
|
270
|
+
def _rule_28(val)
|
271
|
+
val
|
272
|
+
end
|
273
|
+
|
274
|
+
def _rule_29(val)
|
275
|
+
|
276
|
+
s(:rule, [val[0], *val[2]], :source_line => val[0].source_line)
|
277
|
+
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
data/lib/ll/rule.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module LL
|
2
|
+
##
|
3
|
+
# Class containing details of a single rule in a grammar.
|
4
|
+
#
|
5
|
+
class Rule
|
6
|
+
attr_reader :name, :branches, :source_line, :references
|
7
|
+
|
8
|
+
##
|
9
|
+
# @param [String] name
|
10
|
+
# @param [LL::SourceLine] source_line
|
11
|
+
#
|
12
|
+
def initialize(name, source_line)
|
13
|
+
@name = name
|
14
|
+
@branches = []
|
15
|
+
@source_line = source_line
|
16
|
+
@references = 0
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# @see [LL::Branch#initialize]
|
21
|
+
#
|
22
|
+
def add_branch(steps, source_line, ruby_code = nil)
|
23
|
+
branches << Branch.new(steps, source_line, ruby_code)
|
24
|
+
end
|
25
|
+
|
26
|
+
def increment_references
|
27
|
+
@references += 1
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Returns an Array containing the terminals that make up the FIRST() set of
|
32
|
+
# this rule.
|
33
|
+
#
|
34
|
+
# @return [Array<LL::Terminal>]
|
35
|
+
#
|
36
|
+
def first_set
|
37
|
+
terminals = []
|
38
|
+
|
39
|
+
branches.each do |branch|
|
40
|
+
terminals += branch.first_set
|
41
|
+
end
|
42
|
+
|
43
|
+
return terminals
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# @return [String]
|
48
|
+
#
|
49
|
+
def inspect
|
50
|
+
return "Rule(name: #{name.inspect}, branches: #{branches.inspect})"
|
51
|
+
end
|
52
|
+
end # Rule
|
53
|
+
end # LL
|
data/lib/ll/setup.rb
ADDED