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