From 8647a15a1923039ca1a37ef7c337256d479f7240 Mon Sep 17 00:00:00 2001 From: inglorion Date: Mon, 4 Apr 2011 04:10:12 +0200 Subject: [PATCH] Improved error reporting --- bin/voodooc | 2 +- lib/voodoo/parser.rb | 68 ++++++++++++++++++++++++++++++++++++------------- lib/voodoo/validator.rb | 17 ++++++++----- 3 files changed, 62 insertions(+), 25 deletions(-) diff --git a/bin/voodooc b/bin/voodooc index f1e0424..be91047 100755 --- a/bin/voodooc +++ b/bin/voodooc @@ -157,7 +157,7 @@ rescue => e message << error.message $stderr.puts message if error.text != nil - $stderr.print "\n #{error.text}\n" + $stderr.print "\n #{error.text.gsub("\n", "\n ")}\n" end end else diff --git a/lib/voodoo/parser.rb b/lib/voodoo/parser.rb index 5cb6c34..4c073af 100644 --- a/lib/voodoo/parser.rb +++ b/lib/voodoo/parser.rb @@ -71,29 +71,54 @@ module Voodoo # Parses a body for a function or a conditional def parse_body kind body = [] + error = nil case kind when :function kind_text = 'function definition' else kind_text = kind.to_s end - while true - statement = parse_top_level_nonvalidating - if statement == nil - parse_error "End of input while inside #{kind_text}", nil - elsif statement[0] == :end - # Done parsing body - break - elsif kind == :conditional && statement[0] == :else - # Done parsing body, but there is another one coming up - body << statement - break - else - # Should be a normal statement. Validate it, then add it to body. - validate_top_level { statement } - body << statement + done = false + until done + begin + with_position do + statement = parse_top_level_nonvalidating + if statement == nil + done = true + parse_error "End of input while inside #{kind_text}", nil + elsif statement[0] == :end + # Done parsing body + done = true + elsif kind == :conditional && statement[0] == :else + # Done parsing body, but there is another one coming up + body << statement + done = true + else + # Should be a normal statement. Validate it, then add it to body + if statement[0] == :function + parse_error "Function definitions are only allowed at top-level" + end + begin + Validator.validate_statement statement + body << statement + rescue Validator::ValidationError => e + parse_error e.message + end + end + end + rescue => e + # Got some kind of error. Still try to parse the rest of the body. + # Save the error if it was the first one. + if error == nil + error = e + end end end + + if error != nil + raise error + end + body end @@ -267,8 +292,15 @@ module Voodoo # Create the error object error = ParseError.new(message, @input_name, @start_line, @start_column, text) + # Set a backtrace to the calling method error.set_backtrace caller + + # If we are not at a new line, skip until the next line + while @column != 1 && lookahead != :eof + consume + end + # Raise the error raise error end @@ -300,7 +332,7 @@ module Voodoo consume end else - parse_error "Unexpected character in input", lookahead + parse_error "Unexpected character (#{lookahead}) in input" end else # Word is not nil @@ -413,8 +445,8 @@ module Voodoo when /\w|\\/ expr = parse_symbol else - parse_error "Invalid character (lookahead.inspect) " + - "in at-expression; expecting number or symbol", lookahead + parse_error "Invalid character (#{lookahead}) " + + "in at-expression; expecting number or symbol" end [:'@', expr] else diff --git a/lib/voodoo/validator.rb b/lib/voodoo/validator.rb index 6e1c933..6eb3275 100644 --- a/lib/voodoo/validator.rb +++ b/lib/voodoo/validator.rb @@ -316,7 +316,14 @@ module Voodoo end # Verify statements - code[2..-1].each {|stmt| validate_statement stmt} + code[2..-1].each do |stmt| + if stmt.respond_to?(:[]) && stmt[0] == :function + raise ValidationError.new("Function definitions are only " + + "valid at top-level", stmt) + else + validate_statement stmt + end + end when :section @@ -327,7 +334,7 @@ module Voodoo code) when 2 unless code[1].kind_of?(::String) || code[1].kind_of?(::Symbol) - raise ValidationError.new("Section name should be a String" + + raise ValidationError.new("Section name should be a string" + " or a symbol", code) end @@ -351,10 +358,8 @@ module Voodoo if STATEMENTS.member? code[0] validate_statement code else - raise ValidationError.new("Directive #{code[0].inspect}" + - " not valid at top-level;" + - " valid directives are: " + - TOP_LEVELS.join(', '), + raise ValidationError.new("Directive #{code[0]}" + + " not valid at top-level", code) end end -- 2.11.4.GIT