@@ -31,7 +31,8 @@ yulParserTests =
3131 " Yul parser"
3232 [ functionKeywordTests,
3333 boolLiteralTests,
34- switchTests
34+ switchTests,
35+ statementKeywordTests
3536 ]
3637
3738-- Bug 1: yulFun matched the `function` keyword with `symbol "function"`, which
@@ -70,6 +71,40 @@ boolLiteralTests =
7071 parsesAs yulExp " false" (YLit YulFalse )
7172 ]
7273
74+ -- Bug 4: pKeyword ran `string` (consuming input) before the
75+ -- `notFollowedBy identChar` boundary check, and was not wrapped in `try`. In a
76+ -- `choice`, a keyword parser that consumed a prefix and then failed the
77+ -- boundary check aborted the whole choice instead of falling through to a
78+ -- later alternative -- so a statement whose leading identifier merely starts
79+ -- with a keyword (e.g. `format` vs `for`) failed to parse. Every
80+ -- statement-level keyword is affected, including the merged
81+ -- break/continue/leave.
82+ statementKeywordTests :: TestTree
83+ statementKeywordTests =
84+ testGroup
85+ " statement keyword boundary"
86+ ( [ testCase (kw ++ " -prefixed identifier parses as a call statement" ) $
87+ parsesAs yulStmt (kw ++ " ish" ) (YExp (yIdent (kw ++ " ish" )))
88+ | kw <- [" let" , " if" , " for" , " switch" , " case" , " default" , " break" , " continue" , " leave" ]
89+ ]
90+ ++
91+ -- The canonical case from the bug report: `format` must not be read as a
92+ -- `for` loop.
93+ [ testCase " `format` parses as an identifier, not a for loop" $
94+ parsesAs yulStmt " format" (YExp (yIdent " format" )),
95+ -- Regression guards: the bare keyword statements still parse.
96+ testCase " bare break parses" $ parsesAs yulStmt " break" YBreak ,
97+ testCase " bare continue parses" $ parsesAs yulStmt " continue" YContinue ,
98+ testCase " bare leave parses" $ parsesAs yulStmt " leave" YLeave ,
99+ testCase " genuine let still parses" $
100+ parsesAs yulStmt " let x" (YLet [Name " x" ] Nothing ),
101+ testCase " genuine if still parses" $
102+ parsesAs yulStmt " if cond { }" (YIf (yIdent " cond" ) [] ),
103+ testCase " genuine for still parses" $
104+ parsesAs yulStmt " for { } cond { } { }" (YFor [] (yIdent " cond" ) [] [] )
105+ ]
106+ )
107+
73108-- Bug 3: YSwitch used `many yulCase`, so a switch with zero `case` clauses
74109-- parsed successfully. Yul requires at least one case.
75110switchTests :: TestTree
0 commit comments