rltk 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rltk/cg.rb ADDED
@@ -0,0 +1,33 @@
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 # :nodoc:
12
+
13
+ # This module contains classes and methods for code generation. Code
14
+ # generation functionality is provided by bindings to
15
+ # [LLVM](http://llvm.org).
16
+ module CG
17
+ autoload :BasicBloc, 'rltk/cg/basic_block'
18
+ autoload :Bindings, 'rltk/cg/bindings'
19
+ autoload :Builder, 'rltk/cg/builder'
20
+ autoload :Context, 'rltk/cg/context'
21
+ autoload :ExecutionEngine, 'rltk/cg/execution_engine'
22
+ autoload :Function, 'rltk/cg/function'
23
+ autoload :GenericValue, 'rltk/cg/generic_value'
24
+ autoload :Instruction, 'rltk/cg/instruction'
25
+ autoload :LLVM, 'rltk/cg/llvm'
26
+ autoload :MemoryBuffer, 'rltk/cg/memory_buffer'
27
+ autoload :Module, 'rltk/cg/module'
28
+ autoload :PassManager, 'rltk/cg/pass_manager'
29
+ autoload :Support, 'rltk/cg/support'
30
+ autoload :Type, 'rltk/cg/type'
31
+ autoload :Value, 'rltk/cg/value'
32
+ end
33
+ end
data/lib/rltk/lexer.rb CHANGED
@@ -21,7 +21,12 @@ module RLTK # :nodoc:
21
21
 
22
22
  # A LexingError exception is raised when an input stream contains a
23
23
  # substring that isn't matched by any of a lexer's rules.
24
- class LexingError < Exception
24
+ class LexingError < StandardError
25
+
26
+ # @param [Integer] stream_offset Offset from begnning of string.
27
+ # @param [Integer] line_number Number of newlines encountered so far.
28
+ # @param [Integer] line_offset Offset from beginning of line.
29
+ # @param [String] remainder Rest of the string that couldn't be lexed.
25
30
  def initialize(stream_offset, line_number, line_offset, remainder)
26
31
  @stream_offset = stream_offset
27
32
  @line_number = line_number
@@ -29,7 +34,8 @@ module RLTK # :nodoc:
29
34
  @remainder = remainder
30
35
  end
31
36
 
32
- def to_s()
37
+ # @return [String] String representation of the error.
38
+ def to_s
33
39
  "#{super()}: #{@remainder}"
34
40
  end
35
41
  end
@@ -38,98 +44,61 @@ module RLTK # :nodoc:
38
44
  # have a lot of features, and are described in the main documentation.
39
45
  class Lexer
40
46
 
41
- # Called when the Lexer class is sub-classed, this method adds a
42
- # LexerCore to the new class, and installs some needed class and
43
- # instance methods.
44
- def Lexer.inherited(klass)
45
- klass.class_exec do
46
- @core = LexerCore.new
47
-
48
- # Returns this class's LexerCore object.
49
- def self.core
50
- @core
51
- end
52
-
53
- # Lexes the given string using a newly instantiated
54
- # environment.
55
- def self.lex(str)
56
- @core.lex(str, self::Environment.new(@core.start_state))
57
- end
58
-
59
- # Lexes the contents of the given file using a newly
60
- # instantiated environment.
61
- def self.lex_file(file_name)
62
- @core.lex_file(file_name, self::Environment.new(@core.start_state))
63
- end
64
-
65
- # Routes method calls to the new subclass to the LexerCore
66
- # object.
67
- def self.method_missing(method, *args, &proc)
68
- @core.send(method, *args, &proc)
69
- end
70
-
71
- # Instantiates a new lexer and creates an environment to be
72
- # used for subsequent calls.
73
- def initialize
74
- @env = self.class::Environment.new(self.class.core.start_state)
75
- end
76
-
77
- # Returns the environment used by an instantiated lexer.
78
- def env
79
- @env
80
- end
81
-
82
- # Lexes a string using the encapsulated environment.
83
- def lex(string)
84
- self.class.core.lex(string, @env)
85
- end
86
-
87
- # Lexes a file using the encapsulated environment.
88
- def lex_file(file_name)
89
- self.class.core.lex_file(file_name, @env)
90
- end
91
- end
92
- end
47
+ # @return [Environment] Environment used by an instantiated lexer.
48
+ attr_reader :env
93
49
 
94
50
  #################
95
- # Inner Classes #
51
+ # Class Methods #
96
52
  #################
97
53
 
98
- # The LexerCore class provides most of the functionality of the Lexer
99
- # class. A LexerCore is instantiated for each subclass of Lexer,
100
- # thereby allowing multiple lexers to be defined inside a single Ruby
101
- # program.
102
- class LexerCore
54
+ class << self
55
+ # @return [Symbol] State in which the lexer starts.
103
56
  attr_reader :start_state
104
57
 
105
- # Instantiate a new LexerCore object.
106
- def initialize
58
+ # Installs instance class varialbes into a class.
59
+ #
60
+ # @return [void]
61
+ def install_icvars
107
62
  @match_type = :longest
108
63
  @rules = Hash.new {|h,k| h[k] = Array.new}
109
64
  @start_state = :default
110
65
  end
111
66
 
112
- # Lex _string_, using _env_ as the environment. This method will
67
+ # Called when the Lexer class is sub-classed, it installes
68
+ # necessary instance class variables.
69
+ #
70
+ # @return [void]
71
+ def inherited(klass)
72
+ klass.install_icvars
73
+ end
74
+
75
+ # Lex *string*, using *env* as the environment. This method will
113
76
  # return the array of tokens generated by the lexer with a token
114
77
  # of type EOS (End of Stream) appended to the end.
115
- def lex(string, env, file_name = nil)
78
+ #
79
+ # @param [String] string String to be lexed.
80
+ # @param [String] file_name File name used for recording token positions.
81
+ # @param [Environment] env Lexing environment.
82
+ #
83
+ # @return [Array<Token>]
84
+ def lex(string, file_name = nil, env = self::Environment.new(@start_state))
116
85
  # Offset from start of stream.
117
86
  stream_offset = 0
118
-
87
+
119
88
  # Offset from the start of the line.
120
89
  line_offset = 0
121
90
  line_number = 1
122
-
91
+
123
92
  # Empty token list.
124
93
  tokens = Array.new
125
-
94
+
126
95
  # The scanner.
127
96
  scanner = StringScanner.new(string)
128
-
97
+
129
98
  # Start scanning the input string.
130
99
  until scanner.eos?
131
100
  match = nil
132
-
101
+
133
102
  # If the match_type is set to :longest all of the
134
103
  # rules for the current state need to be scanned
135
104
  # and the longest match returned. If the
@@ -140,27 +109,27 @@ module RLTK # :nodoc:
140
109
  if txt = scanner.check(rule.pattern)
141
110
  if not match or match.first.length < txt.length
142
111
  match = [txt, rule]
143
-
112
+
144
113
  break if @match_type == :first
145
114
  end
146
115
  end
147
116
  end
148
117
  end
149
-
118
+
150
119
  if match
151
120
  rule = match.last
152
-
121
+
153
122
  txt = scanner.scan(rule.pattern)
154
123
  type, value = env.rule_exec(rule.pattern.match(txt), txt, &rule.action)
155
-
124
+
156
125
  if type
157
126
  pos = StreamPosition.new(stream_offset, line_number, line_offset, txt.length, file_name)
158
127
  tokens << Token.new(type, value, pos)
159
128
  end
160
-
129
+
161
130
  # Advance our stat counters.
162
131
  stream_offset += txt.length
163
-
132
+
164
133
  if (newlines = txt.count("\n")) > 0
165
134
  line_number += newlines
166
135
  line_offset = 0
@@ -172,18 +141,25 @@ module RLTK # :nodoc:
172
141
  raise(error, 'Unable to match string with any of the given rules')
173
142
  end
174
143
  end
175
-
144
+
176
145
  return tokens << Token.new(:EOS)
177
146
  end
178
147
 
179
- # A wrapper function that calls ParserCore.lex on the
180
- # contents of a file.
181
- def lex_file(file_name, env)
182
- File.open(file_name, 'r') { |f| lex(f.read, env, file_name) }
148
+ # A wrapper function that calls {Lexer.lex} on the contents of a
149
+ # file.
150
+ #
151
+ # @param [String] file_name File to be lexed.
152
+ # @param [Environment] env Lexing environment.
153
+ #
154
+ # @return [Array<Token>]
155
+ def lex_file(file_name, env = self::Environment.new(@start_state))
156
+ File.open(file_name, 'r') { |f| self.lex(f.read, file_name, env) }
183
157
  end
184
158
 
185
159
  # Used to tell a lexer to use the first match found instead
186
160
  # of the longest match found.
161
+ #
162
+ # @return [void]
187
163
  def match_first
188
164
  @match_type = :first
189
165
  end
@@ -197,6 +173,13 @@ module RLTK # :nodoc:
197
173
  # type and value to be used in constructing a Token. If no
198
174
  # block is specified the matched substring will be
199
175
  # discarded and lexing will continue.
176
+ #
177
+ # @param [Regexp, String] pattern Pattern for matching text.
178
+ # @param [Symbol] state State in which this rule is active.
179
+ # @param [Array<Symbol>] flags Flags which must be set for rule to be active.
180
+ # @param [Proc] action Proc object that produces Tokens.
181
+ #
182
+ # @return [void]
200
183
  def rule(pattern, state = :default, flags = [], &action)
201
184
  # If no action is given we will set it to an empty
202
185
  # action.
@@ -208,28 +191,63 @@ module RLTK # :nodoc:
208
191
 
209
192
  if state == :ALL then @rules.each_key { |k| @rules[k] << r } else @rules[state] << r end
210
193
  end
211
-
212
194
  alias :r :rule
213
195
 
214
196
  # Changes the starting state of the lexer.
197
+ #
198
+ # @param [Symbol] state Starting state for this lexer.
199
+ #
200
+ # @return [void]
215
201
  def start(state)
216
202
  @start_state = state
217
203
  end
218
204
  end
219
205
 
206
+ ####################
207
+ # Instance Methods #
208
+ ####################
209
+
210
+ # Instantiates a new lexer and creates an environment to be
211
+ # used for subsequent calls.
212
+ def initialize
213
+ @env = self.class::Environment.new(self.class.start_state)
214
+ end
215
+
216
+ # Lexes a string using the encapsulated environment.
217
+ #
218
+ # @param [String] string String to be lexed.
219
+ # @param [String] file_name File name used for Token positions.
220
+ #
221
+ # @return [Array<Token>]
222
+ def lex(string, file_name = nil)
223
+ self.class.lex(string, file_name, @env)
224
+ end
225
+
226
+ # Lexes a file using the encapsulated environment.
227
+ #
228
+ # @param [String] file_name File to be lexed.
229
+ #
230
+ # @return [Array<Token>]
231
+ def lex_file(file_name)
232
+ self.class.lex_file(file_name, @env)
233
+ end
234
+
220
235
  # All actions passed to LexerCore.rule are evaluated inside an
221
236
  # instance of the Environment class or its subclass (which must have
222
237
  # the same name). This class provides functions for manipulating
223
238
  # lexer state and flags.
224
239
  class Environment
225
240
 
226
- # The flags currently set in this environment.
241
+ # @return [Array<Symbol>] Flags currently set in this environment.
227
242
  attr_reader :flags
228
243
 
229
- # The Match object generated by a rule's regular expression.
244
+ # @return [Match] Match object generated by a rule's regular expression.
230
245
  attr_accessor :match
231
246
 
232
247
  # Instantiates a new Environment object.
248
+ #
249
+ # @param [Symbol] start_state Lexer's start state.
250
+ # @param [Match] match Match object for matching text.
233
251
  def initialize(start_state, match = nil)
234
252
  @state = [start_state]
235
253
  @match = match
@@ -238,6 +256,10 @@ module RLTK # :nodoc:
238
256
 
239
257
  # This function will instance_exec a block for a rule after
240
258
  # setting the match value.
259
+ #
260
+ # @param [Match] match Match object for matching text.
261
+ # @param [String] txt Text of matching string.
262
+ # @param [Proc] block Block for matched rule.
241
263
  def rule_exec(match, txt, &block)
242
264
  self.match = match
243
265
 
@@ -245,6 +267,8 @@ module RLTK # :nodoc:
245
267
  end
246
268
 
247
269
  # Pops a state from the state stack.
270
+ #
271
+ # @return [void]
248
272
  def pop_state
249
273
  @state.pop
250
274
 
@@ -252,6 +276,8 @@ module RLTK # :nodoc:
252
276
  end
253
277
 
254
278
  # Pushes a new state onto the state stack.
279
+ #
280
+ # @return [void]
255
281
  def push_state(state)
256
282
  @state << state
257
283
 
@@ -259,18 +285,26 @@ module RLTK # :nodoc:
259
285
  end
260
286
 
261
287
  # Sets the value on the top of the state stack.
288
+ #
289
+ # @param [Symbol] state New state for the lexing environment.
290
+ #
291
+ # @return [void]
262
292
  def set_state(state)
263
293
  @state[-1] = state
264
294
 
265
295
  nil
266
296
  end
267
297
 
268
- # Returns the current state.
298
+ # @return [Symbol] Current state of the lexing environment.
269
299
  def state
270
- return @state.last
300
+ @state.last
271
301
  end
272
302
 
273
303
  # Sets a flag in the current environment.
304
+ #
305
+ # @param [Symbol] flag Flag to set as enabled.
306
+ #
307
+ # @return [void]
274
308
  def set_flag(flag)
275
309
  if not @flags.include?(flag)
276
310
  @flags << flag
@@ -280,6 +314,10 @@ module RLTK # :nodoc:
280
314
  end
281
315
 
282
316
  # Unsets a flag in the current environment.
317
+ #
318
+ # @param [Symbol] flag Flag to unset.
319
+ #
320
+ # @return [void]
283
321
  def unset_flag(flag)
284
322
  @flags.delete(flag)
285
323
 
@@ -287,6 +325,8 @@ module RLTK # :nodoc:
287
325
  end
288
326
 
289
327
  # Unsets all flags in the current environment.
328
+ #
329
+ # @return [void]
290
330
  def clear_flags
291
331
  @flags = Array.new
292
332
 
@@ -296,11 +336,21 @@ module RLTK # :nodoc:
296
336
 
297
337
  # The Rule class is used simply for data encapsulation.
298
338
  class Rule
339
+ # @return [Proc] Token producting action to be taken when this rule is matched.
299
340
  attr_reader :action
341
+
342
+ # @return [Regexp] Regular expression for matching this rule.
300
343
  attr_reader :pattern
344
+
345
+ # @return [Array<Symbol>] Flags currently set in this lexing environment.
301
346
  attr_reader :flags
302
347
 
303
348
  # Instantiates a new Rule object.
349
+ #
350
+ # @param [Regexp] pattern Regular expression used to match to this rule.
351
+ # @param [Proc] action Token producing action associated with this rule.
352
+ # @param [Symbol] state State in which this rule is active.
353
+ # @param [Array<Symbol>] flags Flags that must be enabled for this rule to match.
304
354
  def initialize(pattern, action, state, flags)
305
355
  @pattern = pattern
306
356
  @action = action
@@ -15,7 +15,10 @@ require 'rltk/lexer'
15
15
  #######################
16
16
 
17
17
  module RLTK # :nodoc:
18
- module Lexers # :nodoc:
18
+
19
+ # The RLTK::Lexers module contains the lexers that are included as part of
20
+ # the RLKT project.
21
+ module Lexers
19
22
 
20
23
  # The Calculator lexer is a simple lexer for use with several of the
21
24
  # provided parsers.
@@ -15,10 +15,7 @@ require 'rltk/lexer'
15
15
  #######################
16
16
 
17
17
  module RLTK # :nodoc:
18
-
19
- # The RLTK::Lexers module contains the lexers that are included as part of
20
- # the RLKT project.
21
- module Lexers
18
+ module Lexers # :nodoc:
22
19
 
23
20
  # The EBNF lexer is used by the RLTK::CFG class.
24
21
  class EBNF < Lexer