Merge pull request 'Add comments to the tree' (#24) from comments-in-tree into main

Reviewed-on: #24
This commit is contained in:
probablycorey 2025-11-06 00:19:34 +00:00
commit 7229f4afd0
10 changed files with 156 additions and 93 deletions

View File

@ -75,6 +75,7 @@ export class Compiler {
if (DEBUG) {
const bytecodeString = bytecodeToString(this.bytecode)
console.log(`\n🤖 bytecode:\n----------------\n${bytecodeString}\n\n`)
console.log(`\n🤖 bytecode:\n----------------\n${this.instructions}\n\n`)
}
} catch (error) {
if (error instanceof CompilerError) {
@ -281,13 +282,27 @@ export class Compiler {
const opValue = input.slice(operator.from, operator.to)
switch (opValue) {
case '+=': instructions.push(['ADD']); break
case '-=': instructions.push(['SUB']); break
case '*=': instructions.push(['MUL']); break
case '/=': instructions.push(['DIV']); break
case '%=': instructions.push(['MOD']); break
case '+=':
instructions.push(['ADD'])
break
case '-=':
instructions.push(['SUB'])
break
case '*=':
instructions.push(['MUL'])
break
case '/=':
instructions.push(['DIV'])
break
case '%=':
instructions.push(['MOD'])
break
default:
throw new CompilerError(`Unknown compound operator: ${opValue}`, operator.from, operator.to)
throw new CompilerError(
`Unknown compound operator: ${opValue}`,
operator.from,
operator.to
)
}
// DUP and store (same as regular assignment)
@ -305,10 +320,8 @@ export class Compiler {
}
case terms.FunctionDef: {
const { paramNames, bodyNodes, catchVariable, catchBody, finallyBody } = getFunctionDefParts(
node,
input
)
const { paramNames, bodyNodes, catchVariable, catchBody, finallyBody } =
getFunctionDefParts(node, input)
const instructions: ProgramItem[] = []
const functionLabel: Label = `.func_${this.fnLabelCount++}`
const afterLabel: Label = `.after_${functionLabel}`
@ -331,7 +344,13 @@ export class Compiler {
if (catchVariable || finallyBody) {
// If function has catch or finally, wrap body in try/catch/finally
instructions.push(
...this.#compileTryCatchFinally(compileFunctionBody, catchVariable, catchBody, finallyBody, input)
...this.#compileTryCatchFinally(
compileFunctionBody,
catchVariable,
catchBody,
finallyBody,
input
)
)
} else {
instructions.push(...compileFunctionBody())
@ -414,8 +433,9 @@ export class Compiler {
instructions.push(['JUMP', afterLabel])
instructions.push([`${fnLabel}:`])
instructions.push(
...block.filter(x => x.type.name !== 'keyword')
.map(x => this.#compileNode(x!, input))
...block
.filter((x) => x.type.name !== 'keyword')
.map((x) => this.#compileNode(x!, input))
.flat()
)
instructions.push(['RETURN'])
@ -435,15 +455,16 @@ export class Compiler {
body = [
...body.slice(0, startSlice),
['MAKE_FUNCTION', [], fnLabel],
...body.slice(startSlice)
...body.slice(startSlice),
]
// @ts-ignore
body[body.length - 3]![1] += 1
instructions.push(...body)
} else {
throw new Error(`FunctionCallWithBlock: Expected FunctionCallOrIdentifier or FunctionCall`)
throw new Error(
`FunctionCallWithBlock: Expected FunctionCallOrIdentifier or FunctionCall`
)
}
return instructions
@ -642,7 +663,7 @@ export class Compiler {
// = can be a valid word, and is also valid inside words, so for now we cheat
// and check for arrays that look like `[ = ]` to interpret them as
// empty dicts
if (children.length === 1 && children[0]!.name === 'Word') {
if (children.length === 1 && children[0]!.type.id === terms.Word) {
const child = children[0]!
if (input.slice(child.from, child.to) === '=') {
return [['MAKE_DICT', 0]]
@ -691,6 +712,10 @@ export class Compiler {
return instructions
}
case terms.Comment: {
return [] // ignore comments
}
default:
throw new CompilerError(
`Compiler doesn't know how to handle a "${node.type.name}" node.`,

View File

@ -304,9 +304,12 @@ describe('default params', () => {
})
test.skip('dict default', () => {
expect('make-person = do person=[name=Bob age=60]: person end; make-person')
.toEvaluateTo({ name: 'Bob', age: 60 })
expect('make-person = do person=[name=Bob age=60]: person end; make-person [name=Jon age=21]')
.toEvaluateTo({ name: 'Jon', age: 21 })
expect('make-person = do person=[name=Bob age=60]: person end; make-person').toEvaluateTo({
name: 'Bob',
age: 60,
})
expect(
'make-person = do person=[name=Bob age=60]: person end; make-person [name=Jon age=21]'
).toEvaluateTo({ name: 'Jon', age: 21 })
})
})

View File

@ -66,8 +66,8 @@ describe('array literals', () => {
})
test('comments within arrays', () => {
expect(`[1 # first
2 # second
expect(`[1
2
]`).toEvaluateTo([1, 2])
})

View File

@ -22,7 +22,8 @@ export const getAllChildren = (node: SyntaxNode): SyntaxNode[] => {
children.push(child)
child = child.nextSibling
}
return children
return children.filter((n) => n.type.id !== terms.Comment)
}
export const getBinaryParts = (node: SyntaxNode) => {
@ -50,13 +51,15 @@ export const getAssignmentParts = (node: SyntaxNode) => {
// array destructuring
if (left && left.type.id === terms.Array) {
const identifiers = getAllChildren(left).filter(child => child.type.id === terms.Identifier)
const identifiers = getAllChildren(left).filter((child) => child.type.id === terms.Identifier)
return { arrayPattern: identifiers, right }
}
if (!left || left.type.id !== terms.AssignableIdentifier) {
throw new CompilerError(
`Assign left child must be an AssignableIdentifier or Array, got ${left ? left.type.name : 'none'}`,
`Assign left child must be an AssignableIdentifier or Array, got ${
left ? left.type.name : 'none'
}`,
node.from,
node.to
)
@ -71,7 +74,9 @@ export const getCompoundAssignmentParts = (node: SyntaxNode) => {
if (!left || left.type.id !== terms.AssignableIdentifier) {
throw new CompilerError(
`CompoundAssign left child must be an AssignableIdentifier, got ${left ? left.type.name : 'none'}`,
`CompoundAssign left child must be an AssignableIdentifier, got ${
left ? left.type.name : 'none'
}`,
node.from,
node.to
)

View File

@ -2,7 +2,7 @@
@context trackScope from "./scopeTracker"
@skip { space | comment }
@skip { space | Comment }
@top Program { item* }
@ -18,7 +18,7 @@
newlineOrSemicolon { "\n" | ";" }
eof { @eof }
space { " " | "\t" }
comment { "#" ![\n]* }
Comment { "#" " " ![\n]* }
leftParen { "(" }
rightParen { ")" }
colon[closedBy="end", @name="colon"] { ":" }

View File

@ -24,42 +24,43 @@ export const
Word = 22,
IdentifierBeforeDot = 23,
Do = 24,
Program = 25,
PipeExpr = 26,
FunctionCall = 27,
DotGet = 28,
Number = 29,
ParenExpr = 30,
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
Comment = 25,
Program = 26,
PipeExpr = 27,
FunctionCall = 28,
DotGet = 29,
Number = 30,
ParenExpr = 31,
IfExpr = 32,
keyword = 70,
ConditionalOp = 34,
String = 35,
StringFragment = 36,
Interpolation = 37,
EscapeSeq = 38,
Boolean = 39,
Regex = 40,
Dict = 41,
NamedArg = 42,
NamedArgPrefix = 43,
FunctionDef = 44,
Params = 45,
NamedParam = 46,
Null = 47,
colon = 48,
CatchExpr = 49,
Block = 51,
FinallyExpr = 52,
Underscore = 55,
Array = 56,
ElseIfExpr = 57,
ElseExpr = 59,
FunctionCallOrIdentifier = 60,
BinOp = 61,
PositionalArg = 62,
WhileExpr = 64,
FunctionCallWithBlock = 66,
TryExpr = 67,
Throw = 69,
CompoundAssign = 71,
Assign = 72

View File

@ -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,if:64, null:92, catch:98, finally:104, end:106, else:114, while:128, try:134, throw:138}
const spec_Identifier = {__proto__:null,if:66, null:94, catch:100, finally:106, end:108, else:116, while:130, try:136, throw:140}
export const parser = LRParser.deserialize({
version: 14,
states: "9[QYQbOOO!dOSO'#DOOOQa'#DU'#DUO#mQbO'#DeO%RQcO'#E^OOQa'#E^'#E^O&XQcO'#E^O'ZQcO'#E]O'qQcO'#E]O)^QRO'#C}O*mQcO'#EWO*wQcO'#EWO+XQbO'#CzO,SOpO'#CxOOQ`'#EX'#EXO,XQbO'#EWO,cQRO'#DtOOQ`'#EW'#EWO,wQQO'#EVOOQ`'#EV'#EVOOQ`'#Dv'#DvQYQbOOO-PQbO'#DXO-[QbO'#C{O.PQbO'#DmO.tQQO'#DpO.PQbO'#DrO.yQbO'#DQO/RQWO'#DROOOO'#E`'#E`OOOO'#Dw'#DwO/gOSO,59jOOQa,59j,59jOOQ`'#Dx'#DxO/uQbO,5:PO/|QbO'#DVO0WQQO,59pOOQa,5:P,5:PO0cQbO,5:POOQa'#E]'#E]OOQ`'#Dk'#DkOOQ`'#El'#ElOOQ`'#EP'#EPO0mQbO,59cO1gQbO,5:aO.PQbO,59iO.PQbO,59iO.PQbO,59iO.PQbO,5:UO.PQbO,5:UO.PQbO,5:UO1wQRO,59fO2OQRO,59fO2ZQRO,59fO2UQQO,59fO2lQQO,59fO2tObO,59dO3PQbO'#EQO3[QbO,59bO3vQbO,5:ZO1gQbO,5:`OOQ`,5:q,5:qOOQ`-E7t-E7tOOQ`'#Dy'#DyO4ZQbO'#DYO4fQbO'#DZOOQO'#Dz'#DzO4^QQO'#DYO4tQQO,59sO4yQcO'#E]O6_QRO'#E[O6fQRO'#E[OOQO'#E['#E[O6qQQO,59gO6vQRO,5:XO6}QRO,5:XO3vQbO,5:[O7YQcO,5:^O8UQcO,5:^O8`QcO,5:^OOOO,59l,59lOOOO,59m,59mOOOO-E7u-E7uOOQa1G/U1G/UOOQ`-E7v-E7vO8pQQO1G/[OOQa1G/k1G/kO8{QbO1G/kOOQ`,59q,59qOOQO'#D|'#D|O8pQQO1G/[OOQa1G/[1G/[OOQ`'#D}'#D}O8{QbO1G/kOOQ`-E7}-E7}OOQ`1G/{1G/{OOQa1G/T1G/TO:WQcO1G/TO:_QcO1G/TO:fQcO1G/TOOQa1G/p1G/pO;_QcO1G/pO;iQcO1G/pO;sQcO1G/pOOQa1G/Q1G/QOOQa1G/O1G/OO<hQbO'#DiO=_QbO'#CwOOQ`,5:l,5:lOOQ`-E8O-E8OOOQ`'#D`'#D`O=lQbO'#D`O>]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<<Hb<<HbOOQa<<Hq<<HqOOQ`,5:g,5:gOOQ`-E7y-E7yOBgQQO,59xO3vQbO,59{OOQ`<<H{<<H{OBlQbO<<H{OOQ`<<He<<HeOBqQbO<<HeOBvQbO<<HeOCOQbO<<HeOOQ`'#EO'#EOOCZQbO<<HXOCcQbO'#DhOOQ`<<HX<<HXOCkQbO<<HXOOQ`<<Hy<<HyOOQ`<<H|<<H|OCpQbO<<H|O3vQbO1G/dOOQ`1G/g1G/gOOQ`AN>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`<<Hr<<Hr",
stateData: "Dk~O!wOS!xOS~OdWOe`OfTOg]OhfOmTOpgOvTOwTO!OTO!bhO!eiO!gjO!}[O#RPO#YQO#ZRO#[cO~OsmO#RpO#TkO#UlO~OdwOfTOg]OmTOvTOwTOzsO!OTO!}[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!R#QX!U#QX!V#QX!Z#QX~OdwOfTOg]OhfOmTOvTOwTOzsO!OTO!WxO!}[O#RPO#YQO#ZRO#_#QX!P#QX~P#tOV|O~P#tOP#PXQ#PXR#PXS#PXT#PXU#PXW#PXX#PXY#PXZ#PX[#PX]#PX^#PX~O#[!zX#a!zX!R!zX!U!zX!V!zX!Z!zX~P&`OdwOfTOg]OhfOmTOvTOwTOzsO!OTO!WxO!}[O#RPO#YQO#ZRO!P!]X!`!]X#[!]X#a!]X#_!]X!R!]X!U!]X!V!]X!Z!]X~P&`OP!ROQ!ROR!SOS!SOT!OOU!POW}OX}OY}OZ}O[}O]}O^!QO~O#[!zX#a!zX!R!zX!U!zX!V!zX!Z!zX~OT!OOU!PO~P*XOP!ROQ!ROR!SOS!SO~P*XOdWOfTOg]OhfOmTOpgOvTOwTO!OTO!}[O#RPO#YQO#ZRO~O!|!YO~O!P!]O!`!ZO~P*XOV|O_!^O`!^Oa!^Ob!^Oc!^O~O#[!_O#a!_O~Od!aOz!cO!P|P~Od!gOfTOg]OmTOvTOwTO!OTO!}[O#RPO#YQO#ZRO~OdwOfTOg]OmTOvTOwTO!OTO!}[O#RPO#YQO#ZRO~O!P!nO~Od!rO!}[O~O#R!sO#T!sO#U!sO#V!sO#W!sO#X!sO~OsmO#R!uO#TkO#UlO~O#^!xO~P!rOhfO!W!zO~P.POzsO#[!{O#^!}O~O#[#OO#^!xO~P.POhfOzsO!WxO!Pka!`ka#[ka#aka#_ka!Rka!Uka!Vka!Zka~P.POe`O!bhO!eiO!gjO~P+XO#_#[O~P&`OT!OOU!PO#_#[O~OP!ROQ!ROR!SOS!SO#_#[O~O!`!ZO#_#[O~Od#]Om#]O!}[O~Od#^Og]O!}[O~O!`!ZO#[ja#aja#_ja!Rja!Uja!Vja!Zja~Oe`O!bhO!eiO!gjO#[#cO~P+XOd!aOz!cO!P|X~Om#hOv#hO!O#hO#RPO~O!P#jO~OhfOzsO!WxOT#PXU#PXW#PXX#PXY#PXZ#PX[#PX]#PX!P#PX~P.POT!OOU!POW}OX}OY}OZ}O[}O]}O~O!P#OX~P5sOT!OOU!PO!P#OX~O!P#kO~O!P#lO~P5sOT!OOU!PO!P#lO~O#[!fa#a!fa!R!fa!U!fa!V!fa!Z!fa~P)^O#[!fa#a!fa!R!fa!U!fa!V!fa!Z!fa~OT!OOU!PO~P7pOP!ROQ!ROR!SOS!SO~P7pOzsO#[!{O#^#oO~O#[#OO#^#qO~P.POW}OX}OY}OZ}O[}O]}OTqi#[qi#aqi#_qi!Pqi!Rqi!Uqi!Vqi!Zqi~OU!PO~P9VOU!PO~P9iOUqi~P9VO^!QOR!^iS!^i#[!^i#a!^i#_!^i!R!^i!U!^i!V!^i!Z!^i~OP!^iQ!^i~P:mOP!ROQ!RO~P:mOP!ROQ!ROR!^iS!^i#[!^i#a!^i#_!^i!R!^i!U!^i!V!^i!Z!^i~OhfOzsO!WxO!`!]X#[!]X#a!]X#_!]X!R!]X!U!]X!V!]X!Z!]X~P.POhfOzsO!WxO~P.POe`O!bhO!eiO!gjO#[#tO!R#]P!U#]P!V#]P!Z#]P~P+XO!R#xO!U#yO!V#zO~Oz!cO!P|a~Oe`O!bhO!eiO!gjO#[$OO~P+XO!R#xO!U#yO!V$RO~OzsO#[!{O#^$UO~O#[#OO#^$VO~P.PO#[$WO~Oe`O!bhO!eiO!gjO#[#tO!R#]X!U#]X!V#]X!Z#]X~P+XOd$YO~O!P$ZO~O!V$[O~O!U#yO!V$[O~O!R#xO!U#yO!V$^O~Oe`O!bhO!eiO!gjO#[#tO!R#]P!U#]P!V#]P~P+XO!V$eO!Z$dO~O!V$gO~O!V$hO~O!U#yO!V$hO~O!P$jO~O!V$lO~O!V$mO~O!U#yO!V$mO~O!R#xO!U#yO!V$mO~O!V$qO!Z$dO~Op$sO!P$tO~O!V$qO~O!V$uO~O!V$wO~O!U#yO!V$wO~O!V$zO~O!V$}O~Op$sO~O!P%OO~Omw~",
goto: "4x#aPPPPPPPPPPPPPPPPPPPPPPPPPP#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/y0T0Z0ePPPP0l0p1^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#^#_",
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 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",
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",
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~",
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#^#_",
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",
maxTerm: 109,
context: trackScope,
nodeProps: [
["closedBy", 47,"end"]
["closedBy", 48,"end"]
],
propSources: [highlighting],
skippedNodes: [0],
skippedNodes: [0,25],
repeatNodeCount: 11,
tokenData: "C_~R|OX#{XY$jYZ%TZp#{pq$jqs#{st%ntu'Vuw#{wx'[xy'ayz'zz{#{{|(e|}#{}!O+X!O!P#{!P!Q-n!Q![)S![!]6Z!]!^%T!^!}#{!}#O6t#O#P8j#P#Q8o#Q#R#{#R#S9Y#S#T#{#T#Y,Y#Y#Z9s#Z#b,Y#b#c>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$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#h<s#h#o,Y#o;'S#{;'S;=`$d<%lO#{U<x^sSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#X,Y#X#Y=t#Y#o,Y#o;'S#{;'S;=`$d<%lO#{U={[vQsSOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{^>x[#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<s#j#o,Y#o;'S#{;'S;=`$d<%lO#{UBvU!`QsSOt#{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$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~",
tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO!|~~", 11)],
topRules: {"Program":[0,25]},
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}],
tokenPrec: 1634
})

View File

@ -48,7 +48,6 @@ describe('Identifier', () => {
FunctionCallOrIdentifier
Identifier even?`)
})
})
describe('Unicode Symbol Support', () => {
@ -637,26 +636,51 @@ describe('DotGet whitespace sensitivity', () => {
})
describe('Comments', () => {
test('are barely there', () => {
expect(`x = 5 # one banana\ny = 2 # two bananas`).toMatchTree(`
test('are greedy', () => {
expect(`
x = 5 # one banana
y = 2 # two bananas`).toMatchTree(`
Assign
AssignableIdentifier x
Eq =
Number 5
Comment # one banana
Assign
AssignableIdentifier y
Eq =
Number 2`)
Number 2
Comment # two bananas`)
expect('# some comment\nbasename = 5 # very astute\n basename / prop\n# good info').toMatchTree(`
expect(`
# some comment
basename = 5 # very astute
basename / prop
# good info`).toMatchTree(`
Comment # some comment
Assign
AssignableIdentifier basename
Eq =
Number 5
Comment # very astute
BinOp
Identifier basename
Slash /
Identifier prop`)
Identifier prop
Comment # good info`)
})
test('words with # are not considered comments', () => {
expect('find #hashtag-file.txt').toMatchTree(`
FunctionCall
Identifier find
PositionalArg
Word #hashtag-file.txt`)
})
test('hastags in strings are not comments', () => {
expect("'this is not a #comment'").toMatchTree(`
String
StringFragment this is not a #comment`)
})
})
@ -697,7 +721,6 @@ describe('Array destructuring', () => {
Number 2`)
})
test('works with dotget', () => {
expect('[ a ] = [ [1 2 3] ]; a.1').toMatchTree(`
Assign

View File

@ -150,8 +150,11 @@ describe('array literals', () => {
2 # second
]`).toMatchTree(`
Array
Comment # something...
Number 1
Comment # first
Number 2
Comment # second
`)
})
@ -397,12 +400,15 @@ c=3]`).toMatchTree(`
c=3
]`).toMatchTree(`
Dict
Comment # something...
NamedArg
NamedArgPrefix a=
Number 1
Comment # first
NamedArg
NamedArgPrefix b=
Number 2
Comment # second
NamedArg
NamedArgPrefix c=
Number 3

Binary file not shown.