lib/import/shake_grammar/lexer.rb in tracksperanto-1.6.6 vs lib/import/shake_grammar/lexer.rb in tracksperanto-1.6.7
- old
+ new
@@ -1,15 +1,25 @@
module Tracksperanto::ShakeGrammar
# Since Shake uses a C-like language for it's scripts we rig up a very sloppy
# but concise C-like lexer to cope
class Lexer
+ # Parsed stack
attr_reader :stack
- def initialize(with_io)
- @io, @stack, @buf = with_io, [], ''
- parse until (@io.eof? || @stop)
+ # Access to the sentinel object
+ attr_reader :sentinel
+
+ STOP_TOKEN = :__stop #:nodoc:
+
+ # The first argument is the IO handle to the data of the Shake script.
+ # The second argument is a "sentinel" that is going to be passed
+ # to the downstream lexers instantiated for nested data structures.
+ # You can use the sentinel to collect data from child nodes for example.
+ def initialize(with_io, sentinel = nil)
+ @io, @stack, @buf, @sentinel = with_io, [], '', sentinel
+ catch(STOP_TOKEN) { parse until @io.eof? }
in_comment? ? consume_comment("\n") : consume_atom!
end
private
@@ -29,18 +39,18 @@
def parse
c = @io.read(1)
return consume_comment(c) if in_comment?
if !@buf.empty? && (c == "(") # Funcall
- push([:funcall, @buf.strip] + self.class.new(@io).stack)
+ push([:funcall, @buf.strip] + self.class.new(@io, @sentinel).stack)
@buf = ''
elsif c == "[" # Array, booring
push([:arr] + self.class.new(@io).stack)
elsif (c == "]" || c == ")")
# Funcall end, and when it happens assume we are called as
# a subexpression.
consume_atom!
- @stop = true
+ throw STOP_TOKEN
elsif (c == ",")
consume_atom!
elsif (c == ";" || c == "\n")
# Skip these - the subexpression already is expanded anyway
elsif (c == "=")
\ No newline at end of file