Compare commits

...

3 Commits

Author SHA1 Message Date
68ec6f9f3e Merge pull request 'atoms-can-be-piped' (#31) from atoms-can-be-piped into main
Reviewed-on: #31
Reviewed-by: probablycorey <probablycorey@gmail.com>
2025-11-08 02:48:11 +00:00
Chris Wanstrath
890eb811b9 pipe atoms/literals to functions 2025-11-07 15:17:29 -08:00
Chris Wanstrath
fd3c5da59b coerce values to string in str prelude functions 2025-11-07 15:16:59 -08:00
6 changed files with 166 additions and 63 deletions

View File

@ -92,4 +92,30 @@ describe('pipe expressions', () => {
get-msg | length get-msg | length
`).toEvaluateTo(5) `).toEvaluateTo(5)
}) })
test('string literals can be piped', () => {
expect(`'hey there' | str.to-upper`).toEvaluateTo('HEY THERE')
})
test('number literals can be piped', () => {
expect(`42 | str.trim`).toEvaluateTo('42')
expect(`4.22 | str.trim`).toEvaluateTo('4.22')
})
test('null literals can be piped', () => {
expect(`null | type`).toEvaluateTo('null')
})
test('boolean literals can be piped', () => {
expect(`true | str.to-upper`).toEvaluateTo('TRUE')
})
test('array literals can be piped', () => {
expect(`[1 2 3] | str.join '-'`).toEvaluateTo('1-2-3')
})
test('dict literals can be piped', () => {
expect(`[a=1 b=2 c=3] | dict.values | list.sort | str.join '-'`).toEvaluateTo('1-2-3')
})
}) })

View File

@ -50,7 +50,7 @@ null { @specialize[@name=Null]<Identifier, "null"> }
call call
} }
item { item {
consumeToTerminator newlineOrSemicolon | consumeToTerminator newlineOrSemicolon |
consumeToTerminator eof | consumeToTerminator eof |
newlineOrSemicolon // allow blank lines newlineOrSemicolon // allow blank lines
@ -77,7 +77,7 @@ PipeExpr {
} }
pipeOperand { pipeOperand {
FunctionCall | FunctionCallOrIdentifier consumeToTerminator
} }
WhileExpr { WhileExpr {
@ -235,7 +235,7 @@ Array {
// We need expressionWithoutIdentifier to avoid conflicts in consumeToTerminator. // We need expressionWithoutIdentifier to avoid conflicts in consumeToTerminator.
// Without this, when parsing "my-var" at statement level, the parser can't decide: // Without this, when parsing "my-var" at statement level, the parser can't decide:
// - ambiguousFunctionCall → FunctionCallOrIdentifier → Identifier // - ambiguousFunctionCall → FunctionCallOrIdentifier → Identifier
// - expression → Identifier // - expression → Identifier
// Both want the same Identifier token! So we use expressionWithoutIdentifier // Both want the same Identifier token! So we use expressionWithoutIdentifier
// to remove Identifier from the second path, forcing standalone identifiers // to remove Identifier from the second path, forcing standalone identifiers
// to go through ambiguousFunctionCall (which is what we want semantically). // to go through ambiguousFunctionCall (which is what we want semantically).

View File

@ -27,38 +27,38 @@ export const
Comment = 25, Comment = 25,
Program = 26, Program = 26,
PipeExpr = 27, PipeExpr = 27,
FunctionCall = 28, WhileExpr = 29,
DotGet = 29,
Number = 30,
ParenExpr = 31,
IfExpr = 32,
keyword = 70, keyword = 70,
ConditionalOp = 34, ConditionalOp = 31,
String = 35, ParenExpr = 32,
StringFragment = 36, IfExpr = 33,
Interpolation = 37, FunctionCall = 35,
EscapeSeq = 38, DotGet = 36,
Boolean = 39, Number = 37,
Regex = 40, PositionalArg = 38,
Dict = 41, FunctionDef = 39,
NamedArg = 42, Params = 40,
NamedArgPrefix = 43, NamedParam = 41,
FunctionDef = 44, NamedArgPrefix = 42,
Params = 45, String = 43,
NamedParam = 46, StringFragment = 44,
Null = 47, Interpolation = 45,
colon = 48, EscapeSeq = 46,
CatchExpr = 49, Boolean = 47,
Block = 51, Null = 48,
FinallyExpr = 52, colon = 49,
Underscore = 55, CatchExpr = 50,
Array = 56, Block = 52,
ElseIfExpr = 57, FinallyExpr = 53,
ElseExpr = 59, Underscore = 56,
FunctionCallOrIdentifier = 60, NamedArg = 57,
BinOp = 61, ElseIfExpr = 58,
PositionalArg = 62, ElseExpr = 60,
WhileExpr = 64, FunctionCallOrIdentifier = 61,
BinOp = 62,
Regex = 63,
Dict = 64,
Array = 65,
FunctionCallWithBlock = 66, FunctionCallWithBlock = 66,
TryExpr = 67, TryExpr = 67,
Throw = 69, Throw = 69,

View File

@ -4,23 +4,23 @@ import {operatorTokenizer} from "./operatorTokenizer"
import {tokenizer, specializeKeyword} from "./tokenizer" import {tokenizer, specializeKeyword} from "./tokenizer"
import {trackScope} from "./parserScopeContext" import {trackScope} from "./parserScopeContext"
import {highlighting} from "./highlight" import {highlighting} from "./highlight"
const spec_Identifier = {__proto__:null,if:66, null:94, catch:100, finally:106, end:108, else:116, while:130, try:136, throw:140} const spec_Identifier = {__proto__:null,while:60, if:68, null:96, catch:102, finally:108, end:110, else:118, try:136, throw:140}
export const parser = LRParser.deserialize({ export const parser = LRParser.deserialize({
version: 14, version: 14,
states: "9[QYQbOOO!dOSO'#DPOOQa'#DV'#DVO#mQbO'#DfO%RQcO'#E^OOQa'#E^'#E^O&XQcO'#E^O'ZQcO'#E]O'qQcO'#E]O)^QRO'#DOO*mQcO'#EWO*wQcO'#EWO+XQbO'#C{O,SOpO'#CyOOQ`'#EX'#EXO,XQbO'#EWO,cQRO'#DuOOQ`'#EW'#EWO,wQQO'#EVOOQ`'#EV'#EVOOQ`'#Dw'#DwQYQbOOO-PQbO'#DYO-[QbO'#C|O.PQbO'#DnO.tQQO'#DqO.PQbO'#DsO.yQbO'#DRO/RQWO'#DSOOOO'#E`'#E`OOOO'#Dx'#DxO/gOSO,59kOOQa,59k,59kOOQ`'#Dy'#DyO/uQbO,5:QO/|QbO'#DWO0WQQO,59qOOQa,5:Q,5:QO0cQbO,5:QOOQa'#E]'#E]OOQ`'#Dl'#DlOOQ`'#El'#ElOOQ`'#EQ'#EQO0mQbO,59dO1gQbO,5:bO.PQbO,59jO.PQbO,59jO.PQbO,59jO.PQbO,5:VO.PQbO,5:VO.PQbO,5:VO1wQRO,59gO2OQRO,59gO2ZQRO,59gO2UQQO,59gO2lQQO,59gO2tObO,59eO3PQbO'#ERO3[QbO,59cO3vQbO,5:[O1gQbO,5:aOOQ`,5:q,5:qOOQ`-E7u-E7uOOQ`'#Dz'#DzO4ZQbO'#DZO4fQbO'#D[OOQO'#D{'#D{O4^QQO'#DZO4tQQO,59tO4yQcO'#E]O6_QRO'#E[O6fQRO'#E[OOQO'#E['#E[O6qQQO,59hO6vQRO,5:YO6}QRO,5:YO3vQbO,5:]O7YQcO,5:_O8UQcO,5:_O8`QcO,5:_OOOO,59m,59mOOOO,59n,59nOOOO-E7v-E7vOOQa1G/V1G/VOOQ`-E7w-E7wO8pQQO1G/]OOQa1G/l1G/lO8{QbO1G/lOOQ`,59r,59rOOQO'#D}'#D}O8pQQO1G/]OOQa1G/]1G/]OOQ`'#EO'#EOO8{QbO1G/lOOQ`-E8O-E8OOOQ`1G/|1G/|OOQa1G/U1G/UO:WQcO1G/UO:_QcO1G/UO:fQcO1G/UOOQa1G/q1G/qO;_QcO1G/qO;iQcO1G/qO;sQcO1G/qOOQa1G/R1G/ROOQa1G/P1G/PO<hQbO'#DjO=_QbO'#CxOOQ`,5:m,5:mOOQ`-E8P-E8POOQ`'#Da'#DaO=lQbO'#DaO>]QbO1G/vOOQ`1G/{1G/{OOQ`-E7x-E7xO>hQQO,59uOOQO,59v,59vOOQO-E7y-E7yO>pQbO1G/`O3vQbO1G/SO3vQbO1G/tO?TQbO1G/wO?`QQO7+$wOOQa7+$w7+$wO?kQbO7+%WOOQa7+%W7+%WOOQO-E7{-E7{OOQ`-E7|-E7|OOQ`'#D|'#D|O?uQQO'#D|O?zQbO'#EiOOQ`,59{,59{O@kQbO'#D_O@pQQO'#DbOOQ`7+%b7+%bO@uQbO7+%bO@zQbO7+%bOASQbO7+$zOA_QbO7+$zOA{QbO7+$nOBTQbO7+%`OOQ`7+%c7+%cOBYQbO7+%cOB_QbO7+%cOOQa<<Hc<<HcOOQa<<Hr<<HrOOQ`,5:h,5:hOOQ`-E7z-E7zOBgQQO,59yO3vQbO,59|OOQ`<<H|<<H|OBlQbO<<H|OOQ`<<Hf<<HfOBqQbO<<HfOBvQbO<<HfOCOQbO<<HfOOQ`'#EP'#EPOCZQbO<<HYOCcQbO'#DiOOQ`<<HY<<HYOCkQbO<<HYOOQ`<<Hz<<HzOOQ`<<H}<<H}OCpQbO<<H}O3vQbO1G/eOOQ`1G/h1G/hOOQ`AN>hAN>hOOQ`AN>QAN>QOCuQbOAN>QOCzQbOAN>QOOQ`-E7}-E7}OOQ`AN=tAN=tODSQbOAN=tO-[QbO,5:RO3vQbO,5:TOOQ`AN>iAN>iOOQ`7+%P7+%POOQ`G23lG23lODXQbOG23lPD^QbO'#DgOOQ`G23`G23`ODcQQO1G/mOOQ`1G/o1G/oOOQ`LD)WLD)WO3vQbO7+%XOOQ`<<Hs<<Hs", states: "9UQYQbOOO!dOpO'#DQO!iOSO'#DXO$_QcO'#DkO&rQcO'#EYOOQ`'#Eh'#EhO'uQRO'#DlO)[QcO'#EWO)lQbO'#C|OOQa'#Dn'#DnO+nQbO'#DoOOQa'#EY'#EYO+uQcO'#EYO+|QcO'#EXO,yQcO'#EWO-TQRO'#DuOOQ`'#EW'#EWO-iQbO'#EWO-pQQO'#EVOOQ`'#EV'#EVOOQ`'#Dw'#DwQYQbOOO-{QbO'#DTO.WQbO'#C}O.{QbO'#CyO/pQQO'#DqO.{QbO'#DsO/uObO,59lO0QQbO'#DZO0YQWO'#D[OOOO'#E`'#E`OOOO'#D|'#D|O0nOSO,59sOOQa,59s,59sOOQ`'#DS'#DSO0|QbO'#DgOOQ`'#E^'#E^OOQ`'#Dy'#DyO1WQbO,59kOOQa'#EX'#EXO.{QbO,5:WO.{QbO,5:WO.{QbO,5:WO.{QbO,59gO.{QbO,59gO.{QbO,59gO2QQRO,59hO2^QQO,59hO2fQQO,59hO2qQRO,59hO3[QRO,59hO3jQQO'#CwOOQ`'#EP'#EPO3oQbO,5:ZO3vQQO,5:YOOQa,5:Z,5:ZO4RQbO,5:ZO)lQbO,5:bO)lQbO,5:aO4]QbO,5:[O4dQbO,59cOOQ`,5:q,5:qO)lQbO'#DxOOQ`-E7u-E7uOOQ`'#Dz'#DzO5OQbO'#DUO5ZQbO'#DVOOQO'#D{'#D{O5RQQO'#DUO5iQQO,59oO5nQcO'#EXO5uQRO'#E[O6lQRO'#E[OOQO'#E['#E[O6sQQO,59iO6xQRO,59eO7PQRO,59eO4]QbO,5:]O7[QcO,5:_O8dQcO,5:_O8tQcO,5:_OOQa1G/W1G/WOOOO,59u,59uOOOO,59v,59vOOOO-E7z-E7zOOQa1G/_1G/_OOQ`,5:R,5:ROOQ`-E7w-E7wOOQa1G/r1G/rO9sQcO1G/rO9}QcO1G/rO:XQcO1G/rOOQa1G/R1G/RO<TQcO1G/RO<[QcO1G/RO<cQcO1G/ROOQa1G/S1G/SOOQ`-E7}-E7}O<jQQO1G/tOOQa1G/u1G/uO<uQbO1G/uOOQO'#EQ'#EQO<jQQO1G/tOOQa1G/t1G/tOOQ`'#ER'#ERO<uQbO1G/uO=PQbO1G/|O=kQbO1G/{O>VQbO'#DbO>hQbO'#DbO>{QbO1G/vOOQ`-E7v-E7vOOQ`,5:d,5:dOOQ`-E7x-E7xO?WQQO,59pOOQO,59q,59qOOQO-E7y-E7yO?`QbO1G/ZO4]QbO1G/TO4]QbO1G/PO?gQbO1G/wO?rQQO7+%`OOQa7+%`7+%`O?}QbO7+%aOOQa7+%a7+%aOOQO-E8O-E8OOOQ`-E8P-E8POOQ`'#D}'#D}O@XQQO'#D}O@aQbO'#EgOOQ`,59|,59|O@tQbO'#D`O@yQQO'#DcOOQ`7+%b7+%bOAOQbO7+%bOATQbO7+%bOA]QbO7+$uOAkQbO7+$uOA{QbO7+$oOBTQbO7+$kOOQ`7+%c7+%cOBYQbO7+%cOB_QbO7+%cOOQa<<Hz<<HzOOQa<<H{<<H{OOQ`,5:i,5:iOOQ`-E7{-E7{OBgQQO,59zO4]QbO,59}OOQ`<<H|<<H|OBlQbO<<H|OOQ`<<Ha<<HaOBqQbO<<HaOBvQbO<<HaOCOQbO<<HaOOQ`'#EO'#EOOCZQbO<<HZOCcQbO'#DjOOQ`<<HZ<<HZOCkQbO<<HZOOQ`<<HV<<HVOOQ`<<H}<<H}OCpQbO<<H}O4]QbO1G/fOOQ`1G/i1G/iOOQ`AN>hAN>hOOQ`AN={AN={OCuQbOAN={OCzQbOAN={OOQ`-E7|-E7|OOQ`AN=uAN=uODSQbOAN=uO.WQbO,5:SO4]QbO,5:UOOQ`AN>iAN>iOOQ`7+%Q7+%QOOQ`G23gG23gODXQbOG23gPD^QbO'#DhOOQ`G23aG23aODcQQO1G/nOOQ`1G/p1G/pOOQ`LD)RLD)RO4]QbO7+%YOOQ`<<Ht<<Ht",
stateData: "Dk~O!xOSiOS~OdWOe`OfTOg]OhfOnTOqgOwTOxTO!PTO!chO!fiO!hjO!}[O#RPO#YQO#ZRO#[cO~OtmO#RpO#TkO#UlO~OdwOfTOg]OnTOwTOxTO{sO!PTO!}[O#RPO#YQO#ZRO#[qO~O#^uO~P!rOP#QXQ#QXR#QXS#QXT#QXU#QXW#QXX#QXY#QXZ#QX[#QX]#QX^#QX#[#QX#a#QX!S#QX!V#QX!W#QX![#QX~OdwOfTOg]OhfOnTOwTOxTO{sO!PTO!XxO!}[O#RPO#YQO#ZRO#_#QX!Q#QX~P#tOV|O~P#tOP#PXQ#PXR#PXS#PXT#PXU#PXW#PXX#PXY#PXZ#PX[#PX]#PX^#PX~O#[!zX#a!zX!S!zX!V!zX!W!zX![!zX~P&`OdwOfTOg]OhfOnTOwTOxTO{sO!PTO!XxO!}[O#RPO#YQO#ZRO!Q!^X!a!^X#[!^X#a!^X#_!^X!S!^X!V!^X!W!^X![!^X~P&`OP!ROQ!ROR!SOS!SOT!OOU!POW}OX}OY}OZ}O[}O]}O^!QO~O#[!zX#a!zX!S!zX!V!zX!W!zX![!zX~OT!OOU!PO~P*XOP!ROQ!ROR!SOS!SO~P*XOdWOfTOg]OhfOnTOqgOwTOxTO!PTO!}[O#RPO#YQO#ZRO~O!|!YO~O!Q!]O!a!ZO~P*XOV|O_!^O`!^Oa!^Ob!^Oc!^O~O#[!_O#a!_O~Od!aO{!cO!Q}P~Od!gOfTOg]OnTOwTOxTO!PTO!}[O#RPO#YQO#ZRO~OdwOfTOg]OnTOwTOxTO!PTO!}[O#RPO#YQO#ZRO~O!Q!nO~Od!rO!}[O~O#R!sO#T!sO#U!sO#V!sO#W!sO#X!sO~OtmO#R!uO#TkO#UlO~O#^!xO~P!rOhfO!X!zO~P.PO{sO#[!{O#^!}O~O#[#OO#^!xO~P.POhfO{sO!XxO!Qla!ala#[la#ala#_la!Sla!Vla!Wla![la~P.POe`O!chO!fiO!hjO~P+XO#_#[O~P&`OT!OOU!PO#_#[O~OP!ROQ!ROR!SOS!SO#_#[O~O!a!ZO#_#[O~Od#]On#]O!}[O~Od#^Og]O!}[O~O!a!ZO#[ka#aka#_ka!Ska!Vka!Wka![ka~Oe`O!chO!fiO!hjO#[#cO~P+XOd!aO{!cO!Q}X~On#hOw#hO!P#hO#RPO~O!Q#jO~OhfO{sO!XxOT#PXU#PXW#PXX#PXY#PXZ#PX[#PX]#PX!Q#PX~P.POT!OOU!POW}OX}OY}OZ}O[}O]}O~O!Q#OX~P5sOT!OOU!PO!Q#OX~O!Q#kO~O!Q#lO~P5sOT!OOU!PO!Q#lO~O#[!ga#a!ga!S!ga!V!ga!W!ga![!ga~P)^O#[!ga#a!ga!S!ga!V!ga!W!ga![!ga~OT!OOU!PO~P7pOP!ROQ!ROR!SOS!SO~P7pO{sO#[!{O#^#oO~O#[#OO#^#qO~P.POW}OX}OY}OZ}O[}O]}OTri#[ri#ari#_ri!Qri!Sri!Vri!Wri![ri~OU!PO~P9VOU!PO~P9iOUri~P9VO^!QOR!_iS!_i#[!_i#a!_i#_!_i!S!_i!V!_i!W!_i![!_i~OP!_iQ!_i~P:mOP!ROQ!RO~P:mOP!ROQ!ROR!_iS!_i#[!_i#a!_i#_!_i!S!_i!V!_i!W!_i![!_i~OhfO{sO!XxO!a!^X#[!^X#a!^X#_!^X!S!^X!V!^X!W!^X![!^X~P.POhfO{sO!XxO~P.POe`O!chO!fiO!hjO#[#tO!S#]P!V#]P!W#]P![#]P~P+XO!S#xO!V#yO!W#zO~O{!cO!Q}a~Oe`O!chO!fiO!hjO#[$OO~P+XO!S#xO!V#yO!W$RO~O{sO#[!{O#^$UO~O#[#OO#^$VO~P.PO#[$WO~Oe`O!chO!fiO!hjO#[#tO!S#]X!V#]X!W#]X![#]X~P+XOd$YO~O!Q$ZO~O!W$[O~O!V#yO!W$[O~O!S#xO!V#yO!W$^O~Oe`O!chO!fiO!hjO#[#tO!S#]P!V#]P!W#]P~P+XO!W$eO![$dO~O!W$gO~O!W$hO~O!V#yO!W$hO~O!Q$jO~O!W$lO~O!W$mO~O!V#yO!W$mO~O!S#xO!V#yO!W$mO~O!W$qO![$dO~Oq$sO!Q$tO~O!W$qO~O!W$uO~O!W$wO~O!V#yO!W$wO~O!W$zO~O!W$}O~Oq$sO~O!Q%OO~Onx~", stateData: "Dk~O!xOSiOS~OdROe_OfZOgPOhfOnhOrgOuZO!PZO!QZO!aZO!fiO!hjO!}WO#RQO#YcO#^XO#_YO~O#PkO~O|nO#RqO#TlO#UmO~OdwOfZOgPOhfOuZOzsO!PZO!QZO!YrO!aZO!}WO#RQO#^XO#_YOT!{XU!{XW!{XX!{XY!{XZ!{X[!{X]!{X~OP!{XQ!{XR!{XS!{X^!{Xl!_X!R!_X#Y!_X#a!_X#]!_X!T!_X!W!_X!X!_X!]!_X~P!wOP!|XQ!|XR!|XS!|XT!|XU!|XW!|XX!|XY!|XZ!|X[!|X]!|X^!|Xl!|X#Y!|X#a!|X#]!|X!T!|X!W!|X!X!|X!]!|X~OdwOfZOgPOhfOuZOzsO!PZO!QZO!YrO!aZO!}WO#RQO#^XO#_YO!R!|X~P%_OPyOQyORzOSzOT|OU}OW{OX{OY{OZ{O[{O]{O^xO~Ol!zX#Y!zX#a!zX!T!zX!W!zX!X!zX#]!zX!]!zX~OPyOQyORzOSzO~P(pOdROe_OfZOgPOhfOnhOrgOuZO!PZO!QZO!aZO!fiO!hjO!}WO#RQO#^XO#_YO~OdwOfZOgPOuZOzsO!PZO!QZO!aZO!}WO#RQO#Y!UO#^XO#_YO~O#`!XO~P*sOV!ZO~P%_OP!{XQ!{XR!{XS!{XT!{XU!{XW!{XX!{XY!{XZ!{X[!{X]!{X^!{X~P(pOT|OU}O~P(pOV!ZO_![O`![Oa![Ob![Oc![O~O!R!]O~P(pOl!`O#Y!_O#a!_O~Od!bOz!dO!RxP~Od!hOfZOgPOuZO!PZO!QZO!aZO!}WO#RQO#^XO#_YO~OdwOfZOgPOuZO!PZO!QZO!aZO!}WO#RQO#^XO#_YO~O!R!oO~Od!sOu!sO!}WO~Od!tO!}WO~O#R!uO#T!uO#U!uO#V!uO#W!uO#X!uO~O|nO#R!wO#TlO#UmO~OhfO!Y!xO~P.{OhfOzsO!YrOlsa!Rsa#Ysa#asa#]sa!Tsa!Wsa!Xsa!]sa~P.{OPyOQyORzOSzO#]#SOl!zX~O!R!]O#]#SOl!zX~O#]#SOP!{XQ!{XR!{XS!{X^!{Xl!zX~P#sOT|OU}O#]#SOl!zX~Ol!`O~O#`#VO~P*sOzsO#Y#XO#`#ZO~O#Y#[O#`#VO~P.{O#Y#aO~P)lOl!`O#Yka#aka#]ka!Tka!Wka!Xka!]ka~Od!bOz!dO!RxX~Ou#gO!P#gO!Q#gO#RQO~O!R#iO~O!R!{X~P!wOT|OU}O!R#OX~OT|OU}OW{OX{OY{OZ{O[{O]{O~O!R#OX~P6QO!R#jO~O!R#kO~P6QOT|OU}O!R#kO~Ol!ga#Y!ga#a!ga!T!ga!W!ga!X!ga#]!ga!]!ga~P'uOl!ga#Y!ga#a!ga!T!ga!W!ga!X!ga#]!ga!]!ga~OPyOQyORzOSzO~P7xOT|OU}O~P7xO^xOR!`iS!`il!`i#Y!`i#a!`i#]!`i!T!`i!W!`i!X!`i!]!`i~OP!`iQ!`i~P9OOPyOQyO~P9OOPyOQyOR!`iS!`il!`i#Y!`i#a!`i#]!`i!T!`i!W!`i!X!`i!]!`i~OW{OX{OY{OZ{O[{O]{OToiloi#Yoi#aoi#]oi!Roi!Toi!Woi!Xoi!]oi~OU}O~P;POU}O~P;cOUoi~P;POzsO#Y#XO#`#nO~O#Y#[O#`#pO~P.{Ol!`O#Y!ji#a!ji!T!ji!W!ji!X!ji#]!ji!]!ji~Ol!`O#Y!ii#a!ii!T!ii!W!ii!X!ii#]!ii!]!ii~Ol!`O!T!UX!W!UX!X!UX!]!UX~O#Y#sO!T#ZP!W#ZP!X#ZP!]#ZP~P)lO!T#wO!W#xO!X#yO~Oz!dO!Rxa~O#Y#}O~P)lO!T#wO!W#xO!X$QO~OzsO#Y#XO#`$TO~O#Y#[O#`$UO~P.{Ol!`O#Y$VO~O#Y#sO!T#ZX!W#ZX!X#ZX!]#ZX~P)lOd$XO~O!R$YO~O!X$ZO~O!W#xO!X$ZO~Ol!`O!T#wO!W#xO!X$]O~O#Y#sO!T#ZP!W#ZP!X#ZP~P)lO!X$dO!]$cO~O!X$fO~O!X$gO~O!W#xO!X$gO~O!R$iO~O!X$kO~O!X$lO~O!W#xO!X$lO~O!T#wO!W#xO!X$lO~O!X$pO!]$cO~Or$rO!R$sO~O!X$pO~O!X$tO~O!X$vO~O!W#xO!X$vO~O!X$yO~O!X$|O~Or$rO~O!R$}O~Ou!a~",
goto: "4x#aPPPPPPPPPPPPPPPPPPPPPPPPPPP#b#w$aP%d#bP&k'bP(a(aPP(e)aP)u*g*jPP*pP*|+fPPP+|,zP-O-U-j.YP.bP.b.bP.bP.b.b.t.z/Q/W/^/h/o/y0T0Z0ePPP0l0p1^PP1v1|3fP4fPPPPPPPP4jPP4ppaOe|!]!^!n#c#j#k#l#v$O$Z$j$t%OR!W[t^O[e|!Z!]!^!n#c#j#k#l#v$O$Z$j$t%OT!jg$srWO[e|!]!^!n#c#j#k#l#v$O$Z$j$t%OzwRSWhjrsv{}!O!P!Q!R!S!g!y#P#^#_#pS!gg$sR#^!ZvSO[eg|!]!^!n#c#j#k#l#v$O$Z$j$s$t%OzTRSWhjrsv{}!O!P!Q!R!S!g!y#P#^#_#pQ!rkQ#]!YR#_!ZpYOe|!]!^!n#c#j#k#l#v$O$Z$j$t%OQ!U[S!ig$sQ!mhQ!pjQ#S!PR#U!O!rTORSW[eghjrsv{|}!O!P!Q!R!S!]!^!g!n!y#P#^#_#c#j#k#l#p#v$O$Z$j$s$t%OR#h!cTmPo!sTORSW[eghjrsv{|}!O!P!Q!R!S!]!^!g!n!y#P#^#_#c#j#k#l#p#v$O$Z$j$s$t%OQtR[ySW{!g#^#_Q!wrX!{t!w!|#npaOe|!]!^!n#c#j#k#l#v$O$Z$j$t%O[xSW{!g#^#_Q!W[R!zsR!ffX!df!b!e#gQ#|#dQ$T#mQ$`#}R$o$aQ#d!]Q#m!nQ$P#kQ$Q#lQ$k$ZQ$v$jQ$|$tR%P%OQ#{#dQ$S#mQ$]#|Q$_#}Q$i$TS$n$`$aR$x$o!QTRSW[ghjrsv{}!O!P!Q!R!S!g!y#P#^#_#p$sqUOe|!]!^!n#c#j#k#l#v$O$Z$j$t%OT$b$P$cQ$f$PR$r$cu^O[e|!Z!]!^!n#c#j#k#l#v$O$Z$j$t%OpZOe|!]!^!n#c#j#k#l#v$O$Z$j$t%OQ!V[Q!qjQ#W!RR#Z!S]ySW{!g#^#_qaOe|!]!^!n#c#j#k#l#v$O$Z$j$t%OQeOR!`eQoPR!toQrRR!vrQ!bfR#f!bQ!efQ#g!bT#i!e#gS#v#c$OR$X#vQ!|tQ#n!wT#r!|#nQ#PvQ#p!yT#s#P#pQ$c$PR$p$cY{SW!g#^#_R#Q{S![_!XR#a![TdOeSbOeQ#R|`#b!]!n#k#l$Z$j$t%OQ#e!^U#u#c#v$OR#}#jp_Oe|!]!^!n#c#j#k#l#v$O$Z$j$t%OQ!X[R#`!ZQ!kgR${$srXO[e|!]!^!n#c#j#k#l#v$O$Z$j$t%OQvR[xSW{!g#^#_S!hg$sQ!lhQ!ojQ!yrQ!zsW#Ov!y#P#pQ#S}Q#T!OQ#V!PQ#W!QQ#X!RR#Y!SpVOe|!]!^!n#c#j#k#l#v$O$Z$j$t%O!OwRSWghjrsv{}!O!P!Q!R!S!g!y#P#^#_#p$sR!T[TnPoQ#w#cR$a$O]zSW{!g#^#_", goto: "4l#]PPPPPPPPPPPPPPPPPPPPPPPPPPP#^P#tP$Y%Q#^P&T&mP'l'r(c(fP(lP)j)jPPP)nP)z*dPPP*z+^P+b+h+|P,m-h#t#tP#tP#t#t.e.k.w/P/V/a/g/n/t/z0UPPP0`0d1W2oP3nP3tP3zPPPPPP4O4Ur`Oe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}R!PWu`OWe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}r^Oe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}Q!SWS!ig$rQ!nhQ!rjQ#O}R#Q|xSOWeg!Z![!]!`!o#a#i#j#k#u#}$Y$i$r$s$}vZRSYhjsvxyz{|}!V!Y!h#W#]#oQ!skR!tltTOWe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}T!kg$rtROWe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}vwRSYhjsvxyz{|}!V!Y!h#W#]#oT!hg$rXtRSv!hr`Oe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}WrRSv!hQ!PWR!xsR!gfX!ef!c!f#f!pZORSWYeghjsvxyz{|}!V!Y!Z![!]!`!h!o#W#]#a#i#j#k#o#u#}$Y$i$r$s$}R#g!dTnQpQ#{#bQ$S#lQ$_#|R$n$`Q#b!]Q#l!oQ$O#jQ$P#kQ$j$YQ$u$iQ${$sR%O$}Q#z#bQ$R#lQ$[#{Q$^#|Q$h$SS$m$_$`R$w$nWtRSv!hQ!WYQ#U!VX#X!W#U#Y#mT$a$O$bQ$e$OR$q$buTOWe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}rVOe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}Q!OWQ!qjQ!zyR!}z!qZORSWYeghjsvxyz{|}!V!Y!Z![!]!`!h!o#W#]#a#i#j#k#o#u#}$Y$i$r$s$}zZRSYghjsvxyz{|}!V!Y!h#W#]#o$ru[OWe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}QeOR!ae^!^b!T#^#_#`#t#|R#c!^UvRS!hR!yvQ!cfR#e!cQ!ffQ#f!cT#h!f#fQpQR!vpS#u#a#}R$W#uQ$b$OR$o$bQ!VYR#T!VQ#Y!WQ#m#UT#q#Y#mQ#]!YQ#o#WT#r#]#oTdOeSbOeQ!TWQ#^!ZQ#_![`#`!]!o#j#k$Y$i$s$}Q#d!`U#t#a#u#}R#|#itUOWe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}WrRSv!hQ!YYS!jg$rQ!mhQ!pjQ!xsQ!zxQ!{yQ!|zQ#O{Q#P|Q#R}Q#W!VX#[!Y#W#]#or]Oe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}zwRSYghjsvxyz{|}!V!Y!h#W#]#o$rR!RWQ!lgR$z$rXuRSv!hToQpQ#v#aR$`#}raOe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}R!QW",
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 Comment Program PipeExpr FunctionCall DotGet Number ParenExpr IfExpr keyword ConditionalOp String StringFragment Interpolation EscapeSeq Boolean Regex Dict NamedArg NamedArgPrefix FunctionDef Params NamedParam Null colon CatchExpr keyword Block FinallyExpr keyword keyword Underscore Array ElseIfExpr keyword ElseExpr FunctionCallOrIdentifier BinOp PositionalArg operator WhileExpr keyword 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 Identifier AssignableIdentifier Word IdentifierBeforeDot Do Comment Program PipeExpr operator WhileExpr keyword ConditionalOp ParenExpr IfExpr keyword FunctionCall DotGet Number PositionalArg FunctionDef Params NamedParam NamedArgPrefix String StringFragment Interpolation EscapeSeq Boolean Null colon CatchExpr keyword Block FinallyExpr keyword keyword Underscore NamedArg ElseIfExpr keyword ElseExpr FunctionCallOrIdentifier BinOp Regex Dict Array FunctionCallWithBlock TryExpr keyword Throw keyword CompoundAssign Assign",
maxTerm: 109, maxTerm: 109,
context: trackScope, context: trackScope,
nodeProps: [ nodeProps: [
["closedBy", 48,"end"] ["closedBy", 49,"end"]
], ],
propSources: [highlighting], propSources: [highlighting],
skippedNodes: [0,25], skippedNodes: [0,25],
repeatNodeCount: 11, repeatNodeCount: 11,
tokenData: "C|~R|OX#{XY$jYZ%TZp#{pq$jqs#{st%ntu'tuw#{wx'yxy(Oyz(iz{#{{|)S|}#{}!O+v!O!P#{!P!Q.]!Q![)q![!]6x!]!^%T!^!}#{!}#O7c#O#P9X#P#Q9^#Q#R#{#R#S9w#S#T#{#T#Y,w#Y#Z:b#Z#b,w#b#c?`#c#f,w#f#g@]#g#h,w#h#iAY#i#o,w#o#p#{#p#qC^#q;'S#{;'S;=`$d<%l~#{~O#{~~CwS$QUtSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{S$gP;=`<%l#{^$qUtS!xYOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U%[UtS#[QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^%sWtSOp#{pq&]qt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^&dZiYtSOY&]YZ#{Zt&]tu'Vuw&]wx'Vx#O&]#O#P'V#P;'S&];'S;=`'n<%lO&]Y'[SiYOY'VZ;'S'V;'S;=`'h<%lO'VY'kP;=`<%l'V^'qP;=`<%l&]~'yO#T~~(OO#R~U(VUtS!}QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(pUtS#_QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U)XWtSOt#{uw#{x!Q#{!Q![)q![#O#{#P;'S#{;'S;=`$d<%lO#{U)xYtSnQOt#{uw#{x!O#{!O!P*h!P!Q#{!Q![)q![#O#{#P;'S#{;'S;=`$d<%lO#{U*mWtSOt#{uw#{x!Q#{!Q![+V![#O#{#P;'S#{;'S;=`$d<%lO#{U+^WtSnQOt#{uw#{x!Q#{!Q![+V![#O#{#P;'S#{;'S;=`$d<%lO#{U+{^tSOt#{uw#{x}#{}!O,w!O!Q#{!Q![)q![!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{U,|[tSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{U-yU{QtSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U.bWtSOt#{uw#{x!P#{!P!Q.z!Q#O#{#P;'S#{;'S;=`$d<%lO#{U/P^tSOY/{YZ#{Zt/{tu1Ouw/{wx1Ox!P/{!P!Q#{!Q!}/{!}#O5q#O#P3^#P;'S/{;'S;=`6r<%lO/{U0S^tSxQOY/{YZ#{Zt/{tu1Ouw/{wx1Ox!P/{!P!Q3s!Q!}/{!}#O5q#O#P3^#P;'S/{;'S;=`6r<%lO/{Q1TXxQOY1OZ!P1O!P!Q1p!Q!}1O!}#O2_#O#P3^#P;'S1O;'S;=`3m<%lO1OQ1sP!P!Q1vQ1{UxQ#Z#[1v#]#^1v#a#b1v#g#h1v#i#j1v#m#n1vQ2bVOY2_Z#O2_#O#P2w#P#Q1O#Q;'S2_;'S;=`3W<%lO2_Q2zSOY2_Z;'S2_;'S;=`3W<%lO2_Q3ZP;=`<%l2_Q3aSOY1OZ;'S1O;'S;=`3m<%lO1OQ3pP;=`<%l1OU3xWtSOt#{uw#{x!P#{!P!Q4b!Q#O#{#P;'S#{;'S;=`$d<%lO#{U4ibtSxQOt#{uw#{x#O#{#P#Z#{#Z#[4b#[#]#{#]#^4b#^#a#{#a#b4b#b#g#{#g#h4b#h#i#{#i#j4b#j#m#{#m#n4b#n;'S#{;'S;=`$d<%lO#{U5v[tSOY5qYZ#{Zt5qtu2_uw5qwx2_x#O5q#O#P2w#P#Q/{#Q;'S5q;'S;=`6l<%lO5qU6oP;=`<%l5qU6uP;=`<%l/{U7PUtS!QQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U7jW#ZQtSOt#{uw#{x!_#{!_!`8S!`#O#{#P;'S#{;'S;=`$d<%lO#{U8XVtSOt#{uw#{x#O#{#P#Q8n#Q;'S#{;'S;=`$d<%lO#{U8uU#YQtSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~9^O#U~U9eU#^QtSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U:OUtS!XQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U:g]tSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#U;`#U#o,w#o;'S#{;'S;=`$d<%lO#{U;e^tSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#`,w#`#a<a#a#o,w#o;'S#{;'S;=`$d<%lO#{U<f^tSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#g,w#g#h=b#h#o,w#o;'S#{;'S;=`$d<%lO#{U=g^tSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#X,w#X#Y>c#Y#o,w#o;'S#{;'S;=`$d<%lO#{U>j[wQtSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^?g[#VWtSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^@d[#XWtSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^Aa^#WWtSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#f,w#f#gB]#g#o,w#o;'S#{;'S;=`$d<%lO#{UBb^tSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#i,w#i#j=b#j#o,w#o;'S#{;'S;=`$d<%lO#{UCeU!aQtSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~C|O#a~", tokenData: "C|~R|OX#{XY$jYZ%TZp#{pq$jqs#{st%ntu'tuw#{wx'yxy(Oyz(iz{#{{|)S|}#{}!O+v!O!P#{!P!Q.]!Q![)q![!]6x!]!^%T!^!}#{!}#O7c#O#P9X#P#Q9^#Q#R#{#R#S9w#S#T#{#T#Y,w#Y#Z:b#Z#b,w#b#c?`#c#f,w#f#g@]#g#h,w#h#iAY#i#o,w#o#p#{#p#qC^#q;'S#{;'S;=`$d<%l~#{~O#{~~CwS$QU|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{S$gP;=`<%l#{^$qU|S!xYOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U%[U|S#YQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^%sW|SOp#{pq&]qt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^&dZiY|SOY&]YZ#{Zt&]tu'Vuw&]wx'Vx#O&]#O#P'V#P;'S&];'S;=`'n<%lO&]Y'[SiYOY'VZ;'S'V;'S;=`'h<%lO'VY'kP;=`<%l'V^'qP;=`<%l&]~'yO#T~~(OO#R~U(VU|S!}QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(pU|S#]QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U)XW|SOt#{uw#{x!Q#{!Q![)q![#O#{#P;'S#{;'S;=`$d<%lO#{U)xY|SuQOt#{uw#{x!O#{!O!P*h!P!Q#{!Q![)q![#O#{#P;'S#{;'S;=`$d<%lO#{U*mW|SOt#{uw#{x!Q#{!Q![+V![#O#{#P;'S#{;'S;=`$d<%lO#{U+^W|SuQOt#{uw#{x!Q#{!Q![+V![#O#{#P;'S#{;'S;=`$d<%lO#{U+{^|SOt#{uw#{x}#{}!O,w!O!Q#{!Q![)q![!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{U,|[|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{U-yUzQ|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U.bW|SOt#{uw#{x!P#{!P!Q.z!Q#O#{#P;'S#{;'S;=`$d<%lO#{U/P^|SOY/{YZ#{Zt/{tu1Ouw/{wx1Ox!P/{!P!Q#{!Q!}/{!}#O5q#O#P3^#P;'S/{;'S;=`6r<%lO/{U0S^|S!aQOY/{YZ#{Zt/{tu1Ouw/{wx1Ox!P/{!P!Q3s!Q!}/{!}#O5q#O#P3^#P;'S/{;'S;=`6r<%lO/{Q1TX!aQOY1OZ!P1O!P!Q1p!Q!}1O!}#O2_#O#P3^#P;'S1O;'S;=`3m<%lO1OQ1sP!P!Q1vQ1{U!aQ#Z#[1v#]#^1v#a#b1v#g#h1v#i#j1v#m#n1vQ2bVOY2_Z#O2_#O#P2w#P#Q1O#Q;'S2_;'S;=`3W<%lO2_Q2zSOY2_Z;'S2_;'S;=`3W<%lO2_Q3ZP;=`<%l2_Q3aSOY1OZ;'S1O;'S;=`3m<%lO1OQ3pP;=`<%l1OU3xW|SOt#{uw#{x!P#{!P!Q4b!Q#O#{#P;'S#{;'S;=`$d<%lO#{U4ib|S!aQOt#{uw#{x#O#{#P#Z#{#Z#[4b#[#]#{#]#^4b#^#a#{#a#b4b#b#g#{#g#h4b#h#i#{#i#j4b#j#m#{#m#n4b#n;'S#{;'S;=`$d<%lO#{U5v[|SOY5qYZ#{Zt5qtu2_uw5qwx2_x#O5q#O#P2w#P#Q/{#Q;'S5q;'S;=`6l<%lO5qU6oP;=`<%l5qU6uP;=`<%l/{U7PU|S!RQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U7jW#_Q|SOt#{uw#{x!_#{!_!`8S!`#O#{#P;'S#{;'S;=`$d<%lO#{U8XV|SOt#{uw#{x#O#{#P#Q8n#Q;'S#{;'S;=`$d<%lO#{U8uU#^Q|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~9^O#U~U9eU#`Q|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U:OU|S!YQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U:g]|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#U;`#U#o,w#o;'S#{;'S;=`$d<%lO#{U;e^|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#`,w#`#a<a#a#o,w#o;'S#{;'S;=`$d<%lO#{U<f^|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#g,w#g#h=b#h#o,w#o;'S#{;'S;=`$d<%lO#{U=g^|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#X,w#X#Y>c#Y#o,w#o;'S#{;'S;=`$d<%lO#{U>j[!PQ|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^?g[#VW|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^@d[#XW|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^Aa^#WW|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#f,w#f#gB]#g#o,w#o;'S#{;'S;=`$d<%lO#{UBb^|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#i,w#i#j=b#j#o,w#o;'S#{;'S;=`$d<%lO#{UCeUlQ|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~C|O#a~",
tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO!|~~", 11)], tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO#P~~", 11)],
topRules: {"Program":[0,26]}, topRules: {"Program":[0,26]},
specialized: [{term: 20, get: (value: any, stack: any) => (specializeKeyword(value, stack) << 1), external: specializeKeyword},{term: 20, get: (value: keyof typeof spec_Identifier) => spec_Identifier[value] || -1}], specialized: [{term: 20, get: (value: any, stack: any) => (specializeKeyword(value, stack) << 1), external: specializeKeyword},{term: 20, get: (value: keyof typeof spec_Identifier) => spec_Identifier[value] || -1}],
tokenPrec: 1634 tokenPrec: 1634

View File

@ -98,4 +98,81 @@ describe('pipe expressions', () => {
Identifier double Identifier double
`) `)
}) })
test('string literals can be piped', () => {
expect(`'hey there' | echo`).toMatchTree(`
PipeExpr
String
StringFragment hey there
operator |
FunctionCallOrIdentifier
Identifier echo
`)
})
test('number literals can be piped', () => {
expect(`42 | echo`).toMatchTree(`
PipeExpr
Number 42
operator |
FunctionCallOrIdentifier
Identifier echo`)
expect(`4.22 | echo`).toMatchTree(`
PipeExpr
Number 4.22
operator |
FunctionCallOrIdentifier
Identifier echo`)
})
test('null literals can be piped', () => {
expect(`null | echo`).toMatchTree(`
PipeExpr
Null null
operator |
FunctionCallOrIdentifier
Identifier echo`)
})
test('boolean literals can be piped', () => {
expect(`true | echo`).toMatchTree(`
PipeExpr
Boolean true
operator |
FunctionCallOrIdentifier
Identifier echo`)
})
test('array literals can be piped', () => {
expect(`[1 2 3] | echo`).toMatchTree(`
PipeExpr
Array
Number 1
Number 2
Number 3
operator |
FunctionCallOrIdentifier
Identifier echo
`)
})
test('dict literals can be piped', () => {
expect(`[a=1 b=2 c=3] | echo`).toMatchTree(`
PipeExpr
Dict
NamedArg
NamedArgPrefix a=
Number 1
NamedArg
NamedArgPrefix b=
Number 2
NamedArg
NamedArgPrefix c=
Number 3
operator |
FunctionCallOrIdentifier
Identifier echo
`)
})
}) })

View File

@ -1,37 +1,37 @@
// strings // strings
export const str = { export const str = {
join: (arr: string[], sep: string = ',') => arr.join(sep), join: (arr: string[], sep: string = ',') => arr.join(sep),
split: (str: string, sep: string = ',') => str.split(sep), split: (str: string, sep: string = ',') => String(str ?? '').split(sep),
'to-upper': (str: string) => str.toUpperCase(), 'to-upper': (str: string) => String(str ?? '').toUpperCase(),
'to-lower': (str: string) => str.toLowerCase(), 'to-lower': (str: string) => String(str ?? '').toLowerCase(),
trim: (str: string) => str.trim(), trim: (str: string) => String(str ?? '').trim(),
// predicates // predicates
'starts-with?': (str: string, prefix: string) => str.startsWith(prefix), 'starts-with?': (str: string, prefix: string) => String(str ?? '').startsWith(prefix),
'ends-with?': (str: string, suffix: string) => str.endsWith(suffix), 'ends-with?': (str: string, suffix: string) => String(str ?? '').endsWith(suffix),
'contains?': (str: string, substr: string) => str.includes(substr), 'contains?': (str: string, substr: string) => String(str ?? '').includes(substr),
'empty?': (str: string) => str.length === 0, 'empty?': (str: string) => String(str ?? '').length === 0,
// inspection // inspection
'index-of': (str: string, search: string) => str.indexOf(search), 'index-of': (str: string, search: string) => String(str ?? '').indexOf(search),
'last-index-of': (str: string, search: string) => str.lastIndexOf(search), 'last-index-of': (str: string, search: string) => String(str ?? '').lastIndexOf(search),
// transformations // transformations
replace: (str: string, search: string, replacement: string) => str.replace(search, replacement), replace: (str: string, search: string, replacement: string) => String(str ?? '').replace(search, replacement),
'replace-all': (str: string, search: string, replacement: string) => str.replaceAll(search, replacement), 'replace-all': (str: string, search: string, replacement: string) => String(str ?? '').replaceAll(search, replacement),
slice: (str: string, start: number, end?: number | null) => str.slice(start, end ?? undefined), slice: (str: string, start: number, end?: number | null) => String(str ?? '').slice(start, end ?? undefined),
substring: (str: string, start: number, end?: number | null) => str.substring(start, end ?? undefined), substring: (str: string, start: number, end?: number | null) => String(str ?? '').substring(start, end ?? undefined),
repeat: (str: string, count: number) => { repeat: (str: string, count: number) => {
if (count < 0) throw new Error(`repeat: count must be non-negative, got ${count}`) if (count < 0) throw new Error(`repeat: count must be non-negative, got ${count}`)
if (!Number.isInteger(count)) throw new Error(`repeat: count must be an integer, got ${count}`) if (!Number.isInteger(count)) throw new Error(`repeat: count must be an integer, got ${count}`)
return str.repeat(count) return String(str ?? '').repeat(count)
}, },
'pad-start': (str: string, length: number, pad: string = ' ') => str.padStart(length, pad), 'pad-start': (str: string, length: number, pad: string = ' ') => String(str ?? '').padStart(length, pad),
'pad-end': (str: string, length: number, pad: string = ' ') => str.padEnd(length, pad), 'pad-end': (str: string, length: number, pad: string = ' ') => String(str ?? '').padEnd(length, pad),
lines: (str: string) => str.split('\n'), lines: (str: string) => String(str ?? '').split('\n'),
chars: (str: string) => str.split(''), chars: (str: string) => String(str ?? '').split(''),
// regex // regex
match: (str: string, regex: RegExp) => str.match(regex), match: (str: string, regex: RegExp) => String(str ?? '').match(regex),
'test?': (str: string, regex: RegExp) => regex.test(str), 'test?': (str: string, regex: RegExp) => regex.test(String(str ?? '')),
} }