diff --git a/src/parser/shrimp.grammar b/src/parser/shrimp.grammar index 352e2bb..64c44df 100644 --- a/src/parser/shrimp.grammar +++ b/src/parser/shrimp.grammar @@ -188,7 +188,7 @@ BinOp { } ParenExpr { - leftParen (ambiguousFunctionCall | BinOp | expressionWithoutIdentifier | ConditionalOp | PipeExpr | FunctionDef) rightParen + leftParen (IfExpr | ambiguousFunctionCall | BinOp | expressionWithoutIdentifier | ConditionalOp | PipeExpr | FunctionDef) rightParen } expression { diff --git a/src/parser/shrimp.terms.ts b/src/parser/shrimp.terms.ts index 05f3d5a..568b4af 100644 --- a/src/parser/shrimp.terms.ts +++ b/src/parser/shrimp.terms.ts @@ -30,36 +30,36 @@ export const DotGet = 28, Number = 29, ParenExpr = 30, - FunctionCallOrIdentifier = 31, - BinOp = 32, - String = 33, - StringFragment = 34, - Interpolation = 35, - EscapeSeq = 36, - Boolean = 37, - Regex = 38, - Dict = 39, - NamedArg = 40, - NamedArgPrefix = 41, - FunctionDef = 42, - Params = 43, - NamedParam = 44, - Null = 45, - colon = 46, - CatchExpr = 47, - keyword = 68, - Block = 49, - FinallyExpr = 50, - Underscore = 53, - Array = 54, - ConditionalOp = 55, - PositionalArg = 56, - WhileExpr = 58, - FunctionCallWithBlock = 60, - TryExpr = 61, - Throw = 63, - IfExpr = 65, - ElseIfExpr = 67, - ElseExpr = 69, + IfExpr = 31, + keyword = 69, + ConditionalOp = 33, + String = 34, + StringFragment = 35, + Interpolation = 36, + EscapeSeq = 37, + Boolean = 38, + Regex = 39, + Dict = 40, + NamedArg = 41, + NamedArgPrefix = 42, + FunctionDef = 43, + Params = 44, + NamedParam = 45, + Null = 46, + colon = 47, + CatchExpr = 48, + Block = 50, + FinallyExpr = 51, + Underscore = 54, + Array = 55, + ElseIfExpr = 56, + ElseExpr = 58, + FunctionCallOrIdentifier = 59, + BinOp = 60, + PositionalArg = 61, + WhileExpr = 63, + FunctionCallWithBlock = 65, + TryExpr = 66, + Throw = 68, CompoundAssign = 70, Assign = 71 diff --git a/src/parser/shrimp.ts b/src/parser/shrimp.ts index c6a98c1..4f09662 100644 --- a/src/parser/shrimp.ts +++ b/src/parser/shrimp.ts @@ -4,24 +4,24 @@ 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:124, throw:128, if:132, else:136} +const spec_Identifier = {__proto__:null,if:64, null:92, catch:98, finally:104, end:106, else:114, while:128, try:134, throw:138} export const parser = LRParser.deserialize({ version: 14, - states: "9[QYQbOOO#zQcO'#C{O$zOSO'#C}OOQa'#DT'#DTO&TQbO'#DdO'iQcO'#E]OOQa'#E]'#E]O(oQcO'#E]O)qQcO'#E[O*XQRO'#C|O+hQcO'#EWO+xQcO'#EWO,SQbO'#CzO,zOpO'#CxOOQ`'#EX'#EXO-PQbO'#EWO-ZQRO'#DtOOQ`'#EW'#EWO-oQQO'#EVOOQ`'#EV'#EVOOQ`'#Dv'#DvQYQbOOO-wQbO'#DWO.SQbO'#DhO.wQQO'#DkO.SQbO'#DmO.|QbO'#DoO/qQbO'#DUOOQa'#E['#E[OOQ`'#Df'#DfOOQ`'#Ek'#EkOOQ`'#EO'#EOO/{QbO,59cO0uQbO'#DPO0}QWO'#DQOOOO'#E_'#E_OOOO'#Dw'#DwO1cOSO,59iOOQa,59i,59iOOQ`'#Dx'#DxO1qQbO,5:OO1xQQO,59oOOQa,5:O,5:OO2TQbO,5:OO2_QbO,5:aO.SQbO,59hO.SQbO,59hO.SQbO,59hO.SQbO,5:PO.SQbO,5:PO.SQbO,5:PO2rQRO,59fO2yQRO,59fO3[QRO,59fO3VQQO,59fO3gQQO,59fO3oObO,59dO3zQbO'#EPO4VQbO,59bO4qQbO,5:UO2_QbO,5:`OOQ`,5:q,5:qOOQ`-E7t-E7tOOQ`'#Dy'#DyO5XQbO'#DXO5dQbO'#DYOOQO'#Dz'#DzO5[QQO'#DXO5rQQO,59rO6cQRO,5:SO6jQRO,5:SO4qQbO,5:VO6uQcO,5:XO7qQcO,5:XO8RQcO,5:XO8]QcO'#E[O8dQRO'#ElO8kQRO'#ElOOQO'#El'#ElO8vQQO,5:ZOOQ`,59p,59pOOQ`-E7|-E7|OOOO,59k,59kOOOO,59l,59lOOOO-E7u-E7uOOQa1G/T1G/TOOQ`-E7v-E7vO8{QQO1G/ZOOQa1G/j1G/jO9WQbO1G/jOOQO'#D|'#D|O8{QQO1G/ZOOQa1G/Z1G/ZOOQ`'#D}'#D}O9WQbO1G/jOOQ`1G/{1G/{OOQa1G/S1G/SO:SQcO1G/SO:^QcO1G/SO:hQcO1G/SOOQa1G/k1G/kO<^QcO1G/kOkQbO1G/pOOQ`1G/z1G/zOOQ`-E7w-E7wO>vQQO,59sOOQO,59t,59tOOQO-E7x-E7xO?OQbO1G/^O4qQbO1G/nO?fQbO1G/qO4qQbO1G/uO?qQQO7+$uOOQa7+$u7+$uO?|QbO7+%UOOQa7+%U7+%UOOQO-E7z-E7zOOQ`-E7{-E7{OOQ`'#D{'#D{O@WQQO'#D{O@]QbO'#EhOOQ`,59y,59yOAPQbO'#D]OAUQQO'#D`OOQ`7+%[7+%[OAZQbO7+%[OA`QbO7+%[OAhQbO7+$xOAsQbO7+$xOBdQbO7+%YOOQ`7+%]7+%]OBiQbO7+%]OBnQbO7+%]OBvQbO7+%aOOQa<bAN>bOOQ`AN>OAN>OOD^QbOAN>OODcQbOAN>OOOQ`AN>cAN>cOOQ`-E8O-E8OOOQ`AN>gAN>gODkQbOAN>gO.|QbO,5:]O4qQbO,5:_OOQ`7+$}7+$}OOQ`G23jG23jODpQbOG23jPDSQbO'#DqOOQ`G24RG24RODuQQO1G/wOOQ`1G/y1G/yOOQ`LD)ULD)UO4qQbO7+%cOOQ`<]QbO1G/uOOQ`1G/z1G/zOOQ`-E7w-E7wO>hQQO,59tOOQO,59u,59uOOQO-E7x-E7xO>pQbO1G/_O3vQbO1G/RO3vQbO1G/sO?TQbO1G/vO?`QQO7+$vOOQa7+$v7+$vO?kQbO7+%VOOQa7+%V7+%VOOQO-E7z-E7zOOQ`-E7{-E7{OOQ`'#D{'#D{O?uQQO'#D{O?zQbO'#EiOOQ`,59z,59zO@kQbO'#D^O@pQQO'#DaOOQ`7+%a7+%aO@uQbO7+%aO@zQbO7+%aOASQbO7+$yOA_QbO7+$yOA{QbO7+$mOBTQbO7+%_OOQ`7+%b7+%bOBYQbO7+%bOB_QbO7+%bOOQa<gAN>gOOQ`AN>PAN>POCuQbOAN>POCzQbOAN>POOQ`-E7|-E7|OOQ`AN=sAN=sODSQbOAN=sO-[QbO,5:QO3vQbO,5:SOOQ`AN>hAN>hOOQ`7+%O7+%OOOQ`G23kG23kODXQbOG23kPD^QbO'#DfOOQ`G23_G23_ODcQQO1G/lOOQ`1G/n1G/nOOQ`LD)VLD)VO3vQbO7+%WOOQ`<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$QUsSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{S$gP;=`<%l#{^$qUsS!wYOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U%[UsS#[QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^%uZsS!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#T~~'aO#R~U'hUsS!}QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(RUsS#_QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(jWsSOt#{uw#{x!Q#{!Q![)S![#O#{#P;'S#{;'S;=`$d<%lO#{U)ZYsSmQOt#{uw#{x!O#{!O!P)y!P!Q#{!Q![)S![#O#{#P;'S#{;'S;=`$d<%lO#{U*OWsSOt#{uw#{x!Q#{!Q![*h![#O#{#P;'S#{;'S;=`$d<%lO#{U*oWsSmQOt#{uw#{x!Q#{!Q![*h![#O#{#P;'S#{;'S;=`$d<%lO#{U+^^sSOt#{uw#{x}#{}!O,Y!O!Q#{!Q![)S![!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{U,_[sSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{U-[UzQsSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U-sWsSOt#{uw#{x!P#{!P!Q.]!Q#O#{#P;'S#{;'S;=`$d<%lO#{U.b^sSOY/^YZ#{Zt/^tu0auw/^wx0ax!P/^!P!Q#{!Q!}/^!}#O5S#O#P2o#P;'S/^;'S;=`6T<%lO/^U/e^sSwQOY/^YZ#{Zt/^tu0auw/^wx0ax!P/^!P!Q3U!Q!}/^!}#O5S#O#P2o#P;'S/^;'S;=`6T<%lO/^Q0fXwQOY0aZ!P0a!P!Q1R!Q!}0a!}#O1p#O#P2o#P;'S0a;'S;=`3O<%lO0aQ1UP!P!Q1XQ1^UwQ#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;=`<%l0aU3ZWsSOt#{uw#{x!P#{!P!Q3s!Q#O#{#P;'S#{;'S;=`$d<%lO#{U3zbsSwQOt#{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[sSOY5SYZ#{Zt5Stu1puw5Swx1px#O5S#O#P2Y#P#Q/^#Q;'S5S;'S;=`5}<%lO5SU6QP;=`<%l5SU6WP;=`<%l/^U6bUsS!PQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U6{W#ZQsSOt#{uw#{x!_#{!_!`7e!`#O#{#P;'S#{;'S;=`$d<%lO#{U7jVsSOt#{uw#{x#O#{#P#Q8P#Q;'S#{;'S;=`$d<%lO#{U8WU#YQsSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~8oO#U~U8vU#^QsSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U9aUsS!WQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U9x]sSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#U:q#U#o,Y#o;'S#{;'S;=`$d<%lO#{U:v^sSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#`,Y#`#a;r#a#o,Y#o;'S#{;'S;=`$d<%lO#{U;w^sSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#g,Y#g#hx[#VWsSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{^?u[#XWsSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{^@r^#WWsSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#f,Y#f#gAn#g#o,Y#o;'S#{;'S;=`$d<%lO#{UAs^sSOt#{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: 1652 + tokenPrec: 1634 }) diff --git a/src/parser/tests/control-flow.test.ts b/src/parser/tests/control-flow.test.ts index fa24a64..1bacc31 100644 --- a/src/parser/tests/control-flow.test.ts +++ b/src/parser/tests/control-flow.test.ts @@ -237,6 +237,22 @@ describe('if/else if/else', () => { keyword end `) }) + + test('allows if/else in parens', () => { + expect(`eh? = (if true: true end)`).toMatchTree(` + Assign + AssignableIdentifier eh? + Eq = + ParenExpr + IfExpr + keyword if + Boolean true + colon : + Block + Boolean true + keyword end + `) + }) }) describe('while', () => {