Compare commits

..

No commits in common. "d306d58b2f49b9da635be215123e4beb9a2f0e70" and "66671970e0ce869b484aaad77a1707fcd77a16d3" have entirely different histories.

12 changed files with 93 additions and 137 deletions

View File

@ -63,26 +63,26 @@ describe('compiler', () => {
})
test('function', () => {
expect(`do a b: a + b end`).toEvaluateTo(Function)
expect(`fn a b: a + b end`).toEvaluateTo(Function)
})
test('function call', () => {
expect(`add = do a b: a + b end; add 2 9`).toEvaluateTo(11)
expect(`add = fn a b: a + b end; add 2 9`).toEvaluateTo(11)
})
test('function call with named args', () => {
expect(`minus = do a b: a - b end; minus b=2 a=9`).toEvaluateTo(7)
expect(`minus = fn a b: a - b end; minus b=2 a=9`).toEvaluateTo(7)
})
test('function call with named and positional args', () => {
expect(`minus = do a b: a - b end; minus b=2 9`).toEvaluateTo(7)
expect(`minus = do a b: a - b end; minus 90 b=20`).toEvaluateTo(70)
expect(`minus = do a b: a - b end; minus a=900 200`).toEvaluateTo(700)
expect(`minus = do a b: a - b end; minus 2000 a=9000`).toEvaluateTo(7000)
expect(`minus = fn a b: a - b end; minus b=2 9`).toEvaluateTo(7)
expect(`minus = fn a b: a - b end; minus 90 b=20`).toEvaluateTo(70)
expect(`minus = fn a b: a - b end; minus a=900 200`).toEvaluateTo(700)
expect(`minus = fn a b: a - b end; minus 2000 a=9000`).toEvaluateTo(7000)
})
test('function call with no args', () => {
expect(`bloop = do: 'bloop' end; bloop`).toEvaluateTo('bloop')
expect(`bloop = fn: 'bloop' end; bloop`).toEvaluateTo('bloop')
})
test('simple conditionals', () => {
@ -150,7 +150,7 @@ describe('errors', () => {
describe('multiline tests', () => {
test('multiline function', () => {
expect(`
add = do a b:
add = fn a b:
result = a + b
result
end

View File

@ -3,7 +3,7 @@ import { describe, test, expect } from 'bun:test'
describe('pipe expressions', () => {
test('simple pipe passes result as first argument', () => {
const code = `
double = do x: x * 2 end
double = fn x: x * 2 end
double 2 | double`
expect(code).toEvaluateTo(8)
@ -11,9 +11,9 @@ describe('pipe expressions', () => {
test('pipe chain with three stages', () => {
const code = `
add-one = do x: x + 1 end
double = do x: x * 2 end
minus-point-one = do x: x - 0.1 end
add-one = fn x: x + 1 end
double = fn x: x * 2 end
minus-point-one = fn x: x - 0.1 end
add-one 3 | double | minus-point-one`
// 4 8 7.9
expect(code).toEvaluateTo(7.9)
@ -21,8 +21,8 @@ describe('pipe expressions', () => {
test('pipe with function that has additional arguments', () => {
const code = `
multiply = do a b: a * b end
get-five = do: 5 end
multiply = fn a b: a * b end
get-five = fn: 5 end
get-five | multiply 3`
expect(code).toEvaluateTo(15)
@ -31,7 +31,7 @@ describe('pipe expressions', () => {
test('pipe with bare identifier', () => {
const code = `
get-value = 42
process = do x: x + 10 end
process = fn x: x + 10 end
get-value | process`
expect(code).toEvaluateTo(52)
@ -39,7 +39,7 @@ describe('pipe expressions', () => {
test('pipe in assignment', () => {
const code = `
add-ten = do x: x + 10 end
add-ten = fn x: x + 10 end
result = add-ten 5 | add-ten
result`
@ -49,23 +49,23 @@ describe('pipe expressions', () => {
test('pipe with named underscore arg', () => {
expect(`
divide = do a b: a / b end
get-ten = do: 10 end
divide = fn a b: a / b end
get-ten = fn: 10 end
get-ten | divide 2 b=_`).toEvaluateTo(0.2)
expect(`
divide = do a b: a / b end
get-ten = do: 10 end
divide = fn a b: a / b end
get-ten = fn: 10 end
get-ten | divide b=_ 2`).toEvaluateTo(0.2)
expect(`
divide = do a b: a / b end
get-ten = do: 10 end
divide = fn a b: a / b end
get-ten = fn: 10 end
get-ten | divide 2 a=_`).toEvaluateTo(5)
expect(`
divide = do a b: a / b end
get-ten = do: 10 end
divide = fn a b: a / b end
get-ten = fn: 10 end
get-ten | divide a=_ 2`).toEvaluateTo(5)
})
@ -74,8 +74,8 @@ describe('pipe expressions', () => {
// handling logic works correctly when there are multiple pipe stages
// in a single expression.
expect(`
sub = do a b: a - b end
div = do a b: a / b end
sub = fn a b: a - b end
div = fn a b: a / b end
sub 3 1 | div (sub 110 9 | sub 1) _ | div 5`).toEvaluateTo(10)
})
})

View File

@ -245,7 +245,7 @@ const commandShapes: CommandShape[] = [
] as const
let commandSource = () => commandShapes
export const setCommandSource = (do: () => CommandShape[]) => {
export const setCommandSource = (fn: () => CommandShape[]) => {
commandSource = fn
}

View File

@ -21,9 +21,14 @@
leftParen { "(" }
rightParen { ")" }
colon[closedBy="end", @name="colon"] { ":" }
end[openedBy="colon", @name="end"] { "end" }
Underscore { "_" }
Null { "null" }
Regex { "//" (![/\\\n[] | "\\" ![\n] | "[" (![\n\\\]] | "\\" ![\n])* "]")+ ("//" $[gimsuy]*)? } // Stolen from the lezer JavaScript grammar
Fn[@name=keyword] { "fn" }
"if" [@name=keyword]
"elsif" [@name=keyword]
"else" [@name=keyword]
"|"[@name=operator]
}
@ -93,11 +98,11 @@ FunctionDef {
}
singleLineFunctionDef {
@specialize[@name=keyword]<Identifier, "do"> Params colon consumeToTerminator @specialize[@name=keyword]<Identifier, "end">
Fn Params colon consumeToTerminator end
}
multilineFunctionDef {
@specialize[@name=keyword]<Identifier, "do"> Params colon newlineOrSemicolon block @specialize[@name=keyword]<Identifier, "end">
Fn Params colon newlineOrSemicolon block end
}
IfExpr {
@ -105,19 +110,19 @@ IfExpr {
}
singleLineIf {
@specialize[@name=keyword]<Identifier, "if"> (ConditionalOp | expression) colon ThenBlock { consumeToTerminator }
"if" (ConditionalOp | expression) colon ThenBlock { consumeToTerminator }
}
multilineIf {
@specialize[@name=keyword]<Identifier, "if"> (ConditionalOp | expression) colon newlineOrSemicolon ThenBlock ElsifExpr* ElseExpr? @specialize[@name=keyword]<Identifier, "end">
"if" (ConditionalOp | expression) colon newlineOrSemicolon ThenBlock ElsifExpr* ElseExpr? end
}
ElsifExpr {
@specialize[@name=keyword]<Identifier, "elsif"> (ConditionalOp | expression) colon newlineOrSemicolon ThenBlock
"elsif" (ConditionalOp | expression) colon newlineOrSemicolon ThenBlock
}
ElseExpr {
@specialize[@name=keyword]<Identifier, "else"> colon newlineOrSemicolon ThenBlock
"else" colon newlineOrSemicolon ThenBlock
}
ThenBlock {
@ -158,14 +163,9 @@ expression {
expressionWithoutIdentifier | DotGet | Identifier
}
@local tokens {
dot { "." }
}
@skip {} {
DotGet {
IdentifierBeforeDot dot Identifier
IdentifierBeforeDot "." Identifier
}
String { "'" stringContent* "'" }

View File

@ -34,9 +34,10 @@ export const
Null = 32,
DotGet = 33,
FunctionDef = 34,
keyword = 50,
Fn = 35,
Params = 36,
colon = 37,
end = 38,
Underscore = 39,
NamedArg = 40,
NamedArgPrefix = 41,

View File

@ -1,27 +1,26 @@
// This file was generated by lezer-generator. You probably shouldn't edit it.
import {LRParser, LocalTokenGroup} from "@lezer/lr"
import {LRParser} from "@lezer/lr"
import {operatorTokenizer} from "./operatorTokenizer"
import {tokenizer} from "./tokenizer"
import {trackScope} from "./scopeTracker"
import {highlighting} from "./highlight"
const spec_Identifier = {__proto__:null,do:70, end:76, if:88, elsif:96, else:100}
export const parser = LRParser.deserialize({
version: 14,
states: ".jQVQbOOO#XQcO'#CrO$RQRO'#CsO$aQcO'#DmO$xQbO'#CqO%gOSO'#CuOOQa'#Dq'#DqO%uOpO'#C}O%zQcO'#DpO&cQbO'#D|OOQ`'#DO'#DOOOQ`'#Dn'#DnO&kQbO'#DmO&yQbO'#EQOOQ`'#DX'#DXO'hQRO'#DaOOQ`'#Dm'#DmO'mQQO'#DlOOQ`'#Dl'#DlOOQ`'#Db'#DbQVQbOOOOQa'#Dp'#DpOOQ`'#Cp'#CpO'uQbO'#DUOOQ`'#Do'#DoOOQ`'#Dc'#DcO(PQbO,59ZO&yQbO,59_O&yQbO,59_O)XQRO'#CsO)iQRO,59]O)zQRO,59]O)uQQO,59]O*uQQO,59]O*}QbO'#CwO+VQWO'#CxOOOO'#Du'#DuOOOO'#Dd'#DdO+kOSO,59aOOQa,59a,59aO+yO`O,59iOOQ`'#De'#DeO,OQbO'#DQO,WQQO,5:hO,]QbO'#DgO,bQbO,59YO,sQRO,5:lO,zQQO,5:lO-PQbO,59{OOQ`,5:W,5:WOOQ`-E7`-E7`OOQ`,59p,59pOOQ`-E7a-E7aOOQa1G.y1G.yO-^QcO1G.yO&yQbO,59`O&yQbO,59`OOQa1G.w1G.wOOOO,59c,59cOOOO,59d,59dOOOO-E7b-E7bOOQa1G.{1G.{OOQa1G/T1G/TOOQ`-E7c-E7cO-xQbO1G0SO!QQbO'#CrOOQ`,5:R,5:ROOQ`-E7e-E7eO.YQbO1G0WOOQ`1G/g1G/gOOQO1G.z1G.zO.jQRO1G.zO.tQbO7+%nO.yQbO7+%oOOQ`'#DZ'#DZOOQ`7+%r7+%rO/ZQbO7+%sOOQ`<<IY<<IYO/qQQO'#DfO/vQbO'#EPO0^QbO<<IZOOQ`'#D['#D[O0cQbO<<I_OOQ`,5:Q,5:QOOQ`-E7d-E7dOOQ`AN>uAN>uO&yQbO'#D]OOQ`'#Dh'#DhO0nQbOAN>yO0yQQO'#D_OOQ`AN>yAN>yO1OQbOAN>yO1TQRO,59wO1[QQO,59wOOQ`-E7f-E7fOOQ`G24eG24eO1aQbOG24eO1fQQO,59yO1kQQO1G/cOOQ`LD*PLD*PO.yQbO1G/eO/ZQbO7+$}OOQ`7+%P7+%POOQ`<<Hi<<Hi",
states: ".jQVQrOOO#XQuO'#CrO$RQRO'#CsO$aQRO'#DmO$xQrO'#CqO%gOWO'#CuOOQq'#Dq'#DqO%uOQO'#C}O%zQRO'#DpO&cQrO'#D|OOQp'#DO'#DOOOQO'#Dn'#DnO&kQQO'#DmO&yQrO'#EQOOQO'#DX'#DXO'hQRO'#DaOOQO'#Dm'#DmO'mQQO'#DlOOQp'#Dl'#DlOOQp'#Db'#DbQVQrOOOOQq'#Dp'#DpOOQp'#Cp'#CpO'uQrO'#DUOOQp'#Do'#DoOOQp'#Dc'#DcO(PQtO,59ZO&yQrO,59_O&yQrO,59_O)XQRO'#CsO)iQRO,59]O)zQRO,59]O)uQQO,59]O*uQQO,59]O*}QrO'#CwO+VQ`O'#CxOOOO'#Du'#DuOOOO'#Dd'#DdO+kOWO,59aOOQq,59a,59aO+yOpO,59iOOQp'#De'#DeO,OQrO'#DQO,WQQO,5:hO,]QrO'#DgO,bQQO,59YO,sQRO,5:lO,zQQO,5:lO-PQrO,59{OOQp,5:W,5:WOOQp-E7`-E7`OOQp,59p,59pOOQp-E7a-E7aOOQP1G.y1G.yO-^QRO1G.yO&yQrO,59`O&yQrO,59`OOQq1G.w1G.wOOOO,59c,59cOOOO,59d,59dOOOO-E7b-E7bOOQq1G.{1G.{OOQq1G/T1G/TOOQp-E7c-E7cO-xQrO1G0SO!QQtO'#CrOOQO,5:R,5:ROOQO-E7e-E7eO.YQrO1G0WOOQO1G/g1G/gOOQO1G.z1G.zO.jQRO1G.zO.tQQO7+%nO.yQrO7+%oOOQO'#DZ'#DZOOQO7+%r7+%rO/ZQrO7+%sOOQp<<IY<<IYO/qQQO'#DfO/vQrO'#EPO0^QQO<<IZOOQO'#D['#D[O0cQQO<<I_OOQp,5:Q,5:QOOQp-E7d-E7dOOQpAN>uAN>uO&yQrO'#D]OOQO'#Dh'#DhO0nQQOAN>yO0yQQO'#D_OOQOAN>yAN>yO1OQQOAN>yO1TQRO,59wO1[QQO,59wOOQO-E7f-E7fOOQOG24eG24eO1aQQOG24eO1fQQO,59yO1kQQO1G/cOOQOLD*PLD*PO.yQrO1G/eO/ZQrO7+$}OOQO7+%P7+%POOQO<<Hi<<Hi",
stateData: "1s~O!_OS~O]PO^_O_UO`VOmUOnUOoUOpUOsXO|]O!fSO!hTO!rbO~O]eO_UO`VOmUOnUOoUOpUOsXOwfOygO!fSO!hTOzfX!rfX!vfX!gfXvfX~OP!dXQ!dXR!dXS!dXT!dXU!dXV!dXW!dXX!dXY!dXZ!dX[!dX~P!QOPkOQkORlOSlO~OPkOQkORlOSlO!r!aX!v!aXv!aX~O]PO_UO`VOmUOnUOoUOpUO!fSO!hTO~OjtO!hwO!jrO!ksO~O!oxO~OP!dXQ!dXR!dXS!dX!r!aX!v!aXv!aX~O^yOutP~Oz|O!r!aX!v!aXv!aX~O]eO_UO`VOmUOnUOoUOpUO!fSO!hTO~OV!QO~O!r!RO!v!RO~OsXOw!TO~P&yOsXOwfOygOzca!rca!vca!gcavca~P&yOT!YOU!YOV!XOW!XOX!XOY!XOZ!XO[!XO~OPkOQkORlOSlO~P(mOPkOQkORlOSlO!g!ZO~O!g!ZOP!dXQ!dXR!dXS!dXT!dXU!dXV!dXW!dXX!dXY!dXZ!dX[!dX~Oz|O!g!ZO~O]![O!fSO~O!h!]O!j!]O!k!]O!l!]O!m!]O!n!]O~OjtO!h!_O!jrO!ksO~O]!`O~O^yOutX~Ou!bO~O]!cO~Oz|O!rba!vba!gbavba~Ou!fO~P(mOu!fO~O^_OsXO|]O~P$xOPkOQkORgiSgi!rgi!vgi!ggivgi~O^_OsXO|]O!r!kO~P$xO^_OsXO|]O!r!nO~P$xO!ghiuhi~P(mOv!oO~O^_OsXO|]Ov!sP~P$xO^_OsXO|]Ov!sP!Q!sP!S!sP~P$xO!r!uO~O^_OsXO|]Ov!sX!Q!sX!S!sX~P$xOv!wO~Ov!|O!Q!xO!S!{O~Ov#RO!Q!xO!S!{O~Ou#TO~Ov#RO~Ou#UO~P(mOu#UO~Ov#VO~O!r#WO~O!r#XO~Omo~",
goto: "+m!vPPPPPPPPPPPPPPPPPP!w#W#f#k#W$V$l$xP%a%aPPPP%e&OP&dPPP#fPP&gP&s&v'PP'TP&g'Z'a'h'n't'}(UPPP([(`(t)W)]*WPPP*sPPPPPP*w*wP+X+a+ad`Od!Q!b!f!k!n!q#W#XRpSiZOSd|!Q!b!f!k!n!q#W#XVhPj!czUOPS]dgjkl!Q!X!Y!b!c!f!k!n!q!x#W#XR![rdROd!Q!b!f!k!n!q#W#XQnSQ!VkR!WlQpSQ!P]Q!h!YR#P!x{UOPS]dgjkl!Q!X!Y!b!c!f!k!n!q!x#W#XTtTvdWOd!Q!b!f!k!n!q#W#XgePS]gjkl!X!Y!c!xd`Od!Q!b!f!k!n!q#W#XUfPj!cR!TgR{Xe`Od!Q!b!f!k!n!q#W#XR!m!fQ!t!nQ#Y#WR#Z#XT!y!t!zQ!}!tR#S!zQdOR!SdSjP!cR!UjQvTR!^vQzXR!azW!q!k!n#W#XR!v!qS}[qR!e}Q!z!tR#Q!zTcOdSaOdQ!g!QQ!j!bQ!l!fZ!p!k!n!q#W#Xd[Od!Q!b!f!k!n!q#W#XQqSR!d|ViPj!cdQOd!Q!b!f!k!n!q#W#XUfPj!cQmSQ!O]Q!TgQ!VkQ!WlQ!h!XQ!i!YR#O!xdWOd!Q!b!f!k!n!q#W#XdeP]gjkl!X!Y!c!xRoSTuTvmYOPdgj!Q!b!c!f!k!n!q#W#XQ!r!kV!s!n#W#Xe^Od!Q!b!f!k!n!q#W#X",
nodeNames: "⚠ Star Slash Plus Minus And Or Eq Neq Lt Lte Gt Gte Identifier AssignableIdentifier Word IdentifierBeforeDot Program PipeExpr FunctionCall PositionalArg ParenExpr FunctionCallOrIdentifier BinOp ConditionalOp String StringFragment Interpolation EscapeSeq Number Boolean Regex Null DotGet FunctionDef keyword Params colon keyword Underscore NamedArg NamedArgPrefix operator IfExpr keyword ThenBlock ThenBlock ElsifExpr keyword ElseExpr keyword Assign",
nodeNames: "⚠ Star Slash Plus Minus And Or Eq Neq Lt Lte Gt Gte Identifier AssignableIdentifier Word IdentifierBeforeDot Program PipeExpr FunctionCall PositionalArg ParenExpr FunctionCallOrIdentifier BinOp ConditionalOp String StringFragment Interpolation EscapeSeq Number Boolean Regex Null DotGet FunctionDef keyword Params colon end Underscore NamedArg NamedArgPrefix operator IfExpr keyword ThenBlock ThenBlock ElsifExpr keyword ElseExpr keyword Assign",
maxTerm: 84,
context: trackScope,
nodeProps: [
["closedBy", 37,"end"]
["closedBy", 37,"end"],
["openedBy", 38,"colon"]
],
propSources: [highlighting],
skippedNodes: [0],
repeatNodeCount: 7,
tokenData: "?p~RyOX#rXY$aYZ$zZp#rpq$aqt#rtu%euw#rwx%jxy%oyz&Yz{#r{|&s|}#r}!O&s!O!P#r!P!Q)g!Q!['b![!]2S!]!^$z!^#O#r#O#P2m#P#R#r#R#S2r#S#T#r#T#Y3]#Y#Z4k#Z#b3]#b#c8y#c#f3]#f#g<c#g#h3]#h#i=Y#i#o3]#o#p#r#p#q?Q#q;'S#r;'S;=`$Z<%l~#r~O#r~~?kS#wUjSOt#ruw#rx#O#r#P;'S#r;'S;=`$Z<%lO#rS$^P;=`<%l#r^$hUjS!_YOt#ruw#rx#O#r#P;'S#r;'S;=`$Z<%lO#rU%RUjS!rQOt#ruw#rx#O#r#P;'S#r;'S;=`$Z<%lO#r~%jO!j~~%oO!h~U%vUjS!fQOt#ruw#rx#O#r#P;'S#r;'S;=`$Z<%lO#rU&aUjS!gQOt#ruw#rx#O#r#P;'S#r;'S;=`$Z<%lO#rU&xWjSOt#ruw#rx!Q#r!Q!['b![#O#r#P;'S#r;'S;=`$Z<%lO#rU'iYjSmQOt#ruw#rx!O#r!O!P(X!P!Q#r!Q!['b![#O#r#P;'S#r;'S;=`$Z<%lO#rU(^WjSOt#ruw#rx!Q#r!Q![(v![#O#r#P;'S#r;'S;=`$Z<%lO#rU(}WjSmQOt#ruw#rx!Q#r!Q![(v![#O#r#P;'S#r;'S;=`$Z<%lO#rU)lWjSOt#ruw#rx!P#r!P!Q*U!Q#O#r#P;'S#r;'S;=`$Z<%lO#rU*Z^jSOY+VYZ#rZt+Vtu,Yuw+Vwx,Yx!P+V!P!Q#r!Q!}+V!}#O0{#O#P.h#P;'S+V;'S;=`1|<%lO+VU+^^jSoQOY+VYZ#rZt+Vtu,Yuw+Vwx,Yx!P+V!P!Q.}!Q!}+V!}#O0{#O#P.h#P;'S+V;'S;=`1|<%lO+VQ,_XoQOY,YZ!P,Y!P!Q,z!Q!},Y!}#O-i#O#P.h#P;'S,Y;'S;=`.w<%lO,YQ,}P!P!Q-QQ-VUoQ#Z#[-Q#]#^-Q#a#b-Q#g#h-Q#i#j-Q#m#n-QQ-lVOY-iZ#O-i#O#P.R#P#Q,Y#Q;'S-i;'S;=`.b<%lO-iQ.USOY-iZ;'S-i;'S;=`.b<%lO-iQ.eP;=`<%l-iQ.kSOY,YZ;'S,Y;'S;=`.w<%lO,YQ.zP;=`<%l,YU/SWjSOt#ruw#rx!P#r!P!Q/l!Q#O#r#P;'S#r;'S;=`$Z<%lO#rU/sbjSoQOt#ruw#rx#O#r#P#Z#r#Z#[/l#[#]#r#]#^/l#^#a#r#a#b/l#b#g#r#g#h/l#h#i#r#i#j/l#j#m#r#m#n/l#n;'S#r;'S;=`$Z<%lO#rU1Q[jSOY0{YZ#rZt0{tu-iuw0{wx-ix#O0{#O#P.R#P#Q+V#Q;'S0{;'S;=`1v<%lO0{U1yP;=`<%l0{U2PP;=`<%l+VU2ZUjSuQOt#ruw#rx#O#r#P;'S#r;'S;=`$Z<%lO#r~2rO!k~U2yUjSwQOt#ruw#rx#O#r#P;'S#r;'S;=`$Z<%lO#rU3bYjSOt#ruw#rx!_#r!_!`4Q!`#O#r#P#T#r#T#o3]#o;'S#r;'S;=`$Z<%lO#rU4XUyQjSOt#ruw#rx#O#r#P;'S#r;'S;=`$Z<%lO#rU4pZjSOt#ruw#rx!_#r!_!`4Q!`#O#r#P#T#r#T#U5c#U#o3]#o;'S#r;'S;=`$Z<%lO#rU5h[jSOt#ruw#rx!_#r!_!`4Q!`#O#r#P#T#r#T#`3]#`#a6^#a#o3]#o;'S#r;'S;=`$Z<%lO#rU6c[jSOt#ruw#rx!_#r!_!`4Q!`#O#r#P#T#r#T#g3]#g#h7X#h#o3]#o;'S#r;'S;=`$Z<%lO#rU7^[jSOt#ruw#rx!_#r!_!`4Q!`#O#r#P#T#r#T#X3]#X#Y8S#Y#o3]#o;'S#r;'S;=`$Z<%lO#rU8ZYnQjSOt#ruw#rx!_#r!_!`4Q!`#O#r#P#T#r#T#o3]#o;'S#r;'S;=`$Z<%lO#r^9Q[!lWjSOt#ruw#rx!_#r!_!`4Q!`#O#r#P#T#r#T#i3]#i#j9v#j#o3]#o;'S#r;'S;=`$Z<%lO#rU9{[jSOt#ruw#rx!_#r!_!`4Q!`#O#r#P#T#r#T#`3]#`#a:q#a#o3]#o;'S#r;'S;=`$Z<%lO#rU:v[jSOt#ruw#rx!_#r!_!`4Q!`#O#r#P#T#r#T#`3]#`#a;l#a#o3]#o;'S#r;'S;=`$Z<%lO#rU;sYpQjSOt#ruw#rx!_#r!_!`4Q!`#O#r#P#T#r#T#o3]#o;'S#r;'S;=`$Z<%lO#r^<jY!nWjSOt#ruw#rx!_#r!_!`4Q!`#O#r#P#T#r#T#o3]#o;'S#r;'S;=`$Z<%lO#r^=a[!mWjSOt#ruw#rx!_#r!_!`4Q!`#O#r#P#T#r#T#f3]#f#g>V#g#o3]#o;'S#r;'S;=`$Z<%lO#rU>[[jSOt#ruw#rx!_#r!_!`4Q!`#O#r#P#T#r#T#i3]#i#j7X#j#o3]#o;'S#r;'S;=`$Z<%lO#rU?XUzQjSOt#ruw#rx#O#r#P;'S#r;'S;=`$Z<%lO#r~?pO!v~",
tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO!o~~", 11)],
tokenData: "JX~R|OX#{XY$jYZ%TZp#{pq$jqt#{tu%nuw#{wx%sxy%xyz&cz{#{{|&||}#{}!O&|!O!P)p!P!Q*Z!Q!['k![!]2v!]!^%T!^#O#{#O#P3a#P#R#{#R#S3f#S#T#{#T#X4P#X#Y5_#Y#Z<e#Z#]4P#]#^Ap#^#b4P#b#cCb#c#f4P#f#gFz#g#h4P#h#iGq#i#o4P#o#p#{#p#qIi#q;'S#{;'S;=`$d<%l~#{~O#{~~JSS$QUjSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{S$gP;=`<%l#{_$qUjS!_ZOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{V%[UjS!rROt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~%sO!j~~%xO!h~V&PUjS!fROt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{V&jUjS!gROt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{V'RWjSOt#{uw#{x!Q#{!Q!['k![#O#{#P;'S#{;'S;=`$d<%lO#{V'rYjSmROt#{uw#{x!O#{!O!P(b!P!Q#{!Q!['k![#O#{#P;'S#{;'S;=`$d<%lO#{V(gWjSOt#{uw#{x!Q#{!Q![)P![#O#{#P;'S#{;'S;=`$d<%lO#{V)WWjSmROt#{uw#{x!Q#{!Q![)P![#O#{#P;'S#{;'S;=`$d<%lO#{T)wU!oPjSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{V*`WjSOt#{uw#{x!P#{!P!Q*x!Q#O#{#P;'S#{;'S;=`$d<%lO#{V*}^jSOY+yYZ#{Zt+ytu,|uw+ywx,|x!P+y!P!Q#{!Q!}+y!}#O1o#O#P/[#P;'S+y;'S;=`2p<%lO+yV,Q^jSoROY+yYZ#{Zt+ytu,|uw+ywx,|x!P+y!P!Q/q!Q!}+y!}#O1o#O#P/[#P;'S+y;'S;=`2p<%lO+yR-RXoROY,|Z!P,|!P!Q-n!Q!},|!}#O.]#O#P/[#P;'S,|;'S;=`/k<%lO,|R-qP!P!Q-tR-yUoR#Z#[-t#]#^-t#a#b-t#g#h-t#i#j-t#m#n-tR.`VOY.]Z#O.]#O#P.u#P#Q,|#Q;'S.];'S;=`/U<%lO.]R.xSOY.]Z;'S.];'S;=`/U<%lO.]R/XP;=`<%l.]R/_SOY,|Z;'S,|;'S;=`/k<%lO,|R/nP;=`<%l,|V/vWjSOt#{uw#{x!P#{!P!Q0`!Q#O#{#P;'S#{;'S;=`$d<%lO#{V0gbjSoROt#{uw#{x#O#{#P#Z#{#Z#[0`#[#]#{#]#^0`#^#a#{#a#b0`#b#g#{#g#h0`#h#i#{#i#j0`#j#m#{#m#n0`#n;'S#{;'S;=`$d<%lO#{V1t[jSOY1oYZ#{Zt1otu.]uw1owx.]x#O1o#O#P.u#P#Q+y#Q;'S1o;'S;=`2j<%lO1oV2mP;=`<%l1oV2sP;=`<%l+yT2}UjSuPOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~3fO!k~V3mUjSwROt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U4UYjSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#o4P#o;'S#{;'S;=`$d<%lO#{U4{UyQjSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{V5d^jSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#`4P#`#a6`#a#b4P#b#c:s#c#o4P#o;'S#{;'S;=`$d<%lO#{V6e[jSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#g4P#g#h7Z#h#o4P#o;'S#{;'S;=`$d<%lO#{V7`^jSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#X4P#X#Y8[#Y#]4P#]#^9R#^#o4P#o;'S#{;'S;=`$d<%lO#{V8cY!SPjSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#o4P#o;'S#{;'S;=`$d<%lO#{V9W[jSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#Y4P#Y#Z9|#Z#o4P#o;'S#{;'S;=`$d<%lO#{V:TY!QPjSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#o4P#o;'S#{;'S;=`$d<%lO#{V:x[jSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#W4P#W#X;n#X#o4P#o;'S#{;'S;=`$d<%lO#{V;uYjSvROt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#o4P#o;'S#{;'S;=`$d<%lO#{V<j]jSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#U=c#U#b4P#b#c@y#c#o4P#o;'S#{;'S;=`$d<%lO#{V=h[jSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#`4P#`#a>^#a#o4P#o;'S#{;'S;=`$d<%lO#{V>c[jSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#g4P#g#h?X#h#o4P#o;'S#{;'S;=`$d<%lO#{V?^[jSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#X4P#X#Y@S#Y#o4P#o;'S#{;'S;=`$d<%lO#{V@ZYnRjSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#o4P#o;'S#{;'S;=`$d<%lO#{VAQYsRjSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#o4P#o;'S#{;'S;=`$d<%lO#{VAu[jSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#Y4P#Y#ZBk#Z#o4P#o;'S#{;'S;=`$d<%lO#{VBrY|PjSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#o4P#o;'S#{;'S;=`$d<%lO#{_Ci[!lWjSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#i4P#i#jD_#j#o4P#o;'S#{;'S;=`$d<%lO#{VDd[jSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#`4P#`#aEY#a#o4P#o;'S#{;'S;=`$d<%lO#{VE_[jSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#`4P#`#aFT#a#o4P#o;'S#{;'S;=`$d<%lO#{VF[YpRjSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#o4P#o;'S#{;'S;=`$d<%lO#{^GRY!nWjSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#o4P#o;'S#{;'S;=`$d<%lO#{_Gx[!mWjSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#f4P#f#gHn#g#o4P#o;'S#{;'S;=`$d<%lO#{VHs[jSOt#{uw#{x!_#{!_!`4t!`#O#{#P#T#{#T#i4P#i#j?X#j#o4P#o;'S#{;'S;=`$d<%lO#{VIpUzRjSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~JXO!v~",
tokenizers: [operatorTokenizer, 0, 1, 2, 3, tokenizer],
topRules: {"Program":[0,17]},
specialized: [{term: 13, get: (value: keyof typeof spec_Identifier) => spec_Identifier[value] || -1}],
tokenPrec: 768
})

View File

@ -286,12 +286,12 @@ describe('Assign', () => {
})
test('parses assignment with functions', () => {
expect('add = do a b: a + b end').toMatchTree(`
expect('add = fn a b: a + b end').toMatchTree(`
Assign
AssignableIdentifier add
Eq =
FunctionDef
keyword do
keyword fn
Params
AssignableIdentifier a
AssignableIdentifier b
@ -300,7 +300,7 @@ describe('Assign', () => {
Identifier a
Plus +
Identifier b
keyword end`)
end end`)
})
})

View File

@ -45,7 +45,7 @@ describe('if/elsif/else', () => {
ThenBlock
FunctionCallOrIdentifier
Identifier yes
keyword end
end end
`)
})
@ -68,7 +68,7 @@ describe('if/elsif/else', () => {
ThenBlock
FunctionCallOrIdentifier
Identifier y
keyword end
end end
`)
})
@ -92,7 +92,7 @@ describe('if/elsif/else', () => {
ThenBlock
FunctionCallOrIdentifier
Identifier y
keyword end
end end
`)
})
@ -133,21 +133,7 @@ describe('if/elsif/else', () => {
ThenBlock
FunctionCallOrIdentifier
Identifier oh-no
keyword end
`)
})
test('does not parse identifiers that start with if', () => {
expect('iffy = if true: 2').toMatchTree(`
Assign
AssignableIdentifier iffy
Eq =
IfExpr
keyword if
Boolean true
colon :
ThenBlock
Number 2
end end
`)
})
})

View File

@ -27,41 +27,41 @@ describe('DotGet', () => {
})
test('function parameters are in scope within function body', () => {
expect('do config: config.path end').toMatchTree(`
expect('fn config: config.path end').toMatchTree(`
FunctionDef
keyword do
keyword fn
Params
AssignableIdentifier config
colon :
DotGet
IdentifierBeforeDot config
Identifier path
keyword end
end end
`)
})
test('parameters out of scope outside function', () => {
expect('do x: x.prop end; x.prop').toMatchTree(`
expect('fn x: x.prop end; x.prop').toMatchTree(`
FunctionDef
keyword do
keyword fn
Params
AssignableIdentifier x
colon :
DotGet
IdentifierBeforeDot x
Identifier prop
keyword end
end end
Word x.prop
`)
})
test('multiple parameters work correctly', () => {
expect(`do x y:
expect(`fn x y:
x.foo
y.bar
end`).toMatchTree(`
FunctionDef
keyword do
keyword fn
Params
AssignableIdentifier x
AssignableIdentifier y
@ -72,17 +72,17 @@ end`).toMatchTree(`
DotGet
IdentifierBeforeDot y
Identifier bar
keyword end
end end
`)
})
test('nested functions with scope isolation', () => {
expect(`do x:
expect(`fn x:
x.outer
do y: y.inner end
fn y: y.inner end
end`).toMatchTree(`
FunctionDef
keyword do
keyword fn
Params
AssignableIdentifier x
colon :
@ -90,15 +90,15 @@ end`).toMatchTree(`
IdentifierBeforeDot x
Identifier outer
FunctionDef
keyword do
keyword fn
Params
AssignableIdentifier y
colon :
DotGet
IdentifierBeforeDot y
Identifier inner
keyword end
keyword end
end end
end end
`)
})

View File

@ -56,21 +56,21 @@ describe('calling functions', () => {
})
})
describe('Do', () => {
describe('Fn', () => {
test('parses function no parameters', () => {
expect('do: 1 end').toMatchTree(`
expect('fn: 1 end').toMatchTree(`
FunctionDef
keyword do
keyword fn
Params
colon :
Number 1
keyword end`)
end end`)
})
test('parses function with single parameter', () => {
expect('do x: x + 1 end').toMatchTree(`
expect('fn x: x + 1 end').toMatchTree(`
FunctionDef
keyword do
keyword fn
Params
AssignableIdentifier x
colon :
@ -78,13 +78,13 @@ describe('Do', () => {
Identifier x
Plus +
Number 1
keyword end`)
end end`)
})
test('parses function with multiple parameters', () => {
expect('do x y: x * y end').toMatchTree(`
expect('fn x y: x * y end').toMatchTree(`
FunctionDef
keyword do
keyword fn
Params
AssignableIdentifier x
AssignableIdentifier y
@ -93,16 +93,16 @@ describe('Do', () => {
Identifier x
Star *
Identifier y
keyword end`)
end end`)
})
test('parses multiline function with multiple statements', () => {
expect(`do x y:
expect(`fn x y:
x * y
x + 9
end`).toMatchTree(`
FunctionDef
keyword do
keyword fn
Params
AssignableIdentifier x
AssignableIdentifier y
@ -115,36 +115,6 @@ end`).toMatchTree(`
Identifier x
Plus +
Number 9
keyword end`)
})
test('does not parse identifiers that start with fn', () => {
expect('fnnn = do x: x end').toMatchTree(`
Assign
AssignableIdentifier fnnn
Eq =
FunctionDef
keyword do
Params
AssignableIdentifier x
colon :
FunctionCallOrIdentifier
Identifier x
keyword end`)
})
test('does not parse identifiers that start with end', () => {
expect('enddd = do x: x end').toMatchTree(`
Assign
AssignableIdentifier enddd
Eq =
FunctionDef
keyword do
Params
AssignableIdentifier x
colon :
FunctionCallOrIdentifier
Identifier x
keyword end`)
end end`)
})
})

View File

@ -13,7 +13,7 @@ describe('multiline', () => {
test('parses multiline functions', () => {
expect(`
add = do a b:
add = fn a b:
result = a + b
result
end
@ -24,7 +24,7 @@ describe('multiline', () => {
AssignableIdentifier add
Eq =
FunctionDef
keyword do
keyword fn
Params
AssignableIdentifier a
AssignableIdentifier b
@ -39,7 +39,7 @@ describe('multiline', () => {
FunctionCallOrIdentifier
Identifier result
keyword end
end end
FunctionCall
Identifier add
PositionalArg
@ -53,7 +53,7 @@ describe('multiline', () => {
3
do x y:
fn x y:
x
end
@ -61,14 +61,14 @@ end
Number 3
FunctionDef
keyword do
keyword fn
Params
AssignableIdentifier x
AssignableIdentifier y
colon :
FunctionCallOrIdentifier
Identifier x
keyword end
end end
`)
})
})

View File

@ -66,7 +66,7 @@ describe('pipe expressions', () => {
})
test('pipe with inline function', () => {
expect('items | each do x: x end').toMatchTree(`
expect('items | each fn x: x end').toMatchTree(`
PipeExpr
FunctionCallOrIdentifier
Identifier items
@ -75,13 +75,13 @@ describe('pipe expressions', () => {
Identifier each
PositionalArg
FunctionDef
keyword do
keyword fn
Params
AssignableIdentifier x
colon :
FunctionCallOrIdentifier
Identifier x
keyword end
end end
`)
})
})