From e68624b6081a48e0eccfc3346f3bed59da99e7a8 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Mon, 3 Nov 2025 20:16:15 -0800 Subject: [PATCH] elseif -> else if --- src/compiler/tests/compiler.test.ts | 12 +++++------ src/compiler/utils.ts | 2 +- src/parser/shrimp.grammar | 3 +-- src/parser/shrimp.terms.ts | 6 +++--- src/parser/shrimp.ts | 18 ++++++++--------- src/parser/tests/control-flow.test.ts | 29 +++++++++++++++------------ 6 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/compiler/tests/compiler.test.ts b/src/compiler/tests/compiler.test.ts index 9418f0b..743f738 100644 --- a/src/compiler/tests/compiler.test.ts +++ b/src/compiler/tests/compiler.test.ts @@ -154,18 +154,18 @@ describe('compiler', () => { end`).toEvaluateTo('white') }) - test('if elseif', () => { + test('if else if', () => { expect(`if false: boromir - elseif true: + else if true: frodo end`).toEvaluateTo('frodo') }) - test('if elseif else', () => { + test('if else if else', () => { expect(`if false: destroyed - elseif true: + else if true: fire else: darkness @@ -173,9 +173,9 @@ describe('compiler', () => { expect(`if false: king - elseif false: + else if false: elf - elseif true: + else if true: dwarf else: scattered diff --git a/src/compiler/utils.ts b/src/compiler/utils.ts index 893c5eb..ed0dfcc 100644 --- a/src/compiler/utils.ts +++ b/src/compiler/utils.ts @@ -210,7 +210,7 @@ export const getIfExprParts = (node: SyntaxNode, input: string) => { } elseThenBlock = parts.at(-1) } else if (child.type.id === terms.ElseIfExpr) { - const [_keyword, conditional, _colon, thenBlock] = parts + const [_else, _if, conditional, _colon, thenBlock] = parts if (!conditional || !thenBlock) { const names = parts.map((p) => p.type.name).join(', ') const message = `ElseIfExpr expected conditional and thenBlock, got ${names}` diff --git a/src/parser/shrimp.grammar b/src/parser/shrimp.grammar index ce0fa45..4ed609a 100644 --- a/src/parser/shrimp.grammar +++ b/src/parser/shrimp.grammar @@ -31,7 +31,6 @@ end { @specialize[@name=keyword] } while { @specialize[@name=keyword] } if { @specialize[@name=keyword] } else { @specialize[@name=keyword] } -elseif { @specialize[@name=keyword] } try { @specialize[@name=keyword] } catch { @specialize[@name=keyword] } finally { @specialize[@name=keyword] } @@ -121,7 +120,7 @@ IfExpr { } ElseIfExpr { - elseif (ConditionalOp | expression) colon Block + else if (ConditionalOp | expression) colon Block } ElseExpr { diff --git a/src/parser/shrimp.terms.ts b/src/parser/shrimp.terms.ts index a844f1f..498ae00 100644 --- a/src/parser/shrimp.terms.ts +++ b/src/parser/shrimp.terms.ts @@ -47,7 +47,7 @@ export const Null = 45, colon = 46, CatchExpr = 47, - keyword = 69, + keyword = 67, Block = 49, FinallyExpr = 50, Underscore = 53, @@ -60,5 +60,5 @@ export const IfExpr = 64, ElseIfExpr = 66, ElseExpr = 68, - CompoundAssign = 70, - Assign = 71 + CompoundAssign = 69, + Assign = 70 diff --git a/src/parser/shrimp.ts b/src/parser/shrimp.ts index 7a852b9..c25351b 100644 --- a/src/parser/shrimp.ts +++ b/src/parser/shrimp.ts @@ -4,14 +4,14 @@ import {operatorTokenizer} from "./operatorTokenizer" import {tokenizer, specializeKeyword} from "./tokenizer" import {trackScope} from "./scopeTracker" import {highlighting} from "./highlight" -const spec_Identifier = {__proto__:null,null:90, catch:96, finally:102, end:104, while:118, try:122, throw:126, if:130, elseif:134, else:138} +const spec_Identifier = {__proto__:null,null:90, catch:96, finally:102, end:104, while:118, try:122, throw:126, if:130, else:134} export const parser = LRParser.deserialize({ version: 14, - states: "7vQYQbOOO#}QcO'#C{O$zOSO'#C}OOQa'#DT'#DTO&TQbO'#DdO'lQcO'#E]OOQa'#E]'#E]O(oQcO'#E]O)qQcO'#E[O*[QRO'#C|O+nQcO'#EWO,OQcO'#EWO,YQbO'#CzO-QOpO'#CxOOQ`'#EX'#EXO-VQbO'#EWO-^QRO'#DtOOQ`'#EW'#EWO-rQQO'#EVOOQ`'#EV'#EVOOQ`'#Dv'#DvQYQbOOO-zQbO'#DWO.VQbO'#DhO.zQQO'#DjO.VQbO'#DlO.VQbO'#DnO/PQbO'#DUOOQa'#E['#E[OOQ`'#Df'#DfOOQ`'#Ek'#EkOOQ`'#EO'#EOO/ZQbO,59cO0TQbO'#DPO0]QWO'#DQOOOO'#E_'#E_OOOO'#Dw'#DwO0qOSO,59iOOQa,59i,59iOOQ`'#Dx'#DxO1PQbO,5:OO1WQQO,59oOOQa,5:O,5:OO1cQbO,5:OO1mQbO,5:aO.VQbO,59hO.VQbO,59hO.VQbO,59hO.VQbO,5:PO.VQbO,5:PO.VQbO,5:PO2QQRO,59fO2XQRO,59fO2jQRO,59fO2eQQO,59fO2uQQO,59fO2}ObO,59dO3YQbO'#EPO3eQbO,59bO1mQbO,5:`OOQ`,5:q,5:qOOQ`-E7t-E7tOOQ`'#Dy'#DyO4SQbO'#DXO4_QbO'#DYOOQO'#Dz'#DzO4VQQO'#DXO4mQQO,59rO5^QRO,5:SO5eQRO,5:SO5pQbO,5:UO6WQcO,5:WO7YQcO,5:WO7jQcO,5:WO7tQRO,5:YO7{QRO,5:YOOQ`,59p,59pOOQ`-E7|-E7|OOOO,59k,59kOOOO,59l,59lOOOO-E7u-E7uOOQa1G/T1G/TOOQ`-E7v-E7vO8WQQO1G/ZOOQa1G/j1G/jO8cQbO1G/jOOQO'#D|'#D|O8WQQO1G/ZOOQa1G/Z1G/ZOOQ`'#D}'#D}O8cQbO1G/jOOQ`1G/{1G/{OOQa1G/S1G/SO9bQcO1G/SO9lQcO1G/SO9vQcO1G/SOOQa1G/k1G/kO;rQcO1G/kO;yQcO1G/kOWQQO7+$uOOQa7+$u7+$uO>cQbO7+%UOOQa7+%U7+%UOOQO-E7z-E7zOOQ`-E7{-E7{O>mQbO7+$xO>xQbO7+$xO?iQbO7+%YOOQ`'#D{'#D{O?nQQO'#D{O?sQbO'#EhOOQ`,59y,59yO@jQbO'#D]O@oQQO'#D`OOQ`7+%[7+%[O@tQbO7+%[O@yQbO7+%[OARQbO7+%`OOQa<OAN>OOBgQbOAN>OOBlQbOAN>OO5pQbO1G/cOOQ`1G/f1G/fOOQ`AN>bAN>bOOQ`-E8O-E8OOOQ`AN>fAN>fOBtQbOAN>fOByQRO,5:[OCQQRO,5:[O5pQbO,5:^OOQ`G23jG23jOC]QbOG23jOOQ`7+$}7+$}OOQ`G24QG24QO5pQbO1G/vOOQ`1G/x1G/xOOQ`LD)ULD)UOOQ`7+%b7+%b", - stateData: "Ce~O!wOS!xOS~OdPOe`OfUOg]OhfOmUOuUOvUO}UO!]gO!_hO!aiO!cjO!}[O#QQO#XRO#YSO#ZcO~OdlOfUOg]OhfOmUOuUOvUOykO}UO!VmO!}[O#QQO#XRO#YSO!ZoX#ZoX#`oX#^oX!QoX!ToX!UoX!eoX!goX~OP#OXQ#OXR#OXS#OXT#OXU#OXW#OXX#OXY#OXZ#OX[#OX]#OX^#OX~P!dOrsO#QvO#SqO#TrO~OdlOfUOg]OmUOuUOvUOykO}UO!}[O#QQO#XRO#YSO#ZwO~O#]zO~P%YOP#PXQ#PXR#PXS#PXT#PXU#PXW#PXX#PXY#PXZ#PX[#PX]#PX^#PX#Z#PX#`#PX!Q#PX!T#PX!U#PX!e#PX!g#PX~OdlOfUOg]OhfOmUOuUOvUOykO}UO!VmO!}[O#QQO#XRO#YSO#^#PX~P&[OV|O~P&[OP#OXQ#OXR#OXS#OXT#OXU#OXW#OXX#OXY#OXZ#OX[#OX]#OX^#OX~O#Z!zX#`!zX!Q!zX!T!zX!U!zX!e!zX!g!zX~P(vOP!OOQ!OOR!POS!POT!ROU!SOW!QOX!QOY!QOZ!QO[!QO]!QO^}O~O#Z!zX#`!zX!Q!zX!T!zX!U!zX!e!zX!g!zX~OP!OOQ!OOR!POS!PO~P+VOT!ROU!SO~P+VOdPOfUOg]OhfOmUOuUOvUO}UO!}[O#QQO#XRO#YSO~O!|!YO~O!Z!ZO~P+VOV|O_!]O`!]Oa!]Ob!]Oc!]O~O#Z!^O#`!^O~Od!`Oy!bO!O{P~OdlOfUOg]OmUOuUOvUO}UO!}[O#QQO#XRO#YSO~O!O!hO~OhfO!V!nO~P.VOhfOykO!VmO!Zka#Zka#`ka#^ka!Qka!Tka!Uka!eka!gka~P.VOd!pO!}[O~O#Q!qO#S!qO#T!qO#U!qO#V!qO#W!qO~OrsO#Q!sO#SqO#TrO~O#]!vO~P%YOykO#Z!xO#]!zO~O#Z!{O#]!vO~P.VOe`O!]gO!_hO!aiO!cjO~P,YO#^#WO~P(vOP!OOQ!OOR!POS!PO#^#WO~OT!ROU!SO#^#WO~O!Z!ZO#^#WO~Od#XOm#XO!}[O~Od#YOg]O!}[O~O!Z!ZO#Zja#`ja#^ja!Qja!Tja!Uja!eja!gja~Od!`Oy!bO!O{X~Om#aOu#aO}#aO#QQO~O!O#cO~OT!ROU!SOW!QOX!QOY!QOZ!QO[!QO]!QO~O!O#dO~P4rOT!ROU!SO!O#dO~Oe`O!]gO!_hO!aiO!cjO#Z#fO~P,YO#Z!`a#`!`a!Q!`a!T!`a!U!`a!e!`a!g!`a~P*[O#Z!`a#`!`a!Q!`a!T!`a!U!`a!e!`a!g!`a~OP!OOQ!OOR!POS!PO~P6qOT!ROU!SO~P6qO!O#hO~P4rOT!ROU!SO!O#hO~OykO#Z!xO#]#jO~O#Z!{O#]#lO~P.VO^}ORpiSpi#Zpi#`pi#^pi!Qpi!Tpi!Upi!epi!gpi~OPpiQpi~P8mOP!OOQ!OO~P8mOP!OOQ!OORpiSpi#Zpi#`pi#^pi!Qpi!Tpi!Upi!epi!gpi~OW!QOX!QOY!QOZ!QO[!QO]!QOT!Xi#Z!Xi#`!Xi#^!Xi!O!Xi!Q!Xi!T!Xi!U!Xi!e!Xi!g!Xi~OU!SO~P:nOU!SO~P;QOU!Xi~P:nOhfOykO!VmO~P.VOy!bO!O{a~Oe`O!]gO!_hO!aiO!cjO#Z#pO~P,YOe`O!]gO!_hO!aiO!cjO#Z#rO!Q#[P!T#[P!U#[P!e#[P!g#[P~P,YO!Q#vO!T#wO!U#xO~OykO#Z!xO#]#|O~O#Z!{O#]#}O~P.VO!Q#vO!T#wO!U$OO~Oe`O!]gO!_hO!aiO!cjO#Z#rO!Q#[P!T#[P!U#[P~P,YO!U$SO~O#Z$TO~Oe`O!]gO!_hO!aiO!cjO#Z#rO!Q#[X!T#[X!U#[X!e#[X!g#[X~P,YOd$VO~O!O$WO~O!U$XO~O!T#wO!U$XO~O!U$_O!e$]O!g$^O~O!U$aO~O!T#wO!U$aO~O!Q#vO!T#wO!U$aO~O!O$dO~O!U$fO~O!U$hO!e$]O!g$^O~O!O$lO~O!U$hO~O!U$mO~O!T#wO!U$mO~O!U$pO~O!O$qO~P4rOT!ROU!SO!O$qO~O!U$sO~Omv~", - goto: "3b#`PPPPPPPPPPPPPPPPPPPPPPPPPP#a#u$YP%X#u&^&{P'x'xPP'|(vP)Z)y)|PP*SP*]*rPPP+S,O,vP,}P,}P,}P,}P-`P-dP,},}-j-p-v-|.S.^.e.o.y/S/ZPPPP/a/e0QPP0i2RP3PPPPPPPPP3TPP3ZnaOe|!]!h#c#d#f#h#p#t$W$d$l$qR!W[s^O[e|!Z!]!h#c#d#f#h#p#t$W$d$l$qpPO[e|!]!h#c#d#f#h#p#t$W$d$l$q|lPSTgijkpx{}!O!P!Q!R!S!w!|#Y#Z#k$]R#Y!ZpTO[e|!]!h#c#d#f#h#p#t$W$d$l$q|UPSTgijkpx{}!O!P!Q!R!S!w!|#Y#Z#k$]Q!pqQ#X!YR#Z!ZnYOe|!]!h#c#d#f#h#p#t$W$d$l$qQ!U[Q!jiQ#O!OR#R!P!nUOPST[egijkpx{|}!O!P!Q!R!S!]!h!w!|#Y#Z#c#d#f#h#k#p#t$W$]$d$l$qR#a!bTsQu!oUOPST[egijkpx{|}!O!P!Q!R!S!]!h!w!|#Y#Z#c#d#f#h#k#p#t$W$]$d$l$qYnPTp#Y#ZQySQ!uxX!xy!u!y#inaOe|!]!h#c#d#f#h#p#t$W$d$l$qYmPTp#Y#ZQ!W[R!nkR!efX!cf!a!d#`Q#z#gQ$Q#oR$c$RQ#g!hQ#q#dQ#{#hQ$e$WQ$o$dQ$r$lR$t$qQ#y#gQ$P#oQ$Y#zS$b$Q$RR$n$c!OUPST[gijkpx{}!O!P!Q!R!S!w!|#Y#Z#k$]oVOe|!]!h#c#d#f#h#p#t$W$d$l$qnZOe|!]!h#c#d#f#h#p#t$W$d$l$qQ!V[Q!ggQ!kiQ!mjQ#S!SQ#U!RR$k$]ZnPTp#Y#ZoaOe|!]!h#c#d#f#h#p#t$W$d$l$qT$Z#{$[Q$`#{R$i$[QeOR!_eQuQR!ruQxSR!txQ!afR#_!aQ!dfQ#`!aT#b!d#`S#t#f#pR$U#tQ!yyQ#i!uT#m!y#iQ!|{Q#k!wT#n!|#kWpPT#Y#ZR!opS![_!XR#]![Q$[#{R$g$[TdOeSbOeQ!}|Q#^!]^#e!h#d#h$W$d$l$qQ#o#cV#s#f#p#tn_Oe|!]!h#c#d#f#h#p#t$W$d$l$qQ!X[R#[!ZpXO[e|!]!h#c#d#f#h#p#t$W$d$l$qYmPTp#Y#ZQ{SQ!fgQ!iiQ!ljQ!nkQ!wxW!{{!w!|#kQ#O}Q#P!OQ#Q!PQ#S!QQ#T!RQ#V!SR$j$]nWOe|!]!h#c#d#f#h#p#t$W$d$l$q|lPSTgijkpx{}!O!P!Q!R!S!w!|#Y#Z#k$]R!T[TtQuQ#u#fR$R#pZoPTp#Y#Z", - nodeNames: "⚠ Star Slash Plus Minus And Or Eq EqEq Neq Lt Lte Gt Gte Modulo PlusEq MinusEq StarEq SlashEq ModuloEq Identifier AssignableIdentifier Word IdentifierBeforeDot Do Program PipeExpr FunctionCall DotGet Number ParenExpr FunctionCallOrIdentifier BinOp String StringFragment Interpolation EscapeSeq Boolean Regex Dict NamedArg NamedArgPrefix FunctionDef Params NamedParam Null colon CatchExpr keyword Block FinallyExpr keyword keyword Underscore Array ConditionalOp PositionalArg operator WhileExpr keyword TryExpr keyword Throw keyword IfExpr keyword ElseIfExpr keyword ElseExpr keyword CompoundAssign Assign", - maxTerm: 108, + states: "7|QYQbOOO#zQcO'#C{O$wOSO'#C}OOQa'#DT'#DTO&QQbO'#DdO'fQcO'#E[OOQa'#E['#E[O(iQcO'#E[O)kQcO'#EZO*RQRO'#C|O+bQcO'#EVO+rQcO'#EVO+|QbO'#CzO,tOpO'#CxOOQ`'#EW'#EWO,yQbO'#EVO-QQRO'#DsOOQ`'#EV'#EVO-fQQO'#EUOOQ`'#EU'#EUOOQ`'#Du'#DuQYQbOOO-nQbO'#DWO-yQbO'#DhO.nQQO'#DjO-yQbO'#DlO-yQbO'#DnO.sQbO'#DUOOQa'#EZ'#EZOOQ`'#Df'#DfOOQ`'#Ej'#EjOOQ`'#D}'#D}O.}QbO,59cO/tQbO'#DPO/|QWO'#DQOOOO'#E^'#E^OOOO'#Dv'#DvO0bOSO,59iOOQa,59i,59iOOQ`'#Dw'#DwO0pQbO,5:OO0wQQO,59oOOQa,5:O,5:OO1SQbO,5:OO1^QbO,5:`O-yQbO,59hO-yQbO,59hO-yQbO,59hO-yQbO,5:PO-yQbO,5:PO-yQbO,5:PO1qQRO,59fO1xQRO,59fO2ZQRO,59fO2UQQO,59fO2fQQO,59fO2nObO,59dO2yQbO'#EOO3UQbO,59bO1^QbO,5:_OOQ`,5:p,5:pOOQ`-E7s-E7sOOQ`'#Dx'#DxO3pQbO'#DXO3{QbO'#DYOOQO'#Dy'#DyO3sQQO'#DXO4ZQQO,59rO4zQRO,5:SO5RQRO,5:SO5^QbO,5:UO5tQcO,5:WO6pQcO,5:WO7QQcO,5:WO7[QRO,5:YO7cQRO,5:YOOQ`,59p,59pOOQ`-E7{-E7{OOOO,59k,59kOOOO,59l,59lOOOO-E7t-E7tOOQa1G/T1G/TOOQ`-E7u-E7uO7nQQO1G/ZOOQa1G/j1G/jO7yQbO1G/jOOQO'#D{'#D{O7nQQO1G/ZOOQa1G/Z1G/ZOOQ`'#D|'#D|O7yQbO1G/jOOQ`1G/z1G/zOOQa1G/S1G/SO8uQcO1G/SO9PQcO1G/SO9ZQcO1G/SOOQa1G/k1G/kO;PQcO1G/kO;WQcO1G/kO;_QcO1G/kOOQa1G/Q1G/QOOQa1G/O1G/OO!dQbO'#C{O;fQbO'#CwOOQ`,5:j,5:jOOQ`-E7|-E7|OOQ`1G/y1G/yOOQ`-E7v-E7vO;sQQO,59sOOQO,59t,59tOOQO-E7w-E7wO;{QbO1G/^O5^QbO1G/nOOQ`'#D_'#D_OSQbO7+$xO>sQbO7+%YOOQ`'#Dz'#DzO>xQQO'#DzO>}QbO'#EgOOQ`,59y,59yO?qQbO'#D]O?vQQO'#D`OOQ`7+%[7+%[O?{QbO7+%[O@QQbO7+%[O@YQbO7+%`OOQa<OAN>OOAkQbOAN>OOApQbOAN>OO5^QbO1G/cOOQ`1G/f1G/fOOQ`AN>bAN>bOOQ`-E7}-E7}OOQ`AN>fAN>fOAxQbOAN>fO-yQbO,5:[O5^QbO,5:^OOQ`G23jG23jOA}QbOG23jOOQ`7+$}7+$}PAaQbO'#DpOOQ`G24QG24QOBSQRO1G/vOBZQRO1G/vOOQ`1G/x1G/xOOQ`LD)ULD)UO5^QbO7+%bOOQ`<q#c#f,Y#f#g?n#g#h,Y#h#i@k#i#o,Y#o#p#{#p#qBo#q;'S#{;'S;=`$d<%l~#{~O#{~~CYS$QUrSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{S$gP;=`<%l#{^$qUrS!wYOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U%[UrS#ZQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^%uZrS!xYOY%nYZ#{Zt%ntu&huw%nwx&hx#O%n#O#P&h#P;'S%n;'S;=`'P<%lO%nY&mS!xYOY&hZ;'S&h;'S;=`&y<%lO&hY&|P;=`<%l&h^'SP;=`<%l%n~'[O#S~~'aO#Q~U'hUrS!}QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(RUrS#^QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(jWrSOt#{uw#{x!Q#{!Q![)S![#O#{#P;'S#{;'S;=`$d<%lO#{U)ZYrSmQOt#{uw#{x!O#{!O!P)y!P!Q#{!Q![)S![#O#{#P;'S#{;'S;=`$d<%lO#{U*OWrSOt#{uw#{x!Q#{!Q![*h![#O#{#P;'S#{;'S;=`$d<%lO#{U*oWrSmQOt#{uw#{x!Q#{!Q![*h![#O#{#P;'S#{;'S;=`$d<%lO#{U+^^rSOt#{uw#{x}#{}!O,Y!O!Q#{!Q![)S![!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{U,_[rSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{U-[UyQrSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U-sWrSOt#{uw#{x!P#{!P!Q.]!Q#O#{#P;'S#{;'S;=`$d<%lO#{U.b^rSOY/^YZ#{Zt/^tu0auw/^wx0ax!P/^!P!Q#{!Q!}/^!}#O5S#O#P2o#P;'S/^;'S;=`6T<%lO/^U/e^rSvQOY/^YZ#{Zt/^tu0auw/^wx0ax!P/^!P!Q3U!Q!}/^!}#O5S#O#P2o#P;'S/^;'S;=`6T<%lO/^Q0fXvQOY0aZ!P0a!P!Q1R!Q!}0a!}#O1p#O#P2o#P;'S0a;'S;=`3O<%lO0aQ1UP!P!Q1XQ1^UvQ#Z#[1X#]#^1X#a#b1X#g#h1X#i#j1X#m#n1XQ1sVOY1pZ#O1p#O#P2Y#P#Q0a#Q;'S1p;'S;=`2i<%lO1pQ2]SOY1pZ;'S1p;'S;=`2i<%lO1pQ2lP;=`<%l1pQ2rSOY0aZ;'S0a;'S;=`3O<%lO0aQ3RP;=`<%l0aU3ZWrSOt#{uw#{x!P#{!P!Q3s!Q#O#{#P;'S#{;'S;=`$d<%lO#{U3zbrSvQOt#{uw#{x#O#{#P#Z#{#Z#[3s#[#]#{#]#^3s#^#a#{#a#b3s#b#g#{#g#h3s#h#i#{#i#j3s#j#m#{#m#n3s#n;'S#{;'S;=`$d<%lO#{U5X[rSOY5SYZ#{Zt5Stu1puw5Swx1px#O5S#O#P2Y#P#Q/^#Q;'S5S;'S;=`5}<%lO5SU6QP;=`<%l5SU6WP;=`<%l/^U6bUrS!OQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U6{W#YQrSOt#{uw#{x!_#{!_!`7e!`#O#{#P;'S#{;'S;=`$d<%lO#{U7jVrSOt#{uw#{x#O#{#P#Q8P#Q;'S#{;'S;=`$d<%lO#{U8WU#XQrSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~8oO#T~U8vU#]QrSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U9aUrS!VQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U9x]rSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#U:q#U#o,Y#o;'S#{;'S;=`$d<%lO#{U:v^rSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#`,Y#`#a;r#a#o,Y#o;'S#{;'S;=`$d<%lO#{U;w^rSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#g,Y#g#hx[#UWrSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{^?u[#WWrSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{^@r^#VWrSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#f,Y#f#gAn#g#o,Y#o;'S#{;'S;=`$d<%lO#{UAs^rSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#i,Y#i#jq#c#f,Y#f#g?n#g#h,Y#h#i@k#i#o,Y#o#p#{#p#qBo#q;'S#{;'S;=`$d<%l~#{~O#{~~CYS$QUrSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{S$gP;=`<%l#{^$qUrS!vYOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U%[UrS#YQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^%uZrS!wYOY%nYZ#{Zt%ntu&huw%nwx&hx#O%n#O#P&h#P;'S%n;'S;=`'P<%lO%nY&mS!wYOY&hZ;'S&h;'S;=`&y<%lO&hY&|P;=`<%l&h^'SP;=`<%l%n~'[O#R~~'aO#P~U'hUrS!|QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(RUrS#]QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(jWrSOt#{uw#{x!Q#{!Q![)S![#O#{#P;'S#{;'S;=`$d<%lO#{U)ZYrSmQOt#{uw#{x!O#{!O!P)y!P!Q#{!Q![)S![#O#{#P;'S#{;'S;=`$d<%lO#{U*OWrSOt#{uw#{x!Q#{!Q![*h![#O#{#P;'S#{;'S;=`$d<%lO#{U*oWrSmQOt#{uw#{x!Q#{!Q![*h![#O#{#P;'S#{;'S;=`$d<%lO#{U+^^rSOt#{uw#{x}#{}!O,Y!O!Q#{!Q![)S![!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{U,_[rSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{U-[UyQrSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U-sWrSOt#{uw#{x!P#{!P!Q.]!Q#O#{#P;'S#{;'S;=`$d<%lO#{U.b^rSOY/^YZ#{Zt/^tu0auw/^wx0ax!P/^!P!Q#{!Q!}/^!}#O5S#O#P2o#P;'S/^;'S;=`6T<%lO/^U/e^rSvQOY/^YZ#{Zt/^tu0auw/^wx0ax!P/^!P!Q3U!Q!}/^!}#O5S#O#P2o#P;'S/^;'S;=`6T<%lO/^Q0fXvQOY0aZ!P0a!P!Q1R!Q!}0a!}#O1p#O#P2o#P;'S0a;'S;=`3O<%lO0aQ1UP!P!Q1XQ1^UvQ#Z#[1X#]#^1X#a#b1X#g#h1X#i#j1X#m#n1XQ1sVOY1pZ#O1p#O#P2Y#P#Q0a#Q;'S1p;'S;=`2i<%lO1pQ2]SOY1pZ;'S1p;'S;=`2i<%lO1pQ2lP;=`<%l1pQ2rSOY0aZ;'S0a;'S;=`3O<%lO0aQ3RP;=`<%l0aU3ZWrSOt#{uw#{x!P#{!P!Q3s!Q#O#{#P;'S#{;'S;=`$d<%lO#{U3zbrSvQOt#{uw#{x#O#{#P#Z#{#Z#[3s#[#]#{#]#^3s#^#a#{#a#b3s#b#g#{#g#h3s#h#i#{#i#j3s#j#m#{#m#n3s#n;'S#{;'S;=`$d<%lO#{U5X[rSOY5SYZ#{Zt5Stu1puw5Swx1px#O5S#O#P2Y#P#Q/^#Q;'S5S;'S;=`5}<%lO5SU6QP;=`<%l5SU6WP;=`<%l/^U6bUrS!OQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U6{W#XQrSOt#{uw#{x!_#{!_!`7e!`#O#{#P;'S#{;'S;=`$d<%lO#{U7jVrSOt#{uw#{x#O#{#P#Q8P#Q;'S#{;'S;=`$d<%lO#{U8WU#WQrSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~8oO#S~U8vU#[QrSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U9aUrS!VQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U9x]rSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#U:q#U#o,Y#o;'S#{;'S;=`$d<%lO#{U:v^rSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#`,Y#`#a;r#a#o,Y#o;'S#{;'S;=`$d<%lO#{U;w^rSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#g,Y#g#hx[#TWrSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{^?u[#VWrSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{^@r^#UWrSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#f,Y#f#gAn#g#o,Y#o;'S#{;'S;=`$d<%lO#{UAs^rSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#i,Y#i#j (specializeKeyword(value, stack) << 1), external: specializeKeyword},{term: 20, get: (value: keyof typeof spec_Identifier) => spec_Identifier[value] || -1}], - tokenPrec: 1582 + tokenPrec: 1540 }) diff --git a/src/parser/tests/control-flow.test.ts b/src/parser/tests/control-flow.test.ts index 9319682..af0f704 100644 --- a/src/parser/tests/control-flow.test.ts +++ b/src/parser/tests/control-flow.test.ts @@ -2,7 +2,7 @@ import { expect, describe, test } from 'bun:test' import '../shrimp.grammar' // Importing this so changes cause it to retest! -describe('if/elseif/else', () => { +describe('if/else if/else', () => { test('parses single line if', () => { expect(`if y == 1: 'cool' end`).toMatchTree(` IfExpr @@ -74,21 +74,22 @@ describe('if/elseif/else', () => { `) }) - test('parses multiline if with elseif', () => { - expect(`if with-elseif: + test('parses multiline if with else if', () => { + expect(`if with-else-if: x - elseif another-condition: + else if another-condition: y end`).toMatchTree(` IfExpr keyword if - Identifier with-elseif + Identifier with-else-if colon : Block FunctionCallOrIdentifier Identifier x ElseIfExpr - keyword elseif + keyword else + keyword if Identifier another-condition colon : Block @@ -98,32 +99,34 @@ describe('if/elseif/else', () => { `) }) - test('parses multiline if with multiple elseif and else', () => { - expect(`if with-elseif-else: + test('parses multiline if with multiple else if and else', () => { + expect(`if with-else-if-else: x - elseif another-condition: + else if another-condition: y - elseif yet-another-condition: + else if yet-another-condition: z else: oh-no end`).toMatchTree(` IfExpr keyword if - Identifier with-elseif-else + Identifier with-else-if-else colon : Block FunctionCallOrIdentifier Identifier x ElseIfExpr - keyword elseif + keyword else + keyword if Identifier another-condition colon : Block FunctionCallOrIdentifier Identifier y ElseIfExpr - keyword elseif + keyword else + keyword if Identifier yet-another-condition colon : Block