{ curly strings }

This commit is contained in:
Chris Wanstrath 2025-11-06 10:40:09 -08:00
parent a156d24a91
commit 503ca41155
6 changed files with 98 additions and 10 deletions

View File

@ -193,3 +193,29 @@ describe('dict literals', () => {
c=3]`).toEvaluateTo({ a: 1, b: 2, c: 3 }) c=3]`).toEvaluateTo({ a: 1, b: 2, c: 3 })
}) })
}) })
describe('curly strings', () => {
test('work on one line', () => {
expect('{ one two three }').toEvaluateTo(" one two three ")
})
test('work on multiple lines', () => {
expect(`{
one
two
three
}`).toEvaluateTo("\n one\n two\n three\n ")
})
test('can contain other curlies', () => {
expect(`{
{ one }
two
{ three }
}`).toEvaluateTo("\n { one }\n two\n { three }\n ")
})
test("don't interpolate", () => {
expect(`{ sum is $(a + b)! }`).toEvaluateTo(` sum is $(a + b)! `)
})
})

View File

@ -41,7 +41,7 @@ finally { @specialize[@name=keyword]<Identifier, "finally"> }
throw { @specialize[@name=keyword]<Identifier, "throw"> } throw { @specialize[@name=keyword]<Identifier, "throw"> }
null { @specialize[@name=Null]<Identifier, "null"> } null { @specialize[@name=Null]<Identifier, "null"> }
@external tokens tokenizer from "./tokenizer" { Identifier, AssignableIdentifier, Word, IdentifierBeforeDot } @external tokens tokenizer from "./tokenizer" { Identifier, AssignableIdentifier, Word, IdentifierBeforeDot, curlyString }
@external specialize {Identifier} specializeKeyword from "./tokenizer" { Do } @external specialize {Identifier} specializeKeyword from "./tokenizer" { Do }
@precedence { @precedence {
@ -233,7 +233,9 @@ expression {
IdentifierBeforeDot dot (Number | Identifier | ParenExpr) IdentifierBeforeDot dot (Number | Identifier | ParenExpr)
} }
String { "'" stringContent* "'" } String {
"'" stringContent* "'" | curlyString
}
} }
stringContent { stringContent {

View File

@ -31,6 +31,7 @@ export const
AssignableIdentifier = 29, AssignableIdentifier = 29,
Word = 30, Word = 30,
IdentifierBeforeDot = 31, IdentifierBeforeDot = 31,
curlyString = 95,
Do = 32, Do = 32,
Comment = 33, Comment = 33,
Program = 34, Program = 34,

View File

@ -7,11 +7,11 @@ import {highlighting} from "./highlight"
const spec_Identifier = {__proto__:null,while:76, null:108, catch:114, finally:120, end:122, if:130, else:136, try:154, throw:158} const spec_Identifier = {__proto__:null,while:76, null:108, catch:114, finally:120, end:122, if:130, else:136, try:154, throw:158}
export const parser = LRParser.deserialize({ export const parser = LRParser.deserialize({
version: 14, version: 14,
states: "<tQYQbOOO!dOpO'#DWO!iOSO'#D_O%^QcO'#DtO(WQcO'#EdOOQ`'#Er'#ErO(qQRO'#DuO*vQcO'#EbO+aQbO'#DUOOQa'#Dw'#DwO-fQbO'#DxOOQa'#Ed'#EdO-mQcO'#EdO/kQcO'#EcO0pQcO'#EbO0}QRO'#EOOOQ`'#Eb'#EbO1fQbO'#EbO1mQQO'#EaOOQ`'#Ea'#EaOOQ`'#EQ'#EQQYQbOOO1xQbO'#DZO2TQbO'#DnO2xQbO'#DRO3mQQO'#DzO2xQbO'#D|O3rObO,59rO3}QbO'#DaO4VQWO'#DbOOOO'#Ej'#EjOOOO'#EV'#EVO4kOSO,59yOOQa,59y,59yOOQ`'#DY'#DYO4yQbO'#DmOOQ`'#Eh'#EhOOQ`'#EY'#EYO5TQbO,5:[OOQa'#Ec'#EcO2xQbO,5:aO2xQbO,5:aO2xQbO,5:aO2xQbO,5:aO2xQbO,59oO2xQbO,59oO2xQbO,59oO2xQbO,59oOOQ`'#ES'#ESO+aQbO,59pO5}QcO'#DtO6UQcO'#EdO6]QRO,59pO6gQQO,59pO6lQQO,59pO6tQQO,59pO7PQRO,59pO7iQRO,59pO7pQQO'#DPO7uQbO,5:dO7|QQO,5:cOOQa,5:d,5:dO8XQbO,5:dO8cQbO,5:kO8cQbO,5:jO9jQbO,5:eO9qQbO,59kOOQ`,5:{,5:{O8cQbO'#EROOQ`-E8O-E8OOOQ`'#ET'#ETO:]QbO'#D[O:hQbO'#D]OOQO'#EU'#EUO:`QQO'#D[O:vQQO,59uO:{QcO'#EcO;xQRO'#EqO<uQRO'#EqOOQO'#Eq'#EqO<|QQO,5:YO=RQRO,59mO=YQRO,59mO9jQbO,5:fO=hQcO,5:hO>vQcO,5:hO?dQcO,5:hOOQa1G/^1G/^OOOO,59{,59{OOOO,59|,59|OOOO-E8T-E8TOOQa1G/e1G/eOOQ`,5:X,5:XOOQ`-E8W-E8WOOQa1G/{1G/{OA`QcO1G/{OAjQcO1G/{OBxQcO1G/{OCSQcO1G/{OCaQcO1G/{OOQa1G/Z1G/ZODrQcO1G/ZODyQcO1G/ZOEQQcO1G/ZOFPQcO1G/ZOEXQcO1G/ZOOQ`-E8Q-E8QOFgQRO1G/[OFqQQO1G/[OFvQQO1G/[OGOQQO1G/[OGZQRO1G/[OGbQRO1G/[OGiQbO,59qOGsQQO1G/[OOQa1G/[1G/[OG{QQO1G/}OOQa1G0O1G0OOHWQbO1G0OOOQO'#E['#E[OG{QQO1G/}OOQa1G/}1G/}OOQ`'#E]'#E]OHWQbO1G0OOHbQbO1G0VOH|QbO1G0UOIhQbO'#DhOIyQbO'#DhOJ^QbO1G0POOQ`-E8P-E8POOQ`,5:m,5:mOOQ`-E8R-E8ROJiQQO,59vOOQO,59w,59wOOQO-E8S-E8SOJqQbO1G/aO9jQbO1G/tO9jQbO1G/XOJxQbO1G0QOKTQQO7+$vOOQa7+$v7+$vOK]QQO1G/]OKeQQO7+%iOOQa7+%i7+%iOKpQbO7+%jOOQa7+%j7+%jOOQO-E8Y-E8YOOQ`-E8Z-E8ZOOQ`'#EW'#EWOKzQQO'#EWOLSQbO'#EpOOQ`,5:S,5:SOLgQbO'#DfOLlQQO'#DiOOQ`7+%k7+%kOLqQbO7+%kOLvQbO7+%kOMOQbO7+${OM^QbO7+${OMnQbO7+%`OMvQbO7+$sOOQ`7+%l7+%lOM{QbO7+%lONQQbO7+%lOOQa<<Hb<<HbONYQbO7+$wONgQQO7+$wOOQa<<IT<<ITOOQa<<IU<<IUOOQ`,5:r,5:rOOQ`-E8U-E8UONoQQO,5:QO9jQbO,5:TOOQ`<<IV<<IVONtQbO<<IVOOQ`<<Hg<<HgONyQbO<<HgO! OQbO<<HgO! WQbO<<HgOOQ`'#EZ'#EZO! cQbO<<HzO! kQbO'#DsOOQ`<<Hz<<HzO! sQbO<<HzOOQ`<<H_<<H_OOQ`<<IW<<IWO! xQbO<<IWOOQO,5:s,5:sO! }QbO<<HcOOQO-E8V-E8VO9jQbO1G/lOOQ`1G/o1G/oOOQ`AN>qAN>qOOQ`AN>RAN>RO!![QbOAN>RO!!aQbOAN>ROOQ`-E8X-E8XOOQ`AN>fAN>fO!!iQbOAN>fO2TQbO,5:]O9jQbO,5:_OOQ`AN>rAN>rPGiQbO'#ESOOQ`7+%W7+%WOOQ`G23mG23mO!!nQbOG23mP! nQbO'#DqOOQ`G24QG24QO!!sQQO1G/wOOQ`1G/y1G/yOOQ`LD)XLD)XO9jQbO7+%cOOQ`<<H}<<H}", states: "<zQYQbOOO!gOpO'#DWO!lOSO'#D_OOQa'#D_'#D_O%dQcO'#DtO(aQcO'#EeOOQ`'#Es'#EsO(zQRO'#DuO+PQcO'#EcO+jQbO'#DUOOQa'#Dw'#DwO-uQbO'#DxOOQa'#Ee'#EeO-|QcO'#EeO/zQcO'#EdO1PQcO'#EcO1^QRO'#EOOOQ`'#Ec'#EcO1uQbO'#EcO1|QQO'#EbOOQ`'#Eb'#EbOOQ`'#EQ'#EQQYQbOOO2XQbO'#DZO2dQbO'#DnO3[QbO'#DRO4SQQO'#DzO3[QbO'#D|O4XObO,59rO4dQbO'#DaO4lQWO'#DbOOOO'#Ek'#EkOOOO'#EV'#EVO5QOSO,59yOOQa,59y,59yOOQ`'#DY'#DYO5`QbO'#DmOOQ`'#Ei'#EiOOQ`'#EY'#EYO5jQbO,5:[OOQa'#Ed'#EdO3[QbO,5:aO3[QbO,5:aO3[QbO,5:aO3[QbO,5:aO3[QbO,59oO3[QbO,59oO3[QbO,59oO3[QbO,59oOOQ`'#ES'#ESO+jQbO,59pO6dQcO'#DtO6kQcO'#EeO6rQRO,59pO6|QQO,59pO7RQQO,59pO7ZQQO,59pO7fQRO,59pO8OQRO,59pO8VQQO'#DPO8[QbO,5:dO8cQQO,5:cOOQa,5:d,5:dO8nQbO,5:dO8xQbO,5:kO8xQbO,5:jO:SQbO,5:eO:ZQbO,59kOOQ`,5:|,5:|O8xQbO'#EROOQ`-E8O-E8OOOQ`'#ET'#ETO:uQbO'#D[O;QQbO'#D]OOQO'#EU'#EUO:xQQO'#D[O;cQQO,59uO;hQcO'#EdO<eQRO'#ErO=bQRO'#ErOOQO'#Er'#ErO=iQQO,5:YO=nQRO,59mO=uQRO,59mO:SQbO,5:fO>TQcO,5:hO?cQcO,5:hO@PQcO,5:hOOQa1G/^1G/^OOOO,59{,59{OOOO,59|,59|OOOO-E8T-E8TOOQa1G/e1G/eOOQ`,5:X,5:XOOQ`-E8W-E8WOOQa1G/{1G/{OA{QcO1G/{OBVQcO1G/{OCeQcO1G/{OCoQcO1G/{OC|QcO1G/{OOQa1G/Z1G/ZOE_QcO1G/ZOEfQcO1G/ZOEmQcO1G/ZOFlQcO1G/ZOEtQcO1G/ZOOQ`-E8Q-E8QOGSQRO1G/[OG^QQO1G/[OGcQQO1G/[OGkQQO1G/[OGvQRO1G/[OG}QRO1G/[OHUQbO,59qOH`QQO1G/[OOQa1G/[1G/[OHhQQO1G/}OOQa1G0O1G0OOHsQbO1G0OOOQO'#E['#E[OHhQQO1G/}OOQa1G/}1G/}OOQ`'#E]'#E]OHsQbO1G0OOH}QbO1G0VOIiQbO1G0UOJTQbO'#DhOJfQbO'#DhOJyQbO1G0POOQ`-E8P-E8POOQ`,5:m,5:mOOQ`-E8R-E8ROKUQQO,59vOOQO,59w,59wOOQO-E8S-E8SOK^QbO1G/aO:SQbO1G/tO:SQbO1G/XOKeQbO1G0QOKpQQO7+$vOOQa7+$v7+$vOKxQQO1G/]OLQQQO7+%iOOQa7+%i7+%iOL]QbO7+%jOOQa7+%j7+%jOOQO-E8Y-E8YOOQ`-E8Z-E8ZOOQ`'#EW'#EWOLgQQO'#EWOLoQbO'#EqOOQ`,5:S,5:SOMSQbO'#DfOMXQQO'#DiOOQ`7+%k7+%kOM^QbO7+%kOMcQbO7+%kOMkQbO7+${OMyQbO7+${ONZQbO7+%`ONcQbO7+$sOOQ`7+%l7+%lONhQbO7+%lONmQbO7+%lOOQa<<Hb<<HbONuQbO7+$wO! SQQO7+$wOOQa<<IT<<ITOOQa<<IU<<IUOOQ`,5:r,5:rOOQ`-E8U-E8UO! [QQO,5:QO:SQbO,5:TOOQ`<<IV<<IVO! aQbO<<IVOOQ`<<Hg<<HgO! fQbO<<HgO! kQbO<<HgO! sQbO<<HgOOQ`'#EZ'#EZO!!OQbO<<HzO!!WQbO'#DsOOQ`<<Hz<<HzO!!`QbO<<HzOOQ`<<H_<<H_OOQ`<<IW<<IWO!!eQbO<<IWOOQO,5:s,5:sO!!jQbO<<HcOOQO-E8V-E8VO:SQbO1G/lOOQ`1G/o1G/oOOQ`AN>qAN>qOOQ`AN>RAN>RO!!wQbOAN>RO!!|QbOAN>ROOQ`-E8X-E8XOOQ`AN>fAN>fO!#UQbOAN>fO2dQbO,5:]O:SQbO,5:_OOQ`AN>rAN>rPHUQbO'#ESOOQ`7+%W7+%WOOQ`G23mG23mO!#ZQbOG23mP!!ZQbO'#DqOOQ`G24QG24QO!#`QQO1G/wOOQ`1G/y1G/yOOQ`LD)XLD)XO:SQbO7+%cOOQ`<<H}<<H}",
stateData: "!!{~O#SOSqOS~OlROm_OnZOoPOpfOvhO{ZO!VZO!WZO!cgO!jZO!oiO!qjO#XWO#YcO#]QO#hXO#iYO~O#ZkO~O!SnO#]qO#_lO#`mO~OlwOnZOoPOpfO{ZO!QsO!VZO!WZO!`rO!jZO#XWO#]QO#hXO#iYOP#VXQ#VXR#VXS#VXT#VXU#VXW#VXX#VXY#VXZ#VX[#VX]#VX^#VXd#VXe#VXf#VXg#VXh#VXi#VXj#VXt!hX!X!hX#g!hX~O#Y!hX#k!hX!Z!hX!^!hX!_!hX!f!hX~P!wOlwOnZOoPOpfO{ZO!QsO!VZO!WZO!`rO!jZO#XWO#]QO#hXO#iYOP#WXQ#WXR#WXS#WXT#WXU#WXW#WXX#WXY#WXZ#WX[#WX]#WX^#WXd#WXe#WXf#WXg#WXh#WXi#WXj#WXt#WX#g#WX~O#Y#WX#k#WX!X#WX!Z#WX!^#WX!_#WX!f#WX~P%tOPyOQyORzOSzOT}OU!OOW|OX|OY|OZ|O[|O]|O^xOd{Oe{Of{Og{Oh{Oi{Oj!PO~OPyOQyORzOSzOd{Oe{Of{Og{Oh{Oi{Ot#UX~O#Y#UX#k#UX!Z#UX!^#UX!_#UX#g#UX!f#UX~P*ROl!SOm_OnZOoPOpfOvhO{ZO!VZO!WZO!cgO!jZO!oiO!qjO#XWO#Y!QO#]QO#hXO#iYO~OlwOnZOoPO{ZO!QsO!VZO!WZO!jZO#XWO#Y!QO#]QO#hXO#iYO~O#j!_O~P,kOV!aO#Y#WX#k#WX!Z#WX!^#WX!_#WX!f#WX~P&pOP#VXQ#VXR#VXS#VXT#VXU#VXW#VXX#VXY#VXZ#VX[#VX]#VX^#VXd#VXe#VXf#VXg#VXh#VXi#VXj#VXt#UX~O#Y#UX#k#UX!Z#UX!^#UX!_#UX#g#UX!f#UX~P.WOt#UX#Y#UX#k#UX!Z#UX!^#UX!_#UX#g#UX!f#UX~OT}OU!OOj!PO~P0UOV!aO_!bO`!bOa!bOb!bOc!bOk!bO~O!X!cO~P0UOt!fO#Y!eO#k!eO~Ol!hO!Q!jO!X!OP~Ol!nOnZOoPO{ZO!VZO!WZO!jZO#XWO#]QO#hXO#iYO~OlwOnZOoPO{ZO!VZO!WZO!jZO#XWO#]QO#hXO#iYO~O!X!uO~Ol!yO{!yO#XWO~Ol!zO#XWO~O#]!{O#_!{O#`!{O#a!{O#b!{O#c!{O~O!SnO#]!}O#_lO#`mO~OpfO!`#OO~P2xOpfO!QsO!`rOt!da!X!da#Y!da#k!da#g!da!Z!da!^!da!_!da!f!da~P2xO#Y!QO~P!wO#Y!QO~P%tO#Y!QO#g#gO~P*RO#g#gO~O#g#gOt#UX~O!X!cO#g#gOt#UX~O#g#gO~P.WOT}OU!OOj!PO#Y!QOt#UX~O#g#gO~P7WOt!fO~O#j#iO~P,kO!QsO#Y#kO#j#mO~O#Y#nO#j#iO~P2xOlROm_OnZOoPOpfOvhO{ZO!VZO!WZO!cgO!jZO!oiO!qjO#XWO#]QO#hXO#iYO~O#Y#sO~P8cOt!fO#Ysa#ksa#gsa!Zsa!^sa!_sa!fsa~Ol!hO!Q!jO!X!OX~O{#yO!V#yO!W#yO#]QO~O!X#{O~OpfO!QsO!`rOT#VXU#VXW#VXX#VXY#VXZ#VX[#VX]#VXj#VX!X#VX~P2xOT}OU!OOj!PO!X#eX~OT}OU!OOW|OX|OY|OZ|O[|O]|Oj!PO~O!X#eX~P<WO!X#|O~O!X#}O~P<WOT}OU!OOj!PO!X#}O~Ot!pa#Y!pa#k!pa!Z!pa!^!pa!_!pa#g!pa!f!pa~P(qOPyOQyORzOSzOd{Oe{Of{Og{Oh{Oi{O~Ot!pa#Y!pa#k!pa!Z!pa!^!pa!_!pa#g!pa!f!pa~P>UOT}OU!OOj!POt!pa#Y!pa#k!pa!Z!pa!^!pa!_!pa#g!pa!f!pa~O^xOR!iiS!iid!iie!iif!iig!iih!iii!iit!ii#Y!ii#k!ii#g!ii!Z!ii!^!ii!_!ii!f!ii~OP!iiQ!ii~P@XOPyOQyO~P@XOPyOQyOd!iie!iif!iig!iih!iii!iit!ii#Y!ii#k!ii#g!ii!Z!ii!^!ii!_!ii!f!ii~OR!iiS!ii~PAtORzOSzO^xO~PAtORzOSzO~PAtOW|OX|OY|OZ|O[|O]|OTwijwitwi#Ywi#kwi#gwi!Xwi!Zwi!^wi!_wi!fwi~OU!OO~PCkOU!OO~PC}OUwi~PCkOT}OU!OOjwitwi#Ywi#kwi#gwi!Xwi!Zwi!^wi!_wi!fwi~OW|OX|OY|OZ|O[|O]|O~PEXO#Y!QO#g$QO~P*RO#g$QO~O#g$QOt#UX~O!X!cO#g$QOt#UX~O#g$QO~P.WO#g$QO~P7WOpfO!`rO~P,kO#Y!QO#g$QO~O!QsO#Y#kO#j$TO~O#Y#nO#j$VO~P2xOt!fO#Y!si#k!si!Z!si!^!si!_!si#g!si!f!si~Ot!fO#Y!ri#k!ri!Z!ri!^!ri!_!ri#g!ri!f!ri~Ot!fO!Z![X!^![X!_![X!f![X~O#Y$YO!Z#dP!^#dP!_#dP!f#dP~P8cO!Z$^O!^$_O!_$`O~O!Q!jO!X!Oa~O#Y$dO~P8cO!Z$^O!^$_O!_$gO~O#Y!QO#g$jO~O#Y!QO#gyi~O!QsO#Y#kO#j$mO~O#Y#nO#j$nO~P2xOt!fO#Y$oO~O#Y$YO!Z#dX!^#dX!_#dX!f#dX~P8cOl$qO~O!X$rO~O!_$sO~O!^$_O!_$sO~Ot!fO!Z$^O!^$_O!_$uO~O#Y$YO!Z#dP!^#dP!_#dP~P8cO!_$|O!f${O~O!_%OO~O!_%PO~O!^$_O!_%PO~OpfO!`rO#gyq~P,kO#Y!QO#gyq~O!X%UO~O!_%WO~O!_%XO~O!^$_O!_%XO~O!Z$^O!^$_O!_%XO~O!_%]O!f${O~O!X%`O!c%_O~O!_%]O~O!_%aO~OpfO!`rO#gyy~P,kO!_%dO~O!^$_O!_%dO~O!_%gO~O!_%jO~O!X%kO~O{!j~", stateData: "!#h~O#TOSqOS~OlSOm`On[OoPOpgOviO{[O!V[O!W[O!chO!j[O!ojO!qkO#RRO#YXO#ZdO#^QO#iYO#jZO~O#[lO~O!SoO#^rO#`mO#anO~OlxOn[OoPOpgO{[O!QtO!V[O!W[O!`sO!j[O#RRO#YXO#^QO#iYO#jZOP#WXQ#WXR#WXS#WXT#WXU#WXW#WXX#WXY#WXZ#WX[#WX]#WX^#WXd#WXe#WXf#WXg#WXh#WXi#WXj#WXt!hX!X!hX#h!hX~O#Z!hX#l!hX!Z!hX!^!hX!_!hX!f!hX~P!zOlxOn[OoPOpgO{[O!QtO!V[O!W[O!`sO!j[O#RRO#YXO#^QO#iYO#jZOP#XXQ#XXR#XXS#XXT#XXU#XXW#XXX#XXY#XXZ#XX[#XX]#XX^#XXd#XXe#XXf#XXg#XXh#XXi#XXj#XXt#XX#h#XX~O#Z#XX#l#XX!X#XX!Z#XX!^#XX!_#XX!f#XX~P%zOPzOQzOR{OS{OT!OOU!POW}OX}OY}OZ}O[}O]}O^yOd|Oe|Of|Og|Oh|Oi|Oj!QO~OPzOQzOR{OS{Od|Oe|Of|Og|Oh|Oi|Ot#VX~O#Z#VX#l#VX!Z#VX!^#VX!_#VX#h#VX!f#VX~P*[Ol!TOm`On[OoPOpgOviO{[O!V[O!W[O!chO!j[O!ojO!qkO#RRO#YXO#Z!RO#^QO#iYO#jZO~OlxOn[OoPO{[O!QtO!V[O!W[O!j[O#RRO#YXO#Z!RO#^QO#iYO#jZO~O#k!`O~P,wOV!bO#Z#XX#l#XX!Z#XX!^#XX!_#XX!f#XX~P&yOP#WXQ#WXR#WXS#WXT#WXU#WXW#WXX#WXY#WXZ#WX[#WX]#WX^#WXd#WXe#WXf#WXg#WXh#WXi#WXj#WXt#VX~O#Z#VX#l#VX!Z#VX!^#VX!_#VX#h#VX!f#VX~P.gOt#VX#Z#VX#l#VX!Z#VX!^#VX!_#VX#h#VX!f#VX~OT!OOU!POj!QO~P0eOV!bO_!cO`!cOa!cOb!cOc!cOk!cO~O!X!dO~P0eOt!gO#Z!fO#l!fO~Ol!iO!Q!kO!X!OP~Ol!oOn[OoPO{[O!V[O!W[O!j[O#RRO#YXO#^QO#iYO#jZO~OlxOn[OoPO{[O!V[O!W[O!j[O#RRO#YXO#^QO#iYO#jZO~O!X!vO~Ol!zO{!zO#YXO~Ol!{O#YXO~O#^!|O#`!|O#a!|O#b!|O#c!|O#d!|O~O!SoO#^#OO#`mO#anO~OpgO!`#PO~P3[OpgO!QtO!`sOt!da!X!da#Z!da#l!da#h!da!Z!da!^!da!_!da!f!da~P3[O#Z!RO~P!zO#Z!RO~P%zO#Z!RO#h#hO~P*[O#h#hO~O#h#hOt#VX~O!X!dO#h#hOt#VX~O#h#hO~P.gOT!OOU!POj!QO#Z!ROt#VX~O#h#hO~P7mOt!gO~O#k#jO~P,wO!QtO#Z#lO#k#nO~O#Z#oO#k#jO~P3[OlSOm`On[OoPOpgOviO{[O!V[O!W[O!chO!j[O!ojO!qkO#RRO#YXO#^QO#iYO#jZO~O#Z#tO~P8xOt!gO#Zsa#lsa#hsa!Zsa!^sa!_sa!fsa~Ol!iO!Q!kO!X!OX~O{#zO!V#zO!W#zO#RRO#^QO~O!X#|O~OpgO!QtO!`sOT#WXU#WXW#WXX#WXY#WXZ#WX[#WX]#WXj#WX!X#WX~P3[OT!OOU!POj!QO!X#fX~OT!OOU!POW}OX}OY}OZ}O[}O]}Oj!QO~O!X#fX~P<sO!X#}O~O!X$OO~P<sOT!OOU!POj!QO!X$OO~Ot!pa#Z!pa#l!pa!Z!pa!^!pa!_!pa#h!pa!f!pa~P(zOPzOQzOR{OS{Od|Oe|Of|Og|Oh|Oi|O~Ot!pa#Z!pa#l!pa!Z!pa!^!pa!_!pa#h!pa!f!pa~P>qOT!OOU!POj!QOt!pa#Z!pa#l!pa!Z!pa!^!pa!_!pa#h!pa!f!pa~O^yOR!iiS!iid!iie!iif!iig!iih!iii!iit!ii#Z!ii#l!ii#h!ii!Z!ii!^!ii!_!ii!f!ii~OP!iiQ!ii~P@tOPzOQzO~P@tOPzOQzOd!iie!iif!iig!iih!iii!iit!ii#Z!ii#l!ii#h!ii!Z!ii!^!ii!_!ii!f!ii~OR!iiS!ii~PBaOR{OS{O^yO~PBaOR{OS{O~PBaOW}OX}OY}OZ}O[}O]}OTwijwitwi#Zwi#lwi#hwi!Xwi!Zwi!^wi!_wi!fwi~OU!PO~PDWOU!PO~PDjOUwi~PDWOT!OOU!POjwitwi#Zwi#lwi#hwi!Xwi!Zwi!^wi!_wi!fwi~OW}OX}OY}OZ}O[}O]}O~PEtO#Z!RO#h$RO~P*[O#h$RO~O#h$ROt#VX~O!X!dO#h$ROt#VX~O#h$RO~P.gO#h$RO~P7mOpgO!`sO~P,wO#Z!RO#h$RO~O!QtO#Z#lO#k$UO~O#Z#oO#k$WO~P3[Ot!gO#Z!si#l!si!Z!si!^!si!_!si#h!si!f!si~Ot!gO#Z!ri#l!ri!Z!ri!^!ri!_!ri#h!ri!f!ri~Ot!gO!Z![X!^![X!_![X!f![X~O#Z$ZO!Z#eP!^#eP!_#eP!f#eP~P8xO!Z$_O!^$`O!_$aO~O!Q!kO!X!Oa~O#Z$eO~P8xO!Z$_O!^$`O!_$hO~O#Z!RO#h$kO~O#Z!RO#hyi~O!QtO#Z#lO#k$nO~O#Z#oO#k$oO~P3[Ot!gO#Z$pO~O#Z$ZO!Z#eX!^#eX!_#eX!f#eX~P8xOl$rO~O!X$sO~O!_$tO~O!^$`O!_$tO~Ot!gO!Z$_O!^$`O!_$vO~O#Z$ZO!Z#eP!^#eP!_#eP~P8xO!_$}O!f$|O~O!_%PO~O!_%QO~O!^$`O!_%QO~OpgO!`sO#hyq~P,wO#Z!RO#hyq~O!X%VO~O!_%XO~O!_%YO~O!^$`O!_%YO~O!Z$_O!^$`O!_%YO~O!_%^O!f$|O~O!X%aO!c%`O~O!_%^O~O!_%bO~OpgO!`sO#hyy~P,wO!_%eO~O!^$`O!_%eO~O!_%hO~O!_%kO~O!X%lO~O{!j~",
goto: "8f#gPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP#hP$RP$h%f&t&zP(U(b)[)_P)eP*l*lPPP*pP*|+fPPP+|#hP,f-PP-T-Z-pP.g/k$R$RP$RP$R$R0q0w1T1w1}2X2_2f2l2v2|3WPPP3b3f4Z6PPPP7ZP7kPPPPP7o7u7{r`Oe!a!b!c!f!u#s#{#|#}$[$d$r%U%`%kQ!WWR#a!Rw`OWe!R!a!b!c!f!u#s#{#|#}$[$d$r%U%`%kr^Oe!a!b!c!f!u#s#{#|#}$[$d$r%U%`%kQ!ZWS!og%_Q!thQ!xjQ#W!OQ#Y}Q#]!PR#d!RvSOeg!a!b!c!f!u#s#{#|#}$[$d$r%U%_%`%k!WZRSYhjsvxyz{|}!O!P!S!T!]!`!n#e#j#o$U$k%S%bS!TW!RQ!ykR!zlQ!VWR#`!RrROe!a!b!c!f!u#s#{#|#}$[$d$r%U%`%k!WwRSYhjsvxyz{|}!O!P!S!T!]!`!n#e#j#o$U$k%S%bS!SW!RT!ng%_etRSv!S!T!n#e$k%S%br`Oe!a!b!c!f!u#s#{#|#}$[$d$r%U%`%kdrRSv!S!T!n#e$k%S%bQ!WWQ#OsR#a!RR!mfX!kf!i!l#x#SZORSWYeghjsvxyz{|}!O!P!R!S!T!]!`!a!b!c!f!n!u#e#j#o#s#{#|#}$U$[$d$k$r%S%U%_%`%b%kR#y!jTnQpQ$b#tQ$i$OQ$w$cR%Z$xQ#t!cQ$O!uQ$e#|Q$f#}Q%V$rQ%c%UQ%i%`R%l%kQ$a#tQ$h$OQ$t$bQ$v$cQ%Q$iS%Y$w$xR%e%ZdtRSv!S!T!n#e$k%S%bQ!^YQ#h!]X#k!^#h#l$SvTOWe!R!a!b!c!f!u#s#{#|#}$[$d$r%U%`%kT!qg%_T$y$e$zQ$}$eR%^$zwTOWe!R!a!b!c!f!u#s#{#|#}$[$d$r%U%`%krVOe!a!b!c!f!u#s#{#|#}$[$d$r%U%`%kQ!UWQ!wjQ#QyQ#TzQ#V{R#_!R#TZORSWYeghjsvxyz{|}!O!P!R!S!T!]!`!a!b!c!f!n!u#e#j#o#s#{#|#}$U$[$d$k$r%S%U%_%`%b%k![ZRSYghjsvxyz{|}!O!P!S!T!]!`!n#e#j#o$U$k%S%_%bw[OWe!R!a!b!c!f!u#s#{#|#}$[$d$r%U%`%kQeOR!ge^!db![#p#q#r$Z$cR#u!dQ!RWQ!]Y`#^!R!]#e#f$P$k%S%bS#e!S!TS#f!U!ZS$P#_#dQ$k$RR%S$lQ!ifR#w!iQ!lfQ#x!iT#z!l#xQpQR!|pS$[#s$dR$p$[Q$l$RR%T$lYvRS!S!T!nR#PvQ$z$eR%[$zQ#l!^Q$S#hT$W#l$SQ#o!`Q$U#jT$X#o$UTdOeSbOeS![W!RQ#p!aQ#q!b`#r!c!u#|#}$r%U%`%kQ#v!fU$Z#s$[$dR$c#{vUOWe!R!a!b!c!f!u#s#{#|#}$[$d$r%U%`%kdrRSv!S!T!n#e$k%S%bQ!`YS!pg%_Q!shQ!vjQ#OsQ#QxQ#RyQ#SzQ#U{Q#W|Q#X}Q#Z!OQ#[!PQ#j!]X#n!`#j#o$Ur]Oe!a!b!c!f!u#s#{#|#}$[$d$r%U%`%k![wRSYghjsvxyz{|}!O!P!S!T!]!`!n#e#j#o$U$k%S%_%bQ!YWR#c!R[uRSv!S!T!nQ$R#eV%R$k%S%bToQpQ$]#sR$x$dQ!rgR%h%_raOe!a!b!c!f!u#s#{#|#}$[$d$r%U%`%kQ!XWR#b!R", goto: "8g#hPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP#iP$SP$i%g&u&{P(V(c)])`P)fP*m*mPPP*qP*}+gPPP+}#iP,g-QP-U-[-qP.h/l$S$SP$SP$S$S0r0x1U1x2O2Y2`2g2m2w2}3XPPPP3c3g4[6QPPP7[P7lPPPPP7p7v7|raOf!b!c!d!g!v#t#|#}$O$]$e$s%V%a%lQ!XXR#b!SwaOXf!S!b!c!d!g!v#t#|#}$O$]$e$s%V%a%lr_Of!b!c!d!g!v#t#|#}$O$]$e$s%V%a%lQ![XS!ph%`Q!uiQ!ykQ#X!PQ#Z!OQ#^!QR#e!SvTOfh!b!c!d!g!v#t#|#}$O$]$e$s%V%`%a%l!W[STZiktwyz{|}!O!P!Q!T!U!^!a!o#f#k#p$V$l%T%cS!UX!SQ!zlR!{mQ!WXR#a!SrSOf!b!c!d!g!v#t#|#}$O$]$e$s%V%a%l!WxSTZiktwyz{|}!O!P!Q!T!U!^!a!o#f#k#p$V$l%T%cS!TX!ST!oh%`euSTw!T!U!o#f$l%T%craOf!b!c!d!g!v#t#|#}$O$]$e$s%V%a%ldsSTw!T!U!o#f$l%T%cQ!XXQ#PtR#b!SR!ngX!lg!j!m#y#S[OSTXZfhiktwyz{|}!O!P!Q!S!T!U!^!a!b!c!d!g!o!v#f#k#p#t#|#}$O$V$]$e$l$s%T%V%`%a%c%lR#z!kToQqQ$c#uQ$j$PQ$x$dR%[$yQ#u!dQ$P!vQ$f#}Q$g$OQ%W$sQ%d%VQ%j%aR%m%lQ$b#uQ$i$PQ$u$cQ$w$dQ%R$jS%Z$x$yR%f%[duSTw!T!U!o#f$l%T%cQ!_ZQ#i!^X#l!_#i#m$TvUOXf!S!b!c!d!g!v#t#|#}$O$]$e$s%V%a%lT!rh%`T$z$f${Q%O$fR%_${wUOXf!S!b!c!d!g!v#t#|#}$O$]$e$s%V%a%lrWOf!b!c!d!g!v#t#|#}$O$]$e$s%V%a%lQ!VXQ!xkQ#RzQ#U{Q#W|R#`!S#T[OSTXZfhiktwyz{|}!O!P!Q!S!T!U!^!a!b!c!d!g!o!v#f#k#p#t#|#}$O$V$]$e$l$s%T%V%`%a%c%l![[STZhiktwyz{|}!O!P!Q!T!U!^!a!o#f#k#p$V$l%T%`%cw]OXf!S!b!c!d!g!v#t#|#}$O$]$e$s%V%a%lQfOR!hf^!ec!]#q#r#s$[$dR#v!eQ!SXQ!^Z`#_!S!^#f#g$Q$l%T%cS#f!T!US#g!V![S$Q#`#eQ$l$SR%T$mQ!jgR#x!jQ!mgQ#y!jT#{!m#yQqQR!}qS$]#t$eR$q$]Q$m$SR%U$mYwST!T!U!oR#QwQ${$fR%]${Q#m!_Q$T#iT$X#m$TQ#p!aQ$V#kT$Y#p$VTeOfScOfS!]X!SQ#q!bQ#r!c`#s!d!v#}$O$s%V%a%lQ#w!gU$[#t$]$eR$d#|vVOXf!S!b!c!d!g!v#t#|#}$O$]$e$s%V%a%ldsSTw!T!U!o#f$l%T%cQ!aZS!qh%`Q!tiQ!wkQ#PtQ#RyQ#SzQ#T{Q#V|Q#X}Q#Y!OQ#[!PQ#]!QQ#k!^X#o!a#k#p$Vr^Of!b!c!d!g!v#t#|#}$O$]$e$s%V%a%l![xSTZhiktwyz{|}!O!P!Q!T!U!^!a!o#f#k#p$V$l%T%`%cQ!ZXR#d!S[vSTw!T!U!oQ$S#fV%S$l%T%cTpQqQ$^#tR$y$eQ!shR%i%`rbOf!b!c!d!g!v#t#|#}$O$]$e$s%V%a%lQ!YXR#c!S",
nodeNames: "⚠ Star Slash Plus Minus And Or Eq EqEq Neq Lt Lte Gt Gte Modulo PlusEq MinusEq StarEq SlashEq ModuloEq Band Bor Bxor Shl Shr Ushr NullishCoalesce NullishEq Identifier AssignableIdentifier Word IdentifierBeforeDot Do Comment Program PipeExpr operator WhileExpr keyword ConditionalOp ParenExpr FunctionCall DotGet Number PositionalArg FunctionDef Params NamedParam NamedArgPrefix String StringFragment Interpolation EscapeSeq Boolean Null colon CatchExpr keyword Block FinallyExpr keyword keyword Underscore NamedArg IfExpr keyword FunctionCall ElseIfExpr keyword ElseExpr FunctionCallOrIdentifier BinOp Regex Dict Array FunctionCallWithBlock TryExpr keyword Throw keyword CompoundAssign Assign", nodeNames: "⚠ Star Slash Plus Minus And Or Eq EqEq Neq Lt Lte Gt Gte Modulo PlusEq MinusEq StarEq SlashEq ModuloEq Band Bor Bxor Shl Shr Ushr NullishCoalesce NullishEq Identifier AssignableIdentifier Word IdentifierBeforeDot Do Comment Program PipeExpr operator WhileExpr keyword ConditionalOp ParenExpr FunctionCall DotGet Number PositionalArg FunctionDef Params NamedParam NamedArgPrefix String StringFragment Interpolation EscapeSeq Boolean Null colon CatchExpr keyword Block FinallyExpr keyword keyword Underscore NamedArg IfExpr keyword FunctionCall ElseIfExpr keyword ElseExpr FunctionCallOrIdentifier BinOp Regex Dict Array FunctionCallWithBlock TryExpr keyword Throw keyword CompoundAssign Assign",
maxTerm: 119, maxTerm: 120,
context: trackScope, context: trackScope,
nodeProps: [ nodeProps: [
["closedBy", 55,"end"] ["closedBy", 55,"end"]
@ -19,9 +19,9 @@ export const parser = LRParser.deserialize({
propSources: [highlighting], propSources: [highlighting],
skippedNodes: [0,33], skippedNodes: [0,33],
repeatNodeCount: 12, repeatNodeCount: 12,
tokenData: "IS~R}OX$OXY$mYZ%WZp$Opq$mqs$Ost%qtu'Yuw$Owx'_xy'dyz'}z{$O{|(h|}$O}!O(h!O!P$O!P!Q0o!Q!R)Y!R![+w![!]9[!]!^%W!^!}$O!}#O9u#O#P;k#P#Q;p#Q#R$O#R#S<Z#S#T$O#T#Y<t#Y#Z>`#Z#b<t#b#cC|#c#f<t#f#gEP#g#h<t#h#iFS#i#o<t#o#p$O#p#qHd#q;'S$O;'S;=`$g<%l~$O~O$O~~H}S$TU!SSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OS$jP;=`<%l$O^$tU!SS#SYOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU%_U!SS#YQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O^%xZqY!SSOY%qYZ$OZt%qtu&kuw%qwx&kx#O%q#O#P&k#P;'S%q;'S;=`'S<%lO%qY&pSqYOY&kZ;'S&k;'S;=`&|<%lO&kY'PP;=`<%l&k^'VP;=`<%l%q~'_O#_~~'dO#]~U'kU!SS#XQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU(UU!SS#gQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU(mX!SSOt$Ouw$Ox!Q$O!Q!R)Y!R![+w![#O$O#P;'S$O;'S;=`$g<%lO$OU)a`!SS{QOt$Ouw$Ox!O$O!O!P*c!P!Q$O!Q![+w![#O$O#P#R$O#R#S,t#S#U$O#U#V-c#V#l$O#l#m.w#m;'S$O;'S;=`$g<%lO$OU*hW!SSOt$Ouw$Ox!Q$O!Q![+Q![#O$O#P;'S$O;'S;=`$g<%lO$OU+XY!SS{QOt$Ouw$Ox!Q$O!Q![+Q![#O$O#P#R$O#R#S*c#S;'S$O;'S;=`$g<%lO$OU,O[!SS{QOt$Ouw$Ox!O$O!O!P*c!P!Q$O!Q![+w![#O$O#P#R$O#R#S,t#S;'S$O;'S;=`$g<%lO$OU,yW!SSOt$Ouw$Ox!Q$O!Q![+w![#O$O#P;'S$O;'S;=`$g<%lO$OU-hX!SSOt$Ouw$Ox!Q$O!Q!R.T!R!S.T!S#O$O#P;'S$O;'S;=`$g<%lO$OU.[X!SS{QOt$Ouw$Ox!Q$O!Q!R.T!R!S.T!S#O$O#P;'S$O;'S;=`$g<%lO$OU.|[!SSOt$Ouw$Ox!Q$O!Q![/r![!c$O!c!i/r!i#O$O#P#T$O#T#Z/r#Z;'S$O;'S;=`$g<%lO$OU/y[!SS{QOt$Ouw$Ox!Q$O!Q![/r![!c$O!c!i/r!i#O$O#P#T$O#T#Z/r#Z;'S$O;'S;=`$g<%lO$OU0tW!SSOt$Ouw$Ox!P$O!P!Q1^!Q#O$O#P;'S$O;'S;=`$g<%lO$OU1c^!SSOY2_YZ$OZt2_tu3buw2_wx3bx!P2_!P!Q$O!Q!}2_!}#O8T#O#P5p#P;'S2_;'S;=`9U<%lO2_U2f^!SS!jQOY2_YZ$OZt2_tu3buw2_wx3bx!P2_!P!Q6V!Q!}2_!}#O8T#O#P5p#P;'S2_;'S;=`9U<%lO2_Q3gX!jQOY3bZ!P3b!P!Q4S!Q!}3b!}#O4q#O#P5p#P;'S3b;'S;=`6P<%lO3bQ4VP!P!Q4YQ4_U!jQ#Z#[4Y#]#^4Y#a#b4Y#g#h4Y#i#j4Y#m#n4YQ4tVOY4qZ#O4q#O#P5Z#P#Q3b#Q;'S4q;'S;=`5j<%lO4qQ5^SOY4qZ;'S4q;'S;=`5j<%lO4qQ5mP;=`<%l4qQ5sSOY3bZ;'S3b;'S;=`6P<%lO3bQ6SP;=`<%l3bU6[W!SSOt$Ouw$Ox!P$O!P!Q6t!Q#O$O#P;'S$O;'S;=`$g<%lO$OU6{b!SS!jQOt$Ouw$Ox#O$O#P#Z$O#Z#[6t#[#]$O#]#^6t#^#a$O#a#b6t#b#g$O#g#h6t#h#i$O#i#j6t#j#m$O#m#n6t#n;'S$O;'S;=`$g<%lO$OU8Y[!SSOY8TYZ$OZt8Ttu4quw8Twx4qx#O8T#O#P5Z#P#Q2_#Q;'S8T;'S;=`9O<%lO8TU9RP;=`<%l8TU9XP;=`<%l2_U9cU!SS!XQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU9|W#iQ!SSOt$Ouw$Ox!_$O!_!`:f!`#O$O#P;'S$O;'S;=`$g<%lO$OU:kV!SSOt$Ouw$Ox#O$O#P#Q;Q#Q;'S$O;'S;=`$g<%lO$OU;XU#hQ!SSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O~;pO#`~U;wU#jQ!SSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU<bU!SS!`QOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU<y^!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#o<t#o;'S$O;'S;=`$g<%lO$OU=|U!QQ!SSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU>e_!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#U?d#U#o<t#o;'S$O;'S;=`$g<%lO$OU?i`!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#`<t#`#a@k#a#o<t#o;'S$O;'S;=`$g<%lO$OU@p`!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#g<t#g#hAr#h#o<t#o;'S$O;'S;=`$g<%lO$OUAw`!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#X<t#X#YBy#Y#o<t#o;'S$O;'S;=`$g<%lO$OUCQ^!VQ!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#o<t#o;'S$O;'S;=`$g<%lO$O^DT^#aW!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#o<t#o;'S$O;'S;=`$g<%lO$O^EW^#cW!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#o<t#o;'S$O;'S;=`$g<%lO$O^FZ`#bW!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#f<t#f#gG]#g#o<t#o;'S$O;'S;=`$g<%lO$OUGb`!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#i<t#i#jAr#j#o<t#o;'S$O;'S;=`$g<%lO$OUHkUtQ!SSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O~ISO#k~", tokenData: "IS~R}OX$OXY$mYZ%WZp$Opq$mqs$Ost%qtu'Yuw$Owx'_xy'dyz'}z{$O{|(h|}$O}!O(h!O!P$O!P!Q0o!Q!R)Y!R![+w![!]9[!]!^%W!^!}$O!}#O9u#O#P;k#P#Q;p#Q#R$O#R#S<Z#S#T$O#T#Y<t#Y#Z>`#Z#b<t#b#cC|#c#f<t#f#gEP#g#h<t#h#iFS#i#o<t#o#p$O#p#qHd#q;'S$O;'S;=`$g<%l~$O~O$O~~H}S$TU!SSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OS$jP;=`<%l$O^$tU!SS#TYOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU%_U!SS#ZQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O^%xZqY!SSOY%qYZ$OZt%qtu&kuw%qwx&kx#O%q#O#P&k#P;'S%q;'S;=`'S<%lO%qY&pSqYOY&kZ;'S&k;'S;=`&|<%lO&kY'PP;=`<%l&k^'VP;=`<%l%q~'_O#`~~'dO#^~U'kU!SS#YQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU(UU!SS#hQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU(mX!SSOt$Ouw$Ox!Q$O!Q!R)Y!R![+w![#O$O#P;'S$O;'S;=`$g<%lO$OU)a`!SS{QOt$Ouw$Ox!O$O!O!P*c!P!Q$O!Q![+w![#O$O#P#R$O#R#S,t#S#U$O#U#V-c#V#l$O#l#m.w#m;'S$O;'S;=`$g<%lO$OU*hW!SSOt$Ouw$Ox!Q$O!Q![+Q![#O$O#P;'S$O;'S;=`$g<%lO$OU+XY!SS{QOt$Ouw$Ox!Q$O!Q![+Q![#O$O#P#R$O#R#S*c#S;'S$O;'S;=`$g<%lO$OU,O[!SS{QOt$Ouw$Ox!O$O!O!P*c!P!Q$O!Q![+w![#O$O#P#R$O#R#S,t#S;'S$O;'S;=`$g<%lO$OU,yW!SSOt$Ouw$Ox!Q$O!Q![+w![#O$O#P;'S$O;'S;=`$g<%lO$OU-hX!SSOt$Ouw$Ox!Q$O!Q!R.T!R!S.T!S#O$O#P;'S$O;'S;=`$g<%lO$OU.[X!SS{QOt$Ouw$Ox!Q$O!Q!R.T!R!S.T!S#O$O#P;'S$O;'S;=`$g<%lO$OU.|[!SSOt$Ouw$Ox!Q$O!Q![/r![!c$O!c!i/r!i#O$O#P#T$O#T#Z/r#Z;'S$O;'S;=`$g<%lO$OU/y[!SS{QOt$Ouw$Ox!Q$O!Q![/r![!c$O!c!i/r!i#O$O#P#T$O#T#Z/r#Z;'S$O;'S;=`$g<%lO$OU0tW!SSOt$Ouw$Ox!P$O!P!Q1^!Q#O$O#P;'S$O;'S;=`$g<%lO$OU1c^!SSOY2_YZ$OZt2_tu3buw2_wx3bx!P2_!P!Q$O!Q!}2_!}#O8T#O#P5p#P;'S2_;'S;=`9U<%lO2_U2f^!SS!jQOY2_YZ$OZt2_tu3buw2_wx3bx!P2_!P!Q6V!Q!}2_!}#O8T#O#P5p#P;'S2_;'S;=`9U<%lO2_Q3gX!jQOY3bZ!P3b!P!Q4S!Q!}3b!}#O4q#O#P5p#P;'S3b;'S;=`6P<%lO3bQ4VP!P!Q4YQ4_U!jQ#Z#[4Y#]#^4Y#a#b4Y#g#h4Y#i#j4Y#m#n4YQ4tVOY4qZ#O4q#O#P5Z#P#Q3b#Q;'S4q;'S;=`5j<%lO4qQ5^SOY4qZ;'S4q;'S;=`5j<%lO4qQ5mP;=`<%l4qQ5sSOY3bZ;'S3b;'S;=`6P<%lO3bQ6SP;=`<%l3bU6[W!SSOt$Ouw$Ox!P$O!P!Q6t!Q#O$O#P;'S$O;'S;=`$g<%lO$OU6{b!SS!jQOt$Ouw$Ox#O$O#P#Z$O#Z#[6t#[#]$O#]#^6t#^#a$O#a#b6t#b#g$O#g#h6t#h#i$O#i#j6t#j#m$O#m#n6t#n;'S$O;'S;=`$g<%lO$OU8Y[!SSOY8TYZ$OZt8Ttu4quw8Twx4qx#O8T#O#P5Z#P#Q2_#Q;'S8T;'S;=`9O<%lO8TU9RP;=`<%l8TU9XP;=`<%l2_U9cU!SS!XQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU9|W#jQ!SSOt$Ouw$Ox!_$O!_!`:f!`#O$O#P;'S$O;'S;=`$g<%lO$OU:kV!SSOt$Ouw$Ox#O$O#P#Q;Q#Q;'S$O;'S;=`$g<%lO$OU;XU#iQ!SSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O~;pO#a~U;wU#kQ!SSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU<bU!SS!`QOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU<y^!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#o<t#o;'S$O;'S;=`$g<%lO$OU=|U!QQ!SSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU>e_!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#U?d#U#o<t#o;'S$O;'S;=`$g<%lO$OU?i`!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#`<t#`#a@k#a#o<t#o;'S$O;'S;=`$g<%lO$OU@p`!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#g<t#g#hAr#h#o<t#o;'S$O;'S;=`$g<%lO$OUAw`!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#X<t#X#YBy#Y#o<t#o;'S$O;'S;=`$g<%lO$OUCQ^!VQ!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#o<t#o;'S$O;'S;=`$g<%lO$O^DT^#bW!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#o<t#o;'S$O;'S;=`$g<%lO$O^EW^#dW!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#o<t#o;'S$O;'S;=`$g<%lO$O^FZ`#cW!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#f<t#f#gG]#g#o<t#o;'S$O;'S;=`$g<%lO$OUGb`!SSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#i<t#i#jAr#j#o<t#o;'S$O;'S;=`$g<%lO$OUHkUtQ!SSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O~ISO#l~",
tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO#Z~~", 11)], tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO#[~~", 11)],
topRules: {"Program":[0,34]}, topRules: {"Program":[0,34]},
specialized: [{term: 28, get: (value: any, stack: any) => (specializeKeyword(value, stack) << 1), external: specializeKeyword},{term: 28, get: (value: keyof typeof spec_Identifier) => spec_Identifier[value] || -1}], specialized: [{term: 28, get: (value: any, stack: any) => (specializeKeyword(value, stack) << 1), external: specializeKeyword},{term: 28, get: (value: keyof typeof spec_Identifier) => spec_Identifier[value] || -1}],
tokenPrec: 2202 tokenPrec: 2229
}) })

View File

@ -127,3 +127,31 @@ describe('string escape sequences', () => {
`) `)
}) })
}) })
describe('curly strings', () => {
test('work on one line', () => {
expect('{ one two three }').toMatchTree(`
String one two three
`)
})
test('work on multiple lines', () => {
expect(`{
one
two
three }`).toMatchTree(`
String
one
two
three `)
})
test('can contain other curlies', () => {
expect(`{ { one }
two
{ three } }`).toMatchTree(`
String { one }
two
{ three } `)
})
})

View File

@ -1,5 +1,5 @@
import { ExternalTokenizer, InputStream, Stack } from '@lezer/lr' import { ExternalTokenizer, InputStream, Stack } from '@lezer/lr'
import { Identifier, AssignableIdentifier, Word, IdentifierBeforeDot, Do } from './shrimp.terms' import { Identifier, AssignableIdentifier, Word, IdentifierBeforeDot, Do, curlyString } from './shrimp.terms'
// doobie doobie do (we need the `do` keyword to know when we're defining params) // doobie doobie do (we need the `do` keyword to know when we're defining params)
export function specializeKeyword(ident: string) { export function specializeKeyword(ident: string) {
@ -18,6 +18,12 @@ export const setGlobals = (newGlobals: string[] | Record<string, any>) => {
export const tokenizer = new ExternalTokenizer( export const tokenizer = new ExternalTokenizer(
(input: InputStream, stack: Stack) => { (input: InputStream, stack: Stack) => {
const ch = getFullCodePoint(input, 0) const ch = getFullCodePoint(input, 0)
// Handle curly strings
if (ch === 123) { // {
return consumeCurlyString(input, stack)
}
if (!isWordChar(ch)) return if (!isWordChar(ch)) return
// Don't consume things that start with digits - let Number token handle it // Don't consume things that start with digits - let Number token handle it
@ -157,6 +163,31 @@ const consumeRestOfWord = (input: InputStream, startPos: number, canBeWord: bool
return pos return pos
} }
const consumeCurlyString = (input: InputStream, stack: Stack) => {
if (!stack.canShift(curlyString)) return
let depth = 0
let pos = 0
while (true) {
const ch = input.peek(pos)
if (ch < 0) return // EOF - invalid
if (ch === 123) depth++ // {
else if (ch === 125) { // }
depth--
if (depth === 0) {
pos++ // consume final }
break
}
}
pos++
}
input.acceptToken(curlyString, pos)
}
// Check if this identifier is in scope (for property access detection) // Check if this identifier is in scope (for property access detection)
// Returns IdentifierBeforeDot token if in scope, null otherwise // Returns IdentifierBeforeDot token if in scope, null otherwise
const checkForDotGet = (input: InputStream, stack: Stack, pos: number): number | null => { const checkForDotGet = (input: InputStream, stack: Stack, pos: number): number | null => {