lib/rhcl/parse.y in rhcl-0.0.3 vs lib/rhcl/parse.y in rhcl-0.0.4

- old
+ new

@@ -110,97 +110,98 @@ @ss = StringScanner.new(src) end def scan tok = nil - @prev_tokens = [] + @backup = [] until @ss.eos? - if (tok = @ss.scan /\s+/) + if (tok = backup { @ss.scan /\s+/ }) # nothing to do - elsif (tok = @ss.scan(/#/)) - @prev_tokens << tok - @prev_tokens << @ss.scan_until(/\n/) - tok = '' - elsif (tok = @ss.scan(%r|/|)) - @prev_tokens << tok - - case (tok = @ss.getch) + elsif (tok = backup { @ss.scan /#/ }) + backup { @ss.scan_until /\n/ } + elsif (tok = backup { @ss.scan %r|/| }) + case (tok = backup { @ss.getch }) when '/' - @prev_tokens << tok - @prev_tokens << @ss.scan_until(/(\n|\z)/) + backup { @ss.scan_until /(\n|\z)/ } when '*' - @prev_tokens << tok nested = 1 until nested.zero? - case (tok = @ss.scan_until(%r{(/\*|\*/|\z)})) + case (tok = backup { @ss.scan_until %r{(/\*|\*/|\z)} }) when %r|/\*\z| - @prev_tokens << tok nested += 1 when %r|\*/\z| - @prev_tokens << tok nested -= 1 else - @prev_tokens << tok break end end else - raise "comment expected, got '#{tok}'" + raise "comment expected, got #{tok.inspect}" end - - tok = '' - elsif (tok = @ss.scan(/-?\d+\.\d+/)) + elsif (tok = backup { @ss.scan /-?\d+\.\d+/ }) yield [:FLOAT, tok.to_f] - elsif (tok = @ss.scan(/-?\d+/)) + elsif (tok = backup { @ss.scan /-?\d+/ }) yield [:INTEGER, tok.to_i] - elsif (tok = @ss.scan(/,/)) + elsif (tok = backup { @ss.scan /,/ }) yield [:COMMA, tok] - elsif (tok = @ss.scan(/\=/)) + elsif (tok = backup { @ss.scan /\=/ }) yield [:EQUAL, tok] - elsif (tok = @ss.scan(/\[/)) + elsif (tok = backup { @ss.scan /\[/ }) yield [:LEFTBRACKET, tok] - elsif (tok = @ss.scan(/\]/)) + elsif (tok = backup { @ss.scan /\]/ }) yield [:RIGHTBRACKET, tok] - elsif (tok = @ss.scan(/\{/)) + elsif (tok = backup { @ss.scan /\{/ }) yield [:LEFTBRACE, tok] - elsif (tok = @ss.scan(/\}/)) + elsif (tok = backup { @ss.scan /\}/ }) yield [:RIGHTBRACE, tok] - elsif (tok = @ss.scan(/"/)) - yield [:STRING, (@ss.scan_until(/("|\z)/) || '').sub(/"\z/, '')] + elsif (tok = backup { @ss.scan /"/ }) + yield [:STRING, (backup { @ss.scan_until /("|\z)/ } || '').sub(/"\z/, '')] else - tok = (@ss.scan_until(/(\s|\z)/) || '').sub(/\s\z/, '') + identifier = (backup { @ss.scan_until /(\s|\z)/ } || '').sub(/\s\z/, '') token_type = :IDENTIFIER - if ['true', 'false'].include?(tok) - tok = !!(tok =~ /true/) + if ['true', 'false'].include?(identifier) + identifier = !!(identifier =~ /true/) token_type = :BOOL end - yield [token_type, tok] + yield [token_type, identifier] end - - @prev_tokens << tok end yield [false, '$end'] end private :scan +def backup + tok = yield + @backup << tok if tok + return tok +end + def parse yyparse self, :scan end def on_error(error_token_id, error_value, value_stack) raise_error(error_value) end def raise_error(error_value) header = "parse error on value: #{error_value}\n" - prev = (@prev_tokens || []) + error_value = @backup.pop + + if error_value =~ /\n\z/ + error_value = '__' + error_value.chomp + "__\n" + else + error_value = '__' + error_value + '__' + end + + prev = (@backup || []) prev = prev.empty? ? '' : prev.join + ' ' - errmsg = prev + "__#{error_value}__" + errmsg = prev + error_value if @ss and @ss.rest? errmsg << ' ' + @ss.rest end