rltk3 3.0.2

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 (56) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +1 -0
  3. data/LICENSE +27 -0
  4. data/README.md +852 -0
  5. data/Rakefile +197 -0
  6. data/lib/rltk/ast.rb +573 -0
  7. data/lib/rltk/cfg.rb +683 -0
  8. data/lib/rltk/cg/basic_block.rb +157 -0
  9. data/lib/rltk/cg/bindings.rb +151 -0
  10. data/lib/rltk/cg/builder.rb +1127 -0
  11. data/lib/rltk/cg/context.rb +48 -0
  12. data/lib/rltk/cg/contractor.rb +51 -0
  13. data/lib/rltk/cg/execution_engine.rb +194 -0
  14. data/lib/rltk/cg/function.rb +237 -0
  15. data/lib/rltk/cg/generated_bindings.rb +8118 -0
  16. data/lib/rltk/cg/generic_value.rb +95 -0
  17. data/lib/rltk/cg/instruction.rb +519 -0
  18. data/lib/rltk/cg/llvm.rb +150 -0
  19. data/lib/rltk/cg/memory_buffer.rb +75 -0
  20. data/lib/rltk/cg/module.rb +451 -0
  21. data/lib/rltk/cg/pass_manager.rb +252 -0
  22. data/lib/rltk/cg/support.rb +29 -0
  23. data/lib/rltk/cg/target.rb +230 -0
  24. data/lib/rltk/cg/triple.rb +58 -0
  25. data/lib/rltk/cg/type.rb +554 -0
  26. data/lib/rltk/cg/value.rb +1272 -0
  27. data/lib/rltk/cg.rb +32 -0
  28. data/lib/rltk/lexer.rb +372 -0
  29. data/lib/rltk/lexers/calculator.rb +44 -0
  30. data/lib/rltk/lexers/ebnf.rb +38 -0
  31. data/lib/rltk/parser.rb +1702 -0
  32. data/lib/rltk/parsers/infix_calc.rb +43 -0
  33. data/lib/rltk/parsers/postfix_calc.rb +34 -0
  34. data/lib/rltk/parsers/prefix_calc.rb +34 -0
  35. data/lib/rltk/token.rb +90 -0
  36. data/lib/rltk/version.rb +11 -0
  37. data/lib/rltk.rb +16 -0
  38. data/test/cg/tc_basic_block.rb +83 -0
  39. data/test/cg/tc_control_flow.rb +191 -0
  40. data/test/cg/tc_function.rb +54 -0
  41. data/test/cg/tc_generic_value.rb +33 -0
  42. data/test/cg/tc_instruction.rb +256 -0
  43. data/test/cg/tc_llvm.rb +25 -0
  44. data/test/cg/tc_math.rb +88 -0
  45. data/test/cg/tc_module.rb +89 -0
  46. data/test/cg/tc_transforms.rb +68 -0
  47. data/test/cg/tc_type.rb +69 -0
  48. data/test/cg/tc_value.rb +151 -0
  49. data/test/cg/ts_cg.rb +23 -0
  50. data/test/tc_ast.rb +332 -0
  51. data/test/tc_cfg.rb +164 -0
  52. data/test/tc_lexer.rb +216 -0
  53. data/test/tc_parser.rb +711 -0
  54. data/test/tc_token.rb +34 -0
  55. data/test/ts_rltk.rb +47 -0
  56. metadata +317 -0
data/lib/rltk/cg.rb ADDED
@@ -0,0 +1,32 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/03/08
4
+ # Description: This file adds some autoload features for the RLTK code
5
+ # generation.
6
+
7
+ #######################
8
+ # Classes and Modules #
9
+ #######################
10
+
11
+ module RLTK
12
+ # This module contains classes and methods for code generation. Code
13
+ # generation functionality is provided by bindings to
14
+ # [LLVM](http://llvm.org).
15
+ module CG
16
+ autoload :BasicBlock, 'rltk/cg/basic_block'
17
+ autoload :Bindings, 'rltk/cg/bindings'
18
+ autoload :Builder, 'rltk/cg/builder'
19
+ autoload :Context, 'rltk/cg/context'
20
+ autoload :ExecutionEngine, 'rltk/cg/execution_engine'
21
+ autoload :Function, 'rltk/cg/function'
22
+ autoload :GenericValue, 'rltk/cg/generic_value'
23
+ autoload :Instruction, 'rltk/cg/instruction'
24
+ autoload :LLVM, 'rltk/cg/llvm'
25
+ autoload :MemoryBuffer, 'rltk/cg/memory_buffer'
26
+ autoload :Module, 'rltk/cg/module'
27
+ autoload :PassManager, 'rltk/cg/pass_manager'
28
+ autoload :Support, 'rltk/cg/support'
29
+ autoload :Type, 'rltk/cg/type'
30
+ autoload :Value, 'rltk/cg/value'
31
+ end
32
+ end
data/lib/rltk/lexer.rb ADDED
@@ -0,0 +1,372 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2011/01/17
4
+ # Description: This file contains the base class for lexers that use RLTK.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Standard Library
11
+ require 'strscan'
12
+
13
+ # Ruby Language Toolkit
14
+ require 'rltk/token'
15
+
16
+ #######################
17
+ # Classes and Modules #
18
+ #######################
19
+
20
+ module RLTK
21
+ # A LexingError exception is raised when an input stream contains a
22
+ # substring that isn't matched by any of a lexer's rules.
23
+ class LexingError < StandardError
24
+ # @return [Integer]
25
+ attr_reader :stream_offset
26
+
27
+ # @return [Integer]
28
+ attr_reader :line_number
29
+
30
+ # @return [Integer]
31
+ attr_reader :line_offset
32
+
33
+ # @return [String]
34
+ attr_reader :remainder
35
+
36
+ # @param [Integer] stream_offset Offset from begnning of string.
37
+ # @param [Integer] line_number Number of newlines encountered so far.
38
+ # @param [Integer] line_offset Offset from beginning of line.
39
+ # @param [String] remainder Rest of the string that couldn't be lexed.
40
+ def initialize(stream_offset, line_number, line_offset, remainder)
41
+ @stream_offset = stream_offset
42
+ @line_number = line_number
43
+ @line_offset = line_offset
44
+ @remainder = remainder
45
+ end
46
+
47
+ # @return [String] String representation of the error.
48
+ def to_s
49
+ "#{super()}: #{@remainder}"
50
+ end
51
+ end
52
+
53
+ # The Lexer class may be sub-classed to produce new lexers. These lexers
54
+ # have a lot of features, and are described in the main documentation.
55
+ class Lexer
56
+
57
+ # @return [Environment] Environment used by an instantiated lexer.
58
+ attr_reader :env
59
+
60
+ #################
61
+ # Class Methods #
62
+ #################
63
+
64
+ class << self
65
+ # @return [Symbol] State in which the lexer starts.
66
+ attr_reader :start_state
67
+
68
+ # Called when the Lexer class is sub-classed, it installes
69
+ # necessary instance class variables.
70
+ #
71
+ # @return [void]
72
+ def inherited(klass)
73
+ klass.install_icvars
74
+ end
75
+
76
+ # Installs instance class varialbes into a class.
77
+ #
78
+ # @return [void]
79
+ def install_icvars
80
+ @match_type = :longest
81
+ @rules = Hash.new {|h,k| h[k] = Array.new}
82
+ @start_state = :default
83
+ end
84
+
85
+ # Lex *string*, using *env* as the environment. This method will
86
+ # return the array of tokens generated by the lexer with a token
87
+ # of type EOS (End of Stream) appended to the end.
88
+ #
89
+ # @param [String] string String to be lexed.
90
+ # @param [String] file_name File name used for recording token positions.
91
+ # @param [Environment] env Lexing environment.
92
+ #
93
+ # @return [Array<Token>]
94
+ def lex(string, file_name = nil, env = self::Environment.new(@start_state))
95
+ # Offset from start of stream.
96
+ stream_offset = 0
97
+
98
+ # Offset from the start of the line.
99
+ line_offset = 0
100
+ line_number = 1
101
+
102
+ # Empty token list.
103
+ tokens = Array.new
104
+
105
+ # The scanner.
106
+ scanner = StringScanner.new(string)
107
+
108
+ # Start scanning the input string.
109
+ until scanner.eos?
110
+ match = nil
111
+
112
+ # If the match_type is set to :longest all of the
113
+ # rules for the current state need to be scanned
114
+ # and the longest match returned. If the
115
+ # match_type is :first, we only need to scan until
116
+ # we find a match.
117
+ @rules[env.state].each do |rule|
118
+ if (rule.flags - env.flags).empty?
119
+ if txt = scanner.check(rule.pattern)
120
+ if not match or match.first.length < txt.length
121
+ match = [txt, rule]
122
+
123
+ break if @match_type == :first
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ if match
130
+ rule = match.last
131
+
132
+ txt = scanner.scan(rule.pattern)
133
+ type, value = env.rule_exec(rule.pattern.match(txt), txt, &rule.action)
134
+
135
+ if type
136
+ pos = StreamPosition.new(stream_offset, line_number, line_offset, txt.length, file_name)
137
+ tokens << Token.new(type, value, pos)
138
+ end
139
+
140
+ # Advance our stat counters.
141
+ stream_offset += txt.length
142
+
143
+ if (newlines = txt.count("\n")) > 0
144
+ line_number += newlines
145
+ line_offset = txt.rpartition("\n").last.length
146
+ else
147
+ line_offset += txt.length()
148
+ end
149
+ else
150
+ error = LexingError.new(stream_offset, line_number, line_offset, scanner.rest)
151
+ raise(error, 'Unable to match string with any of the given rules')
152
+ end
153
+ end
154
+
155
+ return tokens << Token.new(:EOS)
156
+ end
157
+
158
+ # A wrapper function that calls {Lexer.lex} on the contents of a
159
+ # file.
160
+ #
161
+ # @param [String] file_name File to be lexed.
162
+ # @param [Environment] env Lexing environment.
163
+ #
164
+ # @return [Array<Token>]
165
+ def lex_file(file_name, env = self::Environment.new(@start_state))
166
+ File.open(file_name, 'r') { |f| self.lex(f.read, file_name, env) }
167
+ end
168
+
169
+ # Used to tell a lexer to use the first match found instead
170
+ # of the longest match found.
171
+ #
172
+ # @return [void]
173
+ def match_first
174
+ @match_type = :first
175
+ end
176
+
177
+ # This method is used to define a new lexing rule. The
178
+ # first argument is the regular expression used to match
179
+ # substrings of the input. The second argument is the state
180
+ # to which the rule belongs. Flags that need to be set for
181
+ # the rule to be considered are specified by the third
182
+ # argument. The last argument is a block that returns a
183
+ # type and value to be used in constructing a Token. If no
184
+ # block is specified the matched substring will be
185
+ # discarded and lexing will continue.
186
+ #
187
+ # @param [Regexp, String] pattern Pattern for matching text.
188
+ # @param [Symbol] state State in which this rule is active.
189
+ # @param [Array<Symbol>] flags Flags which must be set for rule to be active.
190
+ # @param [Proc] action Proc object that produces Tokens.
191
+ #
192
+ # @return [void]
193
+ def rule(pattern, state = :default, flags = [], &action)
194
+ # If no action is given we will set it to an empty
195
+ # action.
196
+ action ||= Proc.new() {}
197
+
198
+ pattern = Regexp.new(pattern) if pattern.is_a?(String)
199
+
200
+ r = Rule.new(pattern, action, state, flags)
201
+
202
+ if state == :ALL then @rules.each_key { |k| @rules[k] << r } else @rules[state] << r end
203
+ end
204
+ alias :r :rule
205
+
206
+ # Changes the starting state of the lexer.
207
+ #
208
+ # @param [Symbol] state Starting state for this lexer.
209
+ #
210
+ # @return [void]
211
+ def start(state)
212
+ @start_state = state
213
+ end
214
+ end
215
+
216
+ ####################
217
+ # Instance Methods #
218
+ ####################
219
+
220
+ # Instantiates a new lexer and creates an environment to be
221
+ # used for subsequent calls.
222
+ def initialize
223
+ @env = self.class::Environment.new(self.class.start_state)
224
+ end
225
+
226
+ # Lexes a string using the encapsulated environment.
227
+ #
228
+ # @param [String] string String to be lexed.
229
+ # @param [String] file_name File name used for Token positions.
230
+ #
231
+ # @return [Array<Token>]
232
+ def lex(string, file_name = nil)
233
+ self.class.lex(string, file_name, @env)
234
+ end
235
+
236
+ # Lexes a file using the encapsulated environment.
237
+ #
238
+ # @param [String] file_name File to be lexed.
239
+ #
240
+ # @return [Array<Token>]
241
+ def lex_file(file_name)
242
+ self.class.lex_file(file_name, @env)
243
+ end
244
+
245
+ # All actions passed to LexerCore.rule are evaluated inside an
246
+ # instance of the Environment class or its subclass (which must have
247
+ # the same name). This class provides functions for manipulating
248
+ # lexer state and flags.
249
+ class Environment
250
+
251
+ # @return [Array<Symbol>] Flags currently set in this environment.
252
+ attr_reader :flags
253
+
254
+ # @return [Match] Match object generated by a rule's regular expression.
255
+ attr_accessor :match
256
+
257
+ # Instantiates a new Environment object.
258
+ #
259
+ # @param [Symbol] start_state Lexer's start state.
260
+ # @param [Match] match Match object for matching text.
261
+ def initialize(start_state, match = nil)
262
+ @state = [start_state]
263
+ @match = match
264
+ @flags = Array.new
265
+ end
266
+
267
+ # This function will instance_exec a block for a rule after
268
+ # setting the match value.
269
+ #
270
+ # @param [Match] match Match object for matching text.
271
+ # @param [String] txt Text of matching string.
272
+ # @param [Proc] block Block for matched rule.
273
+ def rule_exec(match, txt, &block)
274
+ self.match = match
275
+
276
+ self.instance_exec(txt, &block)
277
+ end
278
+
279
+ # Pops a state from the state stack.
280
+ #
281
+ # @return [void]
282
+ def pop_state
283
+ @state.pop
284
+
285
+ nil
286
+ end
287
+
288
+ # Pushes a new state onto the state stack.
289
+ #
290
+ # @return [void]
291
+ def push_state(state)
292
+ @state << state
293
+
294
+ nil
295
+ end
296
+
297
+ # Sets the value on the top of the state stack.
298
+ #
299
+ # @param [Symbol] state New state for the lexing environment.
300
+ #
301
+ # @return [void]
302
+ def set_state(state)
303
+ @state[-1] = state
304
+
305
+ nil
306
+ end
307
+
308
+ # @return [Symbol] Current state of the lexing environment.
309
+ def state
310
+ @state.last
311
+ end
312
+
313
+ # Sets a flag in the current environment.
314
+ #
315
+ # @param [Symbol] flag Flag to set as enabled.
316
+ #
317
+ # @return [void]
318
+ def set_flag(flag)
319
+ if not @flags.include?(flag)
320
+ @flags << flag
321
+ end
322
+
323
+ nil
324
+ end
325
+
326
+ # Unsets a flag in the current environment.
327
+ #
328
+ # @param [Symbol] flag Flag to unset.
329
+ #
330
+ # @return [void]
331
+ def unset_flag(flag)
332
+ @flags.delete(flag)
333
+
334
+ nil
335
+ end
336
+
337
+ # Unsets all flags in the current environment.
338
+ #
339
+ # @return [void]
340
+ def clear_flags
341
+ @flags = Array.new
342
+
343
+ nil
344
+ end
345
+ end
346
+
347
+ # The Rule class is used simply for data encapsulation.
348
+ class Rule
349
+ # @return [Proc] Token producting action to be taken when this rule is matched.
350
+ attr_reader :action
351
+
352
+ # @return [Regexp] Regular expression for matching this rule.
353
+ attr_reader :pattern
354
+
355
+ # @return [Array<Symbol>] Flags currently set in this lexing environment.
356
+ attr_reader :flags
357
+
358
+ # Instantiates a new Rule object.
359
+ #
360
+ # @param [Regexp] pattern Regular expression used to match to this rule.
361
+ # @param [Proc] action Token producing action associated with this rule.
362
+ # @param [Symbol] state State in which this rule is active.
363
+ # @param [Array<Symbol>] flags Flags that must be enabled for this rule to match.
364
+ def initialize(pattern, action, state, flags)
365
+ @pattern = pattern
366
+ @action = action
367
+ @state = state
368
+ @flags = flags
369
+ end
370
+ end
371
+ end
372
+ end
@@ -0,0 +1,44 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2011/03/04
4
+ # Description: This file contains a lexer for a simple calculator.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/lexer'
12
+
13
+ #######################
14
+ # Classes and Modules #
15
+ #######################
16
+
17
+ module RLTK
18
+
19
+ # The RLTK::Lexers module contains the lexers that are included as part of
20
+ # the RLKT project.
21
+ module Lexers
22
+
23
+ # The Calculator lexer is a simple lexer for use with several of the
24
+ # provided parsers.
25
+ class Calculator < Lexer
26
+
27
+ #################
28
+ # Default State #
29
+ #################
30
+
31
+ rule(/\+/) { :PLS }
32
+ rule(/-/) { :SUB }
33
+ rule(/\*/) { :MUL }
34
+ rule(/\//) { :DIV }
35
+
36
+ rule(/\(/) { :LPAREN }
37
+ rule(/\)/) { :RPAREN }
38
+
39
+ rule(/[0-9]+/) { |t| [:NUM, t.to_i] }
40
+
41
+ rule(/\s/)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,38 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2011/01/20
4
+ # Description: This file contains a lexer for Extended Backus–Naur Form.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/lexer'
12
+
13
+ #######################
14
+ # Classes and Modules #
15
+ #######################
16
+
17
+ module RLTK
18
+ module Lexers
19
+
20
+ # The EBNF lexer is used by the RLTK::CFG class.
21
+ class EBNF < Lexer
22
+
23
+ #################
24
+ # Default State #
25
+ #################
26
+
27
+ rule(/\*/) { :STAR }
28
+ rule(/\+/) { :PLUS }
29
+ rule(/\?/) { :QUESTION }
30
+ rule(/\./) { :DOT }
31
+
32
+ rule(/[a-z0-9_']+/) { |t| [:NONTERM, t.to_sym] }
33
+ rule(/[A-Z0-9_']+/) { |t| [:TERM, t.to_sym] }
34
+
35
+ rule(/\s/)
36
+ end
37
+ end
38
+ end