parse arrays

This commit is contained in:
Chris Wanstrath 2025-10-28 16:30:45 -07:00
parent 7a4affd01e
commit 7da4c14962
5 changed files with 112 additions and 29 deletions

View File

@ -191,6 +191,10 @@ EscapeSeq {
"\\" ("$" | "n" | "t" | "r" | "\\" | "'") "\\" ("$" | "n" | "t" | "r" | "\\" | "'")
} }
Array {
"[" (newlineOrSemicolon | expression)* "]"
}
// 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
@ -200,7 +204,7 @@ EscapeSeq {
// to go through ambiguousFunctionCall (which is what we want semantically). // to go through ambiguousFunctionCall (which is what we want semantically).
// Yes, it is annoying and I gave up trying to use GLR to fix it. // Yes, it is annoying and I gave up trying to use GLR to fix it.
expressionWithoutIdentifier { expressionWithoutIdentifier {
ParenExpr | Word | String | Number | Boolean | Regex | @specialize[@name=Null]<Identifier, "null"> ParenExpr | Word | String | Number | Boolean | Regex | Array | @specialize[@name=Null]<Identifier, "null">
} }
block { block {

View File

@ -31,19 +31,20 @@ export const
EscapeSeq = 29, EscapeSeq = 29,
Boolean = 30, Boolean = 30,
Regex = 31, Regex = 31,
Null = 32, Array = 32,
ConditionalOp = 33, Null = 33,
FunctionDef = 34, ConditionalOp = 34,
Params = 35, FunctionDef = 35,
colon = 36, Params = 36,
keyword = 50, colon = 37,
PositionalArg = 38, keyword = 51,
Underscore = 39, PositionalArg = 39,
NamedArg = 40, Underscore = 40,
NamedArgPrefix = 41, NamedArg = 41,
IfExpr = 43, NamedArgPrefix = 42,
SingleLineThenBlock = 45, IfExpr = 44,
ThenBlock = 46, SingleLineThenBlock = 46,
ElseIfExpr = 47, ThenBlock = 47,
ElseExpr = 49, ElseIfExpr = 48,
Assign = 51 ElseExpr = 50,
Assign = 52

View File

@ -4,24 +4,24 @@ import {operatorTokenizer} from "./operatorTokenizer"
import {tokenizer, specializeKeyword} from "./tokenizer" import {tokenizer, specializeKeyword} from "./tokenizer"
import {trackScope} from "./scopeTracker" import {trackScope} from "./scopeTracker"
import {highlighting} from "./highlight" import {highlighting} from "./highlight"
const spec_Identifier = {__proto__:null,null:64, end:74, if:88, elseif:96, else:100} const spec_Identifier = {__proto__:null,null:66, end:76, if:90, elseif:98, else:102}
export const parser = LRParser.deserialize({ export const parser = LRParser.deserialize({
version: 14, version: 14,
states: "/SQYQbOOO!TOpO'#CqO#aQcO'#CtO$ZOSO'#CvO%aQcO'#DsOOQa'#Ds'#DsO&gQcO'#DrO'OQRO'#CuO'^QcO'#DnO'uQbO'#D{OOQ`'#DO'#DOO'}QbO'#CsOOQ`'#Do'#DoO(oQbO'#DnO(}QbO'#EROOQ`'#DX'#DXO)lQRO'#DaOOQ`'#Dn'#DnO)qQQO'#DmOOQ`'#Dm'#DmOOQ`'#Db'#DbQYQbOOO)yObO,59]OOQa'#Dr'#DrOOQ`'#DS'#DSO*RQbO'#DUOOQ`'#EQ'#EQOOQ`'#Df'#DfO*]QbO,59[O*pQbO'#CxO*xQWO'#CyOOOO'#Du'#DuOOOO'#Dc'#DcO+^OSO,59bOOQa,59b,59bO(}QbO,59aO(}QbO,59aOOQ`'#Dd'#DdO+lQbO'#DPO+tQQO,5:gO+yQRO,59_O-`QRO'#CuO-pQRO,59_O-|QQO,59_O.RQQO,59_O.ZQbO'#DgO.fQbO,59ZO.wQRO,5:mO/OQQO,5:mO/TQbO,59{OOQ`,5:X,5:XOOQ`-E7`-E7`OOQa1G.w1G.wOOQ`,59p,59pOOQ`-E7d-E7dOOOO,59d,59dOOOO,59e,59eOOOO-E7a-E7aOOQa1G.|1G.|OOQa1G.{1G.{O/_QcO1G.{OOQ`-E7b-E7bO/yQbO1G0ROOQa1G.y1G.yO(}QbO,59iO(}QbO,59iO!YQbO'#CtO$iQbO'#CpOOQ`,5:R,5:ROOQ`-E7e-E7eO0WQbO1G0XOOQ`1G/g1G/gO0eQbO7+%mO0jQbO7+%nOOQO1G/T1G/TO0zQRO1G/TOOQ`'#DZ'#DZO1UQbO7+%sO1ZQbO7+%tOOQ`<<IX<<IXOOQ`'#De'#DeO1qQQO'#DeO1vQbO'#EOO2^QbO<<IYOOQ`<<I_<<I_OOQ`'#D['#D[O2cQbO<<I`OOQ`,5:P,5:POOQ`-E7c-E7cOOQ`AN>tAN>tO(}QbO'#D]OOQ`'#Dh'#DhO2nQbOAN>zO2yQQO'#D_OOQ`AN>zAN>zO3OQbOAN>zO3TQRO,59wO3[QQO,59wOOQ`-E7f-E7fOOQ`G24fG24fO3aQbOG24fO3fQQO,59yO3kQQO1G/cOOQ`LD*QLD*QO0jQbO1G/eO1ZQbO7+$}OOQ`7+%P7+%POOQ`<<Hi<<Hi", states: "/xQYQbOOO!WOpO'#CqO#gQcO'#CtO$aOSO'#CvO%dQbO'#C|O&fQcO'#DuOOQa'#Du'#DuO'lQcO'#DtO(TQRO'#CuO(cQcO'#DpO(zQbO'#EQOOQ`'#DP'#DPO)SQbO'#CsOOQ`'#Dq'#DqO)wQbO'#DpO*VQbO'#EVOOQ`'#DY'#DYO*wQRO'#DbOOQ`'#Dp'#DpO*|QQO'#DoOOQ`'#Do'#DoOOQ`'#Dc'#DcQYQbOOO+UObO,59]OOQa'#Dt'#DtOOQ`'#DT'#DTO+^QbO'#DVOOQ`'#EU'#EUOOQ`'#Dh'#DhO+hQbO,59[O+{QbO'#CxO,TQWO'#CyOOOO'#Dw'#DwOOOO'#Dd'#DdO,iOSO,59bOOQa,59b,59bOOQ`'#De'#DeO,wQbO,59hOOQa,59h,59hO*VQbO,59aO*VQbO,59aOOQ`'#Df'#DfO-OQbO'#DQO-WQQO,5:lO-]QRO,59_O.rQRO'#CuO/SQRO,59_O/`QQO,59_O/eQQO,59_O/mQbO'#DiO/xQbO,59ZO0ZQRO,5:qO0bQQO,5:qO0gQbO,59|OOQ`,5:Z,5:ZOOQ`-E7a-E7aOOQa1G.w1G.wOOQ`,59q,59qOOQ`-E7f-E7fOOOO,59d,59dOOOO,59e,59eOOOO-E7b-E7bOOQa1G.|1G.|OOQ`-E7c-E7cOOQa1G/S1G/SOOQa1G.{1G.{O0qQcO1G.{OOQ`-E7d-E7dO1]QbO1G0WOOQa1G.y1G.yO*VQbO,59jO*VQbO,59jO!]QbO'#CtO%kQbO'#CpOOQ`,5:T,5:TOOQ`-E7g-E7gO1jQbO1G0]OOQ`1G/h1G/hO1wQbO7+%rO1|QbO7+%sOOQO1G/U1G/UO2^QRO1G/UOOQ`'#D['#D[O2hQbO7+%wO2mQbO7+%xOOQ`<<I^<<I^OOQ`'#Dg'#DgO3TQQO'#DgO3YQbO'#ESO3pQbO<<I_OOQ`<<Ic<<IcOOQ`'#D]'#D]O3uQbO<<IdOOQ`,5:R,5:ROOQ`-E7e-E7eOOQ`AN>yAN>yO*VQbO'#D^OOQ`'#Dj'#DjO4QQbOAN?OO4]QQO'#D`OOQ`AN?OAN?OO4bQbOAN?OO4gQRO,59xO4nQQO,59xOOQ`-E7h-E7hOOQ`G24jG24jO4sQbOG24jO4xQQO,59zO4}QQO1G/dOOQ`LD*ULD*UO1|QbO1G/fO2mQbO7+%OOOQ`7+%Q7+%QOOQ`<<Hj<<Hj",
stateData: "3s~O!_OS!`OS~O]QO^`O_TO`POaXOfTOnTOoTOpTO|^O!eZO!hRO!qcO~O!dfO~O]gO_TO`POaXOfTOnTOoTOpTOwhOyiO!eZO!hROzhX!qhX!whX!shXuhX~OP!fXQ!fXR!fXS!fXT!fXU!fXV!fXW!fXX!fXY!fXZ!fX[!fX~P!YOkoO!hrO!jmO!knO~O]gO_TO`POaXOfTOnTOoTOpTOwhOyiO!eZO!hRO~OP!gXQ!gXR!gXS!gX!q!gX!w!gXT!gXU!gXV!gXW!gXX!gXY!gXZ!gX[!gX!s!gXu!gX~P$iOP!fXQ!fXR!fXS!fX!q!bX!w!bXu!bX~OPsOQsORtOStO~OPsOQsORtOStO!q!bX!w!bXu!bX~O]uOtsP~O]QO_TO`POaXOfTOnTOoTOpTO!eZO!hRO~Oz}O!q!bX!w!bXu!bX~O]gO_TO`POfTOnTOoTOpTO!eZO!hRO~OV!RO~O!q!SO!w!SO~O]!UOf!UO~OaXOw!VO~P(}Ozda!qda!wda!sdauda~P$iO]!XO!eZO~O!h!YO!j!YO!k!YO!l!YO!m!YO!n!YO~OkoO!h![O!jmO!knO~O]uOtsX~Ot!`O~O!s!aOP!fXQ!fXR!fXS!fXT!fXU!fXV!fXW!fXX!fXY!fXZ!fX[!fX~OT!cOU!cOV!bOW!bOX!bOY!bOZ!bO[!bO~OPsOQsORtOStO~P,tOPsOQsORtOStO!s!aO~Oz}O!s!aO~O]!dO`PO!eZO~Oz}O!qca!wca!scauca~Ot!hO~P,tOt!hO~O^`O|^O~P'}OPsOQsORiiSii!qii!wii!siiuii~O^`O|^O!q!kO~P'}O^`O|^O!q!pO~P'}Ou!qO~O^`O|^O!q!rOu!rP~P'}O!sqitqi~P,tOu!vO~O^`O|^O!q!rOu!rP!Q!rP!S!rP~P'}O!q!yO~O^`O|^O!q!rOu!rX!Q!rX!S!rX~P'}Ou!{O~Ou#QO!Q!|O!S#PO~Ou#VO!Q!|O!S#PO~Ot#XO~Ou#VO~Ot#YO~P,tOt#YO~Ou#ZO~O!q#[O~O!q#]O~Ofo~", stateData: "5V~O!aOS!bOS~O]QO^aO_UO`POaYOfUOnUOoUOqUO}_O!g[O!jRO!qSO!rdO~O!fgO~O]hO_UO`POaYOfUOnUOoUOqUOxiOzjO!g[O!jRO!qSO{hX!rhX!{hX!whXvhX~OP!hXQ!hXR!hXS!hXT!hXU!hXV!hXW!hXX!hXY!hXZ!hX[!hX~P!]OkpO!jsO!lnO!moO~O]hO_UO`POfUOnUOoUOqUO!g[O!jRO!qSO!rtO~O!svO~P$oO]hO_UO`POaYOfUOnUOoUOqUOxiOzjO!g[O!jRO!qSO~OP!iXQ!iXR!iXS!iX!r!iX!{!iXT!iXU!iXV!iXW!iXX!iXY!iXZ!iX[!iX!w!iXv!iX~P%kOP!hXQ!hXR!hXS!hX!r!dX!{!dXv!dX~OPwOQwORxOSxO~OPwOQwORxOSxO!r!dX!{!dXv!dX~O]yOutP~O]QO_UO`POaYOfUOnUOoUOqUO!g[O!jRO!qSO~O{!RO!r!dX!{!dXv!dX~O]hO_UO`POfUOnUOoUOqUO!g[O!jRO!qSO~OV!VO~O!r!WO!{!WO~O]!YOf!YO~OaYOx!ZO~P*VO{da!rda!{da!wdavda~P%kO]!]O!g[O~O!j!^O!l!^O!m!^O!n!^O!o!^O!p!^O~OkpO!j!`O!lnO!moO~O!s!bO~P$oO]yOutX~Ou!fO~O!w!gOP!hXQ!hXR!hXS!hXT!hXU!hXV!hXW!hXX!hXY!hXZ!hX[!hX~OT!iOU!iOV!hOW!hOX!hOY!hOZ!hO[!hO~OPwOQwORxOSxO~P.WOPwOQwORxOSxO!w!gO~O{!RO!w!gO~O]!jO`PO!g[O~O{!RO!rca!{ca!wcavca~Ou!nO~P.WOu!nO~O^aO}_O~P)SOPwOQwORiiSii!rii!{ii!wiivii~O^aO}_O!r!qO~P)SO^aO}_O!r!vO~P)SOv!wO~O^aO}_O!r!xOv!vP~P)SO!wriuri~P.WOv!|O~O^aO}_O!r!xOv!vP!R!vP!T!vP~P)SO!r#PO~O^aO}_O!r!xOv!vX!R!vX!T!vX~P)SOv#RO~Ov#WO!R#SO!T#VO~Ov#]O!R#SO!T#VO~Ou#_O~Ov#]O~Ou#`O~P.WOu#`O~Ov#aO~O!r#bO~O!r#cO~Ofo~",
goto: ",`!wPPPPPPPPPPPPPPPPPPP!x#X#gP$V#X$x%_P%x%xPPP%|&Y&sPP&vP&vPP&}P'Z'^'gP'kP&}'q'w'}(T(^(g(nPPPP(t(x)^PP)p*mP+[PPPPP+`+`P+sP+{,S,SdaOe!R!`!h!k!p!t#[#]R{Zi[OZe}!R!`!h!k!p!t#[#]fQOZe!R!`!h!k!p!t#[#]hgQS^ilst!b!c!d!e!|R!d}fSOZe!R!`!h!k!p!t#[#]hTQS^ilst!b!c!d!e!|Q!XmR!e}dWOe!R!`!h!k!p!t#[#]QzZQ!]sR!^t!PTOQSZ^eilst!R!`!b!c!d!e!h!k!p!t!|#[#]ToRqQ{ZQ!Q^Q!l!cR#T!|daOe!R!`!h!k!p!t#[#]YhQSl!d!eQ{ZR!ViRwXZjQSl!d!eeaOe!R!`!h!k!p!t#[#]R!o!hQ!x!pQ#^#[R#_#]T!}!x#OQ#R!xR#W#OQeOR!TeQqRR!ZqQvXR!_vW!t!k!p#[#]R!z!tWlQS!d!eR!WlS!O]|R!g!OQ#O!xR#U#OTdOeSbOeQ!i!RQ!j!`Q!n!hZ!s!k!p!t#[#]d]Oe!R!`!h!k!p!t#[#]Q|ZR!f}dVOe!R!`!h!k!p!t#[#]YhQSl!d!eQyZQ!P^Q!ViQ!]sQ!^tQ!l!bQ!m!cR#S!|dUOe!R!`!h!k!p!t#[#]hgQS^ilst!b!c!d!e!|RxZTpRqsYOQSZeil!R!`!d!e!h!k!p!t#[#]Q!u!kV!w!p#[#]ZkQSl!d!ee_Oe!R!`!h!k!p!t#[#]", goto: ",v!{PPPPPPPPPPPPPPPPPPP!|#]#kP$]#]%Q%gP&S&SPP%gP&W&d&}PP'QP'QPP'XP'e'h'qP'uP'X'{(R(X(_(e(n(w)OPPPP)U)Y)nPP*Q+RP+rPPPPPPPP+v+v,ZP,c,j,jdbOf!V!f!n!q!v!z#b#cR!P[i]O[f!R!V!f!n!q!v!z#b#cfQO[f!V!f!n!q!v!z#b#clhQST_jmuwx!h!i!j!k#SR!j!RfTO[f!V!f!n!q!v!z#b#clUQST_jmuwx!h!i!j!k#SQ!]nR!k!RdXOf!V!f!n!q!v!z#b#cQ!O[Q!cwR!dx!TUOQST[_fjmuwx!V!f!h!i!j!k!n!q!v!z#S#b#cTpRrQ!P[Q!U_Q!r!iR#Z#SdbOf!V!f!n!q!v!z#b#cYiQTm!j!kQ!P[R!ZjR{YZkQTm!j!kebOf!V!f!n!q!v!z#b#cR!u!nQ#O!vQ#d#bR#e#cT#T#O#UQ#X#OR#^#UQfOR!XfQrRR!_rQuSR!auQzYR!ezW!z!q!v#b#cR#Q!zWmQT!j!kR![mS!S^!QR!m!SQ#U#OR#[#UTeOfScOfQ!o!VQ!p!fQ!t!nZ!y!q!v!z#b#cd^Of!V!f!n!q!v!z#b#cQ!Q[R!l!RdWOf!V!f!n!q!v!z#b#cYiQTm!j!kStSuQ}[Q!T_Q!ZjQ!cwQ!dxQ!r!hQ!s!iR#Y#SdVOf!V!f!n!q!v!z#b#clhQST_jmuwx!h!i!j!k#SR|[TqRrsZOQT[fjm!V!f!j!k!n!q!v!z#b#cQ!{!qV!}!v#b#cZlQTm!j!ke`Of!V!f!n!q!v!z#b#c",
nodeNames: "⚠ Star Slash Plus Minus And Or Eq Neq Lt Lte Gt Gte Identifier AssignableIdentifier Word IdentifierBeforeDot Do Program PipeExpr FunctionCall DotGet Number ParenExpr FunctionCallOrIdentifier BinOp String StringFragment Interpolation EscapeSeq Boolean Regex Null ConditionalOp FunctionDef Params colon keyword PositionalArg Underscore NamedArg NamedArgPrefix operator IfExpr keyword SingleLineThenBlock ThenBlock ElseIfExpr keyword ElseExpr keyword Assign", nodeNames: "⚠ Star Slash Plus Minus And Or Eq Neq Lt Lte Gt Gte Identifier AssignableIdentifier Word IdentifierBeforeDot Do Program PipeExpr FunctionCall DotGet Number ParenExpr FunctionCallOrIdentifier BinOp String StringFragment Interpolation EscapeSeq Boolean Regex Array Null ConditionalOp FunctionDef Params colon keyword PositionalArg Underscore NamedArg NamedArgPrefix operator IfExpr keyword SingleLineThenBlock ThenBlock ElseIfExpr keyword ElseExpr keyword Assign",
maxTerm: 85, maxTerm: 89,
context: trackScope, context: trackScope,
nodeProps: [ nodeProps: [
["closedBy", 36,"end"] ["closedBy", 37,"end"]
], ],
propSources: [highlighting], propSources: [highlighting],
skippedNodes: [0], skippedNodes: [0],
repeatNodeCount: 7, repeatNodeCount: 8,
tokenData: ">i~RzOX#uXY$dYZ$}Zp#upq$dqs#ust%htu'Puw#uwx'Uxy'Zyz'tz{#u{|(_|}#u}!O(_!O!P#u!P!Q+R!Q![(|![!]3n!]!^$}!^#O#u#O#P4X#P#R#u#R#S4^#S#T#u#T#Y4w#Y#Z6V#Z#b4w#b#c:e#c#f4w#f#g;[#g#h4w#h#i<R#i#o4w#o#p#u#p#q=y#q;'S#u;'S;=`$^<%l~#u~O#u~~>dS#zUkSOt#uuw#ux#O#u#P;'S#u;'S;=`$^<%lO#uS$aP;=`<%l#u^$kUkS!_YOt#uuw#ux#O#u#P;'S#u;'S;=`$^<%lO#uU%UUkS!qQOt#uuw#ux#O#u#P;'S#u;'S;=`$^<%lO#u^%oZkS!`YOY%hYZ#uZt%htu&buw%hwx&bx#O%h#O#P&b#P;'S%h;'S;=`&y<%lO%hY&gS!`YOY&bZ;'S&b;'S;=`&s<%lO&bY&vP;=`<%l&b^&|P;=`<%l%h~'UO!j~~'ZO!h~U'bUkS!eQOt#uuw#ux#O#u#P;'S#u;'S;=`$^<%lO#uU'{UkS!sQOt#uuw#ux#O#u#P;'S#u;'S;=`$^<%lO#uU(dWkSOt#uuw#ux!Q#u!Q![(|![#O#u#P;'S#u;'S;=`$^<%lO#uU)TYkSfQOt#uuw#ux!O#u!O!P)s!P!Q#u!Q![(|![#O#u#P;'S#u;'S;=`$^<%lO#uU)xWkSOt#uuw#ux!Q#u!Q![*b![#O#u#P;'S#u;'S;=`$^<%lO#uU*iWkSfQOt#uuw#ux!Q#u!Q![*b![#O#u#P;'S#u;'S;=`$^<%lO#uU+WWkSOt#uuw#ux!P#u!P!Q+p!Q#O#u#P;'S#u;'S;=`$^<%lO#uU+u^kSOY,qYZ#uZt,qtu-tuw,qwx-tx!P,q!P!Q#u!Q!},q!}#O2g#O#P0S#P;'S,q;'S;=`3h<%lO,qU,x^kSoQOY,qYZ#uZt,qtu-tuw,qwx-tx!P,q!P!Q0i!Q!},q!}#O2g#O#P0S#P;'S,q;'S;=`3h<%lO,qQ-yXoQOY-tZ!P-t!P!Q.f!Q!}-t!}#O/T#O#P0S#P;'S-t;'S;=`0c<%lO-tQ.iP!P!Q.lQ.qUoQ#Z#[.l#]#^.l#a#b.l#g#h.l#i#j.l#m#n.lQ/WVOY/TZ#O/T#O#P/m#P#Q-t#Q;'S/T;'S;=`/|<%lO/TQ/pSOY/TZ;'S/T;'S;=`/|<%lO/TQ0PP;=`<%l/TQ0VSOY-tZ;'S-t;'S;=`0c<%lO-tQ0fP;=`<%l-tU0nWkSOt#uuw#ux!P#u!P!Q1W!Q#O#u#P;'S#u;'S;=`$^<%lO#uU1_bkSoQOt#uuw#ux#O#u#P#Z#u#Z#[1W#[#]#u#]#^1W#^#a#u#a#b1W#b#g#u#g#h1W#h#i#u#i#j1W#j#m#u#m#n1W#n;'S#u;'S;=`$^<%lO#uU2l[kSOY2gYZ#uZt2gtu/Tuw2gwx/Tx#O2g#O#P/m#P#Q,q#Q;'S2g;'S;=`3b<%lO2gU3eP;=`<%l2gU3kP;=`<%l,qU3uUkStQOt#uuw#ux#O#u#P;'S#u;'S;=`$^<%lO#u~4^O!k~U4eUkSwQOt#uuw#ux#O#u#P;'S#u;'S;=`$^<%lO#uU4|YkSOt#uuw#ux!_#u!_!`5l!`#O#u#P#T#u#T#o4w#o;'S#u;'S;=`$^<%lO#uU5sUyQkSOt#uuw#ux#O#u#P;'S#u;'S;=`$^<%lO#uU6[ZkSOt#uuw#ux!_#u!_!`5l!`#O#u#P#T#u#T#U6}#U#o4w#o;'S#u;'S;=`$^<%lO#uU7S[kSOt#uuw#ux!_#u!_!`5l!`#O#u#P#T#u#T#`4w#`#a7x#a#o4w#o;'S#u;'S;=`$^<%lO#uU7}[kSOt#uuw#ux!_#u!_!`5l!`#O#u#P#T#u#T#g4w#g#h8s#h#o4w#o;'S#u;'S;=`$^<%lO#uU8x[kSOt#uuw#ux!_#u!_!`5l!`#O#u#P#T#u#T#X4w#X#Y9n#Y#o4w#o;'S#u;'S;=`$^<%lO#uU9uYnQkSOt#uuw#ux!_#u!_!`5l!`#O#u#P#T#u#T#o4w#o;'S#u;'S;=`$^<%lO#u^:lY!lWkSOt#uuw#ux!_#u!_!`5l!`#O#u#P#T#u#T#o4w#o;'S#u;'S;=`$^<%lO#u^;cY!nWkSOt#uuw#ux!_#u!_!`5l!`#O#u#P#T#u#T#o4w#o;'S#u;'S;=`$^<%lO#u^<Y[!mWkSOt#uuw#ux!_#u!_!`5l!`#O#u#P#T#u#T#f4w#f#g=O#g#o4w#o;'S#u;'S;=`$^<%lO#uU=T[kSOt#uuw#ux!_#u!_!`5l!`#O#u#P#T#u#T#i4w#i#j8s#j#o4w#o;'S#u;'S;=`$^<%lO#uU>QUzQkSOt#uuw#ux#O#u#P;'S#u;'S;=`$^<%lO#u~>iO!w~", tokenData: "?s~R|OX#{XY$jYZ%TZp#{pq$jqs#{st%ntu'Vuw#{wx'[xy'ayz'zz{#{{|(e|}#{}!O(e!O!P#{!P!Q+X!Q![)S![!]3t!]!^%T!^!}#{!}#O4_#O#P4x#P#Q4}#Q#R#{#R#S5h#S#T#{#T#Y6R#Y#Z7a#Z#b6R#b#c;o#c#f6R#f#g<f#g#h6R#h#i=]#i#o6R#o#p#{#p#q?T#q;'S#{;'S;=`$d<%l~#{~O#{~~?nS$QUkSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{S$gP;=`<%l#{^$qUkS!aYOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U%[UkS!rQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^%uZkS!bYOY%nYZ#{Zt%ntu&huw%nwx&hx#O%n#O#P&h#P;'S%n;'S;=`'P<%lO%nY&mS!bYOY&hZ;'S&h;'S;=`&y<%lO&hY&|P;=`<%l&h^'SP;=`<%l%n~'[O!l~~'aO!j~U'hUkS!gQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(RUkS!wQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(jWkSOt#{uw#{x!Q#{!Q![)S![#O#{#P;'S#{;'S;=`$d<%lO#{U)ZYkSfQOt#{uw#{x!O#{!O!P)y!P!Q#{!Q![)S![#O#{#P;'S#{;'S;=`$d<%lO#{U*OWkSOt#{uw#{x!Q#{!Q![*h![#O#{#P;'S#{;'S;=`$d<%lO#{U*oWkSfQOt#{uw#{x!Q#{!Q![*h![#O#{#P;'S#{;'S;=`$d<%lO#{U+^WkSOt#{uw#{x!P#{!P!Q+v!Q#O#{#P;'S#{;'S;=`$d<%lO#{U+{^kSOY,wYZ#{Zt,wtu-zuw,wwx-zx!P,w!P!Q#{!Q!},w!}#O2m#O#P0Y#P;'S,w;'S;=`3n<%lO,wU-O^kSoQOY,wYZ#{Zt,wtu-zuw,wwx-zx!P,w!P!Q0o!Q!},w!}#O2m#O#P0Y#P;'S,w;'S;=`3n<%lO,wQ.PXoQOY-zZ!P-z!P!Q.l!Q!}-z!}#O/Z#O#P0Y#P;'S-z;'S;=`0i<%lO-zQ.oP!P!Q.rQ.wUoQ#Z#[.r#]#^.r#a#b.r#g#h.r#i#j.r#m#n.rQ/^VOY/ZZ#O/Z#O#P/s#P#Q-z#Q;'S/Z;'S;=`0S<%lO/ZQ/vSOY/ZZ;'S/Z;'S;=`0S<%lO/ZQ0VP;=`<%l/ZQ0]SOY-zZ;'S-z;'S;=`0i<%lO-zQ0lP;=`<%l-zU0tWkSOt#{uw#{x!P#{!P!Q1^!Q#O#{#P;'S#{;'S;=`$d<%lO#{U1ebkSoQOt#{uw#{x#O#{#P#Z#{#Z#[1^#[#]#{#]#^1^#^#a#{#a#b1^#b#g#{#g#h1^#h#i#{#i#j1^#j#m#{#m#n1^#n;'S#{;'S;=`$d<%lO#{U2r[kSOY2mYZ#{Zt2mtu/Zuw2mwx/Zx#O2m#O#P/s#P#Q,w#Q;'S2m;'S;=`3h<%lO2mU3kP;=`<%l2mU3qP;=`<%l,wU3{UkSuQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U4fU!qQkSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~4}O!m~U5UU!sQkSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U5oUkSxQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U6WYkSOt#{uw#{x!_#{!_!`6v!`#O#{#P#T#{#T#o6R#o;'S#{;'S;=`$d<%lO#{U6}UzQkSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U7fZkSOt#{uw#{x!_#{!_!`6v!`#O#{#P#T#{#T#U8X#U#o6R#o;'S#{;'S;=`$d<%lO#{U8^[kSOt#{uw#{x!_#{!_!`6v!`#O#{#P#T#{#T#`6R#`#a9S#a#o6R#o;'S#{;'S;=`$d<%lO#{U9X[kSOt#{uw#{x!_#{!_!`6v!`#O#{#P#T#{#T#g6R#g#h9}#h#o6R#o;'S#{;'S;=`$d<%lO#{U:S[kSOt#{uw#{x!_#{!_!`6v!`#O#{#P#T#{#T#X6R#X#Y:x#Y#o6R#o;'S#{;'S;=`$d<%lO#{U;PYnQkSOt#{uw#{x!_#{!_!`6v!`#O#{#P#T#{#T#o6R#o;'S#{;'S;=`$d<%lO#{^;vY!nWkSOt#{uw#{x!_#{!_!`6v!`#O#{#P#T#{#T#o6R#o;'S#{;'S;=`$d<%lO#{^<mY!pWkSOt#{uw#{x!_#{!_!`6v!`#O#{#P#T#{#T#o6R#o;'S#{;'S;=`$d<%lO#{^=d[!oWkSOt#{uw#{x!_#{!_!`6v!`#O#{#P#T#{#T#f6R#f#g>Y#g#o6R#o;'S#{;'S;=`$d<%lO#{U>_[kSOt#{uw#{x!_#{!_!`6v!`#O#{#P#T#{#T#i6R#i#j9}#j#o6R#o;'S#{;'S;=`$d<%lO#{U?[U{QkSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~?sO!{~",
tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO!d~~", 11)], tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO!f~~", 11)],
topRules: {"Program":[0,18]}, topRules: {"Program":[0,18]},
specialized: [{term: 13, get: (value: any, stack: any) => (specializeKeyword(value, stack) << 1), external: specializeKeyword},{term: 13, get: (value: keyof typeof spec_Identifier) => spec_Identifier[value] || -1}], specialized: [{term: 13, get: (value: any, stack: any) => (specializeKeyword(value, stack) << 1), external: specializeKeyword},{term: 13, get: (value: keyof typeof spec_Identifier) => spec_Identifier[value] || -1}],
tokenPrec: 860 tokenPrec: 924
}) })

View File

@ -0,0 +1,72 @@
import { expect, describe, test } from 'bun:test'
import '../shrimp.grammar' // Importing this so changes cause it to retest!
describe('array literals', () => {
test('work with numbers', () => {
expect('[1 2 3]').toMatchTree(`
Array
Number 1
Number 2
Number 3
`)
})
test('work with strings', () => {
expect("['one' 'two' 'three']").toMatchTree(`
Array
String
StringFragment one
String
StringFragment two
String
StringFragment three
`)
})
test('work with identifiers', () => {
expect('[one two three]').toMatchTree(`
Array
Identifier one
Identifier two
Identifier three
`)
})
test('can be nested', () => {
expect('[one [two [three]]]').toMatchTree(`
Array
Identifier one
Array
Identifier two
Array
Identifier three
`)
})
test('can span multiple lines', () => {
expect(`[
1
2
3
]`).toMatchTree(`
Array
Number 1
Number 2
Number 3
`)
})
test('can span multiple w/o calling functions', () => {
expect(`[
one
two
three
]`).toMatchTree(`
Array
Identifier one
Identifier two
Identifier three
`)
})
})

View File

@ -195,7 +195,13 @@ const isWhiteSpace = (ch: number): boolean => {
} }
const isWordChar = (ch: number): boolean => { const isWordChar = (ch: number): boolean => {
return !isWhiteSpace(ch) && ch !== 10 /* \n */ && ch !== 41 /* ) */ && ch !== -1 /* EOF */ return (
!isWhiteSpace(ch) &&
ch !== 10 /* \n */ &&
ch !== 41 /* ) */ &&
ch !== 93 /* ] */ &&
ch !== -1 /* EOF */
)
} }
const isLowercaseLetter = (ch: number): boolean => { const isLowercaseLetter = (ch: number): boolean => {