From 642be10afc2b1545b3765962c60ae39b7a766674 Mon Sep 17 00:00:00 2001 From: shaggy Date: Fri, 28 Aug 2026 02:18:41 +0530 Subject: [PATCH] cmd/goyacc: don't panic on grammar files ending without a newline getrune keeps EOF sticky in peekrune (it returns EOF without clearing the slot), so when gettok's IDENTIFIER/IDENTCOLON look-ahead reaches end-of-file and ungets the EOF rune, ungetrune hit its single-slot "2nd unget" panic. A 10-byte grammar such as %% S: A; B (with no trailing newline) crashed with panic: ungetc - 2nd unget Make ungetting EOF a no-op: an exhausted reader returns EOF again on the next read regardless, so behavior for well-formed files is unchanged. The example above now reports the proper syntax error ("illegal rule: missing semicolon or |"), and a valid grammar compiles to identical output. --- cmd/goyacc/yacc.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmd/goyacc/yacc.go b/cmd/goyacc/yacc.go index 3729739dda3..f9d1db46c73 100644 --- a/cmd/goyacc/yacc.go +++ b/cmd/goyacc/yacc.go @@ -3156,6 +3156,13 @@ func ungetrune(f *bufio.Reader, c rune) { if f != finput { panic("ungetc - not finput") } + if c == EOF { + // getrune keeps EOF sticky in peekrune, so re-ungetting EOF (e.g. + // from gettok's IDENTIFIER/IDENTCOLON look-ahead at end of file) + // must not trip the single-slot check; an exhausted reader returns + // EOF again anyway. + return + } if peekrune != 0 { panic("ungetc - 2nd unget") }