Feature: Better syntax errors via `@last_good` marker

This commit is contained in:
Netscape Navigator 2020-05-10 17:08:11 -05:00
parent bb084345f6
commit 46341dd088
1 changed files with 13 additions and 1 deletions

View File

@ -13,6 +13,7 @@ module Pigeon
@scanner = StringScanner.new(bundle_string) @scanner = StringScanner.new(bundle_string)
@tokens = [] @tokens = []
@state = HEADER @state = HEADER
@last_good = :START
end end
def tokenize def tokenize
@ -75,13 +76,14 @@ module Pigeon
class LexError < StandardError; end class LexError < StandardError; end
def flunk!(why) def flunk!(why)
raise LexError, "Syntax error at #{scanner.pos}. #{why}" raise LexError, "Syntax error @ #{scanner.pos} after #{@last_good}: #{why}"
end end
# This might be a mistake or uneccessary. NN 20 MAR 2020 # This might be a mistake or uneccessary. NN 20 MAR 2020
def maybe_end_message! def maybe_end_message!
if tokens.last.last != :MESSAGE_END if tokens.last.last != :MESSAGE_END
@tokens << [:MESSAGE_END] @tokens << [:MESSAGE_END]
@last_good = :MESSAGE_END
end end
end end
@ -89,36 +91,42 @@ module Pigeon
if scanner.scan(AUTHOR) if scanner.scan(AUTHOR)
author = scanner.matched.chomp.gsub("author ", "") author = scanner.matched.chomp.gsub("author ", "")
@tokens << [:AUTHOR, author] @tokens << [:AUTHOR, author]
@last_good = :AUTHOR
return return
end end
if scanner.scan(DEPTH) if scanner.scan(DEPTH)
depth = scanner.matched.chomp.gsub("depth ", "").to_i depth = scanner.matched.chomp.gsub("depth ", "").to_i
@tokens << [:DEPTH, depth] @tokens << [:DEPTH, depth]
@last_good = :DEPTH
return return
end end
if scanner.scan(LIPMAA) if scanner.scan(LIPMAA)
depth = scanner.matched.chomp.gsub("lipmaa ", "").to_i depth = scanner.matched.chomp.gsub("lipmaa ", "").to_i
@tokens << [:LIPMAA, depth] @tokens << [:LIPMAA, depth]
@last_good = :LIPMAA
return return
end end
if scanner.scan(PREV) if scanner.scan(PREV)
prev = scanner.matched.chomp.gsub("prev ", "") prev = scanner.matched.chomp.gsub("prev ", "")
@tokens << [:PREV, prev] @tokens << [:PREV, prev]
@last_good = :PREV
return return
end end
if scanner.scan(KIND) if scanner.scan(KIND)
kind = scanner.matched.chomp.gsub("kind ", "") kind = scanner.matched.chomp.gsub("kind ", "")
@tokens << [:KIND, kind] @tokens << [:KIND, kind]
@last_good = :KIND
return return
end end
if scanner.scan(SEPERATOR) if scanner.scan(SEPERATOR)
@state = BODY @state = BODY
@tokens << [:HEADER_END] @tokens << [:HEADER_END]
@last_good = :HEADER_SEPERATOR
return return
end end
@ -129,12 +137,14 @@ module Pigeon
if scanner.scan(BODY_ENTRY) if scanner.scan(BODY_ENTRY)
key, value = scanner.matched.chomp.split(":") key, value = scanner.matched.chomp.split(":")
@tokens << [:BODY_ENTRY, key, value] @tokens << [:BODY_ENTRY, key, value]
@last_good = :A_BODY_ENTRY
return return
end end
if scanner.scan(SEPERATOR) if scanner.scan(SEPERATOR)
@state = FOOTER @state = FOOTER
@tokens << [:BODY_END] @tokens << [:BODY_END]
@last_good = :BODY_SEPERATOR
return return
end end
@ -148,12 +158,14 @@ module Pigeon
if scanner.scan(FOOTER_ENTRY) if scanner.scan(FOOTER_ENTRY)
sig = scanner.matched.strip.gsub("signature ", "") sig = scanner.matched.strip.gsub("signature ", "")
@tokens << [:SIGNATURE, sig] @tokens << [:SIGNATURE, sig]
@last_good = :FOOTER_ENTRY
return return
end end
if scanner.scan(SEPERATOR) if scanner.scan(SEPERATOR)
@state = HEADER @state = HEADER
maybe_end_message! maybe_end_message!
@last_good = :FOOTER_SEPERATOR
return return
end end