Add % operator

This commit is contained in:
Chris Wanstrath 2025-10-29 10:58:48 -07:00
parent d843071bee
commit ced190488a
7 changed files with 71 additions and 50 deletions

View File

@ -220,6 +220,9 @@ export class Compiler {
case '/': case '/':
instructions.push(['DIV']) instructions.push(['DIV'])
break break
case '%':
instructions.push(['MOD'])
break
default: default:
throw new CompilerError(`Unsupported binary operator: ${opValue}`, op.from, op.to) throw new CompilerError(`Unsupported binary operator: ${opValue}`, op.from, op.to)
} }

View File

@ -38,6 +38,12 @@ describe('compiler', () => {
expect('15 / 3').toEvaluateTo(5) expect('15 / 3').toEvaluateTo(5)
}) })
test('modulo', () => {
expect('44 % 2').toEvaluateTo(0)
expect('44 % 3').toEvaluateTo(2)
expect('3 % 4').toEvaluateTo(3)
})
test('assign number', () => { test('assign number', () => {
expect('x = 5').toEvaluateTo(5) expect('x = 5').toEvaluateTo(5)
}) })

View File

@ -17,6 +17,7 @@ const operators: Array<Operator> = [
{ str: '-', tokenName: 'Minus' }, { str: '-', tokenName: 'Minus' },
{ str: '>', tokenName: 'Gt' }, { str: '>', tokenName: 'Gt' },
{ str: '<', tokenName: 'Lt' }, { str: '<', tokenName: 'Lt' },
{ str: '%', tokenName: 'Modulo' },
] ]
export const operatorTokenizer = new ExternalTokenizer((input: InputStream) => { export const operatorTokenizer = new ExternalTokenizer((input: InputStream) => {

View File

@ -6,7 +6,7 @@
@top Program { item* } @top Program { item* }
@external tokens operatorTokenizer from "./operatorTokenizer" { Star, Slash, Plus, Minus, And, Or, Eq, Neq, Lt, Lte, Gt, Gte } @external tokens operatorTokenizer from "./operatorTokenizer" { Star, Slash, Plus, Minus, And, Or, Eq, Neq, Lt, Lte, Gt, Gte, Modulo }
@tokens { @tokens {
@precedence { Number Regex } @precedence { Number Regex }
@ -148,6 +148,7 @@ Assign {
} }
BinOp { BinOp {
expression !multiplicative Modulo expression |
(expression | BinOp) !multiplicative Star (expression | BinOp) | (expression | BinOp) !multiplicative Star (expression | BinOp) |
(expression | BinOp) !multiplicative Slash (expression | BinOp) | (expression | BinOp) !multiplicative Slash (expression | BinOp) |
(expression | BinOp) !additive Plus (expression | BinOp) | (expression | BinOp) !additive Plus (expression | BinOp) |

View File

@ -12,40 +12,41 @@ export const
Lte = 10, Lte = 10,
Gt = 11, Gt = 11,
Gte = 12, Gte = 12,
Identifier = 13, Modulo = 13,
AssignableIdentifier = 14, Identifier = 14,
Word = 15, AssignableIdentifier = 15,
IdentifierBeforeDot = 16, Word = 16,
Do = 17, IdentifierBeforeDot = 17,
Program = 18, Do = 18,
PipeExpr = 19, Program = 19,
FunctionCall = 20, PipeExpr = 20,
DotGet = 21, FunctionCall = 21,
Number = 22, DotGet = 22,
ParenExpr = 23, Number = 23,
FunctionCallOrIdentifier = 24, ParenExpr = 24,
BinOp = 25, FunctionCallOrIdentifier = 25,
String = 26, BinOp = 26,
StringFragment = 27, String = 27,
Interpolation = 28, StringFragment = 28,
EscapeSeq = 29, Interpolation = 29,
Boolean = 30, EscapeSeq = 30,
Regex = 31, Boolean = 31,
Dict = 32, Regex = 32,
NamedArg = 33, Dict = 33,
NamedArgPrefix = 34, NamedArg = 34,
FunctionDef = 35, NamedArgPrefix = 35,
Params = 36, FunctionDef = 36,
colon = 37, Params = 37,
keyword = 52, colon = 38,
Underscore = 39, keyword = 53,
Array = 40, Underscore = 40,
Null = 41, Array = 41,
ConditionalOp = 42, Null = 42,
PositionalArg = 43, ConditionalOp = 43,
IfExpr = 45, PositionalArg = 44,
SingleLineThenBlock = 47, IfExpr = 46,
ThenBlock = 48, SingleLineThenBlock = 48,
ElseIfExpr = 49, ThenBlock = 49,
ElseExpr = 51, ElseIfExpr = 50,
Assign = 53 ElseExpr = 52,
Assign = 54

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,end:76, null:82, if:92, elseif:100, else:104} const spec_Identifier = {__proto__:null,end:78, null:84, if:94, elseif:102, else:106}
export const parser = LRParser.deserialize({ export const parser = LRParser.deserialize({
version: 14, version: 14,
states: "2YQYQbOOO!ZOpO'#CqO#mQcO'#CtO$gOSO'#CvO$uQbO'#ETOOQ`'#DP'#DPOOQa'#C|'#C|O%xQbO'#DUO&}QcO'#DxOOQa'#Dx'#DxO(TQcO'#DwO(lQRO'#CuO(zQcO'#DsO)cQbO'#CsOOQ`'#Dt'#DtO*ZQbO'#DsO*iQbO'#EZOOQ`'#DZ'#DZO+^QRO'#DcOOQ`'#Ds'#DsO+cQQO'#DrOOQ`'#Dr'#DrOOQ`'#Dd'#DdQYQbOOO+kObO,59]O+sQbO'#C}OOQa'#Dw'#DwOOQ`'#DX'#DXOOQ`'#EY'#EYOOQ`'#Dk'#DkO+}QbO,59[O,bQbO'#CxO,jQWO'#CyOOOO'#Dz'#DzOOOO'#De'#DeO-OOSO,59bOOQa,59b,59bOOQ`'#Dg'#DgO-^QbO'#DQO-fQQO,5:oOOQ`'#Df'#DfO-kQbO,59pO-rQQO,59hOOQa,59p,59pO-}QbO,59pO*iQbO,59aO*iQbO,59aO.XQRO,59_O/nQRO'#CuO0OQRO,59_O0[QQO,59_O0aQQO,59_O0iQbO'#DlO0tQbO,59ZO1VQRO,5:uO1^QQO,5:uO1cQbO,59}OOQ`,5:^,5:^OOQ`-E7b-E7bOOQa1G.w1G.wOOQ`,59i,59iOOQ`-E7i-E7iOOOO,59d,59dOOOO,59e,59eOOOO-E7c-E7cOOQa1G.|1G.|OOQ`-E7e-E7eO1mQbO1G0ZOOQ`-E7d-E7dO1zQQO1G/SOOQa1G/[1G/[O2VQbO1G/[OOQO'#Di'#DiO1zQQO1G/SOOQa1G/S1G/SOOQ`'#Dj'#DjO2VQbO1G/[OOQa1G.{1G.{O2aQcO1G.{OOQa1G.y1G.yO*iQbO,59rO*iQbO,59rO!`QbO'#CtO&PQbO'#CpOOQ`,5:W,5:WOOQ`-E7j-E7jO2{QbO1G0aOOQ`1G/i1G/iO3YQbO7+%uO3_QbO7+%vO3oQQO7+$nOOQa7+$n7+$nO3zQbO7+$vOOQa7+$v7+$vOOQO-E7g-E7gOOQ`-E7h-E7hOOQO1G/^1G/^O4UQRO1G/^OOQ`'#D]'#D]O4`QbO7+%{O4eQbO7+%|OOQ`<<Ia<<IaOOQ`'#Dh'#DhO4{QQO'#DhO5QQbO'#EVO5hQbO<<IbOOQa<<HY<<HYOOQa<<Hb<<HbOOQ`<<Ig<<IgOOQ`'#D^'#D^O5mQbO<<IhOOQ`,5:S,5:SOOQ`-E7f-E7fOOQ`AN>|AN>|O*iQbO'#D_OOQ`'#Dm'#DmO5xQbOAN?SO6TQQO'#DaOOQ`AN?SAN?SO6YQbOAN?SO6_QRO,59yO6fQQO,59yOOQ`-E7k-E7kOOQ`G24nG24nO6kQbOG24nO6pQQO,59{O6uQQO1G/eOOQ`LD*YLD*YO3_QbO1G/gO4eQbO7+%POOQ`7+%R7+%ROOQ`<<Hk<<Hk", states: "2lQYQbOOO!ZOpO'#CrO#mQcO'#CuO$jOSO'#CwO$xQbO'#EUOOQ`'#DQ'#DQOOQa'#C}'#C}O%{QbO'#DVO'QQcO'#DyOOQa'#Dy'#DyO(lQcO'#DxO(yQRO'#CvO)[QcO'#DtO)sQbO'#CtOOQ`'#Du'#DuO*kQbO'#DtO*yQbO'#E[OOQ`'#D['#D[O+nQRO'#DdOOQ`'#Dt'#DtO+sQQO'#DsOOQ`'#Ds'#DsOOQ`'#De'#DeQYQbOOO+{ObO,59^O,TQbO'#DOOOQa'#Dx'#DxOOQ`'#DY'#DYOOQ`'#EZ'#EZOOQ`'#Dl'#DlO,_QbO,59]O,rQbO'#CyO,zQWO'#CzOOOO'#D{'#D{OOOO'#Df'#DfO-`OSO,59cOOQa,59c,59cOOQ`'#Dh'#DhO-nQbO'#DRO-vQQO,5:pOOQ`'#Dg'#DgO-{QbO,59qO.SQQO,59iOOQa,59q,59qO._QbO,59qO*yQbO,59bO*yQbO,59bO*yQbO,59bO.iQRO,59`O/YQRO'#CvO/vQRO,59`O0SQQO,59`O0XQQO,59`O0aQbO'#DmO0lQbO,59[O1iQRO,5:vO1pQQO,5:vO1uQbO,5:OOOQ`,5:_,5:_OOQ`-E7c-E7cOOQa1G.x1G.xOOQ`,59j,59jOOQ`-E7j-E7jOOOO,59e,59eOOOO,59f,59fOOOO-E7d-E7dOOQa1G.}1G.}OOQ`-E7f-E7fO2PQbO1G0[OOQ`-E7e-E7eO2^QQO1G/TOOQa1G/]1G/]O2iQbO1G/]OOQO'#Dj'#DjO2^QQO1G/TOOQa1G/T1G/TOOQ`'#Dk'#DkO2iQbO1G/]OOQa1G.|1G.|O3[QcO1G.|O3fQcO1G.|O3pQcO1G.|OOQa1G.z1G.zO*yQbO,59sO*yQbO,59sO!`QbO'#CuO&SQbO'#CqOOQ`,5:X,5:XOOQ`-E7k-E7kO4[QbO1G0bOOQ`1G/j1G/jO4iQbO7+%vO4nQbO7+%wO5OQQO7+$oOOQa7+$o7+$oO5ZQbO7+$wOOQa7+$w7+$wOOQO-E7h-E7hOOQ`-E7i-E7iOOQO1G/_1G/_O5eQRO1G/_OOQ`'#D^'#D^O5oQbO7+%|O5tQbO7+%}OOQ`<<Ib<<IbOOQ`'#Di'#DiO6[QQO'#DiO6aQbO'#EWO6wQbO<<IcOOQa<<HZ<<HZOOQa<<Hc<<HcOOQ`<<Ih<<IhOOQ`'#D_'#D_O6|QbO<<IiOOQ`,5:T,5:TOOQ`-E7g-E7gOOQ`AN>}AN>}O*yQbO'#D`OOQ`'#Dn'#DnO7XQbOAN?TO7dQQO'#DbOOQ`AN?TAN?TO7iQbOAN?TO7nQRO,59zO7uQQO,59zOOQ`-E7l-E7lOOQ`G24oG24oO7zQbOG24oO8PQQO,59|O8UQQO1G/fOOQ`LD*ZLD*ZO4nQbO1G/hO5tQbO7+%QOOQ`7+%S7+%SOOQ`<<Hl<<Hl",
stateData: "6}~O!dOS!eOS~O]QO^bO_XO`POaSOfXOnXOoXOyXO!O`O!j]O!mRO!tUO!uVO!veO~O!ihO~O]jO_XO`POaSOfXOnXOoXOriOwkOyXO!j]O!mRO!tUO!uVO|hX!vhX#PhX!{hXvhX~OP!kXQ!kXR!kXS!kXT!kXU!kXV!kXW!kXX!kXY!kXZ!kX[!kX~P!`OkqO!mtO!ooO!ppO~O]uOutP~O]jO_XO`POfXOnXOoXOriOyXO!j]O!mRO!tUO!uVO!vxO~O!z{O~P$}O]jO_XO`POaSOfXOnXOoXOriOwkOyXO!j]O!mRO!tUO!uVO~OP!lXQ!lXR!lXS!lX!v!lX#P!lXT!lXU!lXV!lXW!lXX!lXY!lXZ!lX[!lX!{!lXv!lX~P&POP!kXQ!kXR!kXS!kX!v!gX#P!gXv!gX~OP}OQ}OR!OOS!OO~OP}OQ}OR!OOS!OO!v!gX#P!gXv!gX~O]QO_XO`POaSOfXOnXOoXOyXO!j]O!mRO!tUO!uVO~O|!UO!v!gX#P!gXv!gX~O]jO_XO`POfXOnXOoXOyXO!j]O!mRO!tUO!uVO~OV!YO~O!v!ZO#P!ZO~O]!]Of!]O~OaSOw!^O~P*iO|da!vda#Pda!{davda~P&PO]!`O!j]O~O!m!aO!o!aO!p!aO!q!aO!r!aO!s!aO~OkqO!m!cO!ooO!ppO~O]uOutX~Ou!eO~O!z!hO~P$}OriO!v!jO!z!lO~O!v!mO!z!hO~P*iO!{!qOP!kXQ!kXR!kXS!kXT!kXU!kXV!kXW!kXX!kXY!kXZ!kX[!kX~OT!sOU!sOV!rOW!rOX!rOY!rOZ!rO[!rO~OP}OQ}OR!OOS!OO~P/SOP}OQ}OR!OOS!OO!{!qO~O|!UO!{!qO~O]!tO`PO!j]O~O|!UO!vca#Pca!{cavca~Ou!xO~P/SOu!xO~O^bO!O`O~P)cO^bO!O`O!v!{O~P)cOriO!v!jO!z!}O~O!v!mO!z#PO~P*iOP}OQ}ORiiSii!vii#Pii!{iivii~O^bO!O`O!v#WO~P)cOv#XO~O^bO!O`O!v#YOv!yP~P)cOriO!v!jO!z#^O~O!v!mO!z#_O~P*iO!{ziuzi~P/SOv#`O~O^bO!O`O!v#YOv!yP!S!yP!U!yP~P)cO!v#cO~O^bO!O`O!v#YOv!yX!S!yX!U!yX~P)cOv#eO~Ov#jO!S#fO!U#iO~Ov#oO!S#fO!U#iO~Ou#qO~Ov#oO~Ou#rO~P/SOu#rO~Ov#sO~O!v#tO~O!v#uO~Ofo~", stateData: "8^~O!eOS!fOS~O^QO_bO`XOaPObSOgXOoXOpXOzXO!P`O!k]O!nRO!uUO!vVO!weO~O!jhO~O^jO`XOaPObSOgXOoXOpXOsiOxkOzXO!k]O!nRO!uUO!vVO}iX!wiX#QiX!|iXwiX~OP!lXQ!lXR!lXS!lX]!lXT!lXU!lXV!lXW!lXX!lXY!lXZ!lX[!lX~P!`OlqO!ntO!poO!qpO~O^uOvuP~O^jO`XOaPOgXOoXOpXOsiOzXO!k]O!nRO!uUO!vVO!wxO~O!{{O~P%QO^jO`XOaPObSOgXOoXOpXOsiOxkOzXO!k]O!nRO!uUO!vVO~OP!mXQ!mXR!mXS!mX]!mX!w!mX#Q!mXT!mXU!mXV!mXW!mXX!mXY!mXZ!mX[!mX!|!mXw!mX~P&SOP!lXQ!lXR!lXS!lX]!lX~O!w!hX#Q!hXw!hX~P(ZOP!OOQ!OOR!POS!PO]}O~OP!OOQ!OOR!POS!PO!w!hX#Q!hXw!hX~O^QO`XOaPObSOgXOoXOpXOzXO!k]O!nRO!uUO!vVO~O}!VO!w!hX#Q!hXw!hX~O^jO`XOaPOgXOoXOpXOzXO!k]O!nRO!uUO!vVO~OV!ZO~O!w![O#Q![O~O^!^Og!^O~ObSOx!_O~P*yO}ea!wea#Qea!|eawea~P&SO^!aO!k]O~O!n!bO!p!bO!q!bO!r!bO!s!bO!t!bO~OlqO!n!dO!poO!qpO~O^uOvuX~Ov!fO~O!{!iO~P%QOsiO!w!kO!{!mO~O!w!nO!{!iO~P*yO!|!tOT!lXU!lXV!lXW!lXX!lXY!lXZ!lX[!lX~P(ZOT!vOU!vOV!uOW!uOX!uOY!uOZ!uO[!uO~P(yOP!OOQ!OOR!POS!PO!|!tO~O}!VO!|!tO~O^!wOaPO!k]O~O}!VO!wda#Qda!|dawda~OT!vOU!vOV!uOW!uOX!uOY!uOZ!uO[!uO~Ov!{O~P0}Ov!{O~O_bO!P`O~P)sO_bO!P`O!w#OO~P)sOsiO!w!kO!{#QO~O!w!nO!{#SO~P*yO]}ORjiSji!wji#Qji!|jiwji~OPjiQji~P2sOP!OOQ!OO~P2sOP!OOQ!OORjiSji!wji#Qji!|jiwji~O_bO!P`O!w#ZO~P)sOw#[O~O_bO!P`O!w#]Ow!zP~P)sOsiO!w!kO!{#aO~O!w!nO!{#bO~P*yO!|{iv{i~P0}Ow#cO~O_bO!P`O!w#]Ow!zP!T!zP!V!zP~P)sO!w#fO~O_bO!P`O!w#]Ow!zX!T!zX!V!zX~P)sOw#hO~Ow#mO!T#iO!V#lO~Ow#rO!T#iO!V#lO~Ov#tO~Ow#rO~Ov#uO~P0}Ov#uO~Ow#vO~O!w#wO~O!w#xO~Ogp~",
goto: ".]#PPPPPPPPPPPPPPPPPPPP#Q#a#oP$e#a%^%sP&d&dPP%s&hP&{'fPPP%sP'i'uP'|P(Y(](fP(jP'|(p(v(|)S)Y)c)m)w*Q*XPPPP*_*c*wPP+Z,dP-XPPPPPPPP-]-]-pPP-x.P.PdcOg!Y!e!x!{#W#[#t#uR!S]i^O]g!U!Y!e!x!{#W#[#t#ufQO]g!Y!e!x!{#W#[#t#utjQVW`iny|}!O!i!n!r!s!t!u#O#fR!t!UfWO]g!Y!e!x!{#W#[#t#utXQVW`iny|}!O!i!n!r!s!t!u#O#fQ!`oR!u!Ud[Og!Y!e!x!{#W#[#t#uQ!R]Q!o}R!p!O!]XOQVW]`giny|}!O!Y!e!i!n!r!s!t!u!x!{#O#W#[#f#t#uTqRsYlQWn!t!uQzVQ!gyX!jz!g!k!|dcOg!Y!e!x!{#W#[#t#uYkQWn!t!uQ!S]R!^iRwSQ!S]Q!X`Q#S!sR#m#fZlQWn!t!uecOg!Y!e!x!{#W#[#t#uR#V!xQ#b#WQ#v#tR#w#uT#g#b#hQ#k#bR#p#hQgOR![gQsRR!bsQyVR!fyQvSR!dvW#[!{#W#t#uR#d#[Q!kzQ!|!gT#Q!k!|Q!n|Q#O!iT#R!n#OWnQW!t!uR!_nS!V_!TR!w!VQ#h#bR#n#hTfOgSdOgQ!y!YQ!z!eQ#U!xZ#Z!{#W#[#t#ud_Og!Y!e!x!{#W#[#t#uQ!T]R!v!UdZOg!Y!e!x!{#W#[#t#uYkQWn!t!uQ|VQ!Q]Q!W`Q!^iQ!iyW!m|!i!n#OQ!o}Q!p!OQ#S!rQ#T!sR#l#fdYOg!Y!e!x!{#W#[#t#utjQVW`iny|}!O!i!n!r!s!t!u#O#fR!P]TrRssTOQW]gin!Y!e!t!u!x!{#W#[#t#uQ#]!{V#a#W#t#uZmQWn!t!ueaOg!Y!e!x!{#W#[#t#u", goto: ".e#QPPPPPPPPPPPPPPPPPPPP#R#b#pP$g#b%a%vP&h&hPP%v&lP'P'jPPP%vP'm'yP(QP(^(a(jP(nP(Q(t(z)Q)W)^)g)q){*U*]PPPP*c*g*{PP+_,kP-aPPPPPPPP-e-e-xPP.Q.X.XdcOg!Z!f!{#O#Z#_#w#xR!T]i^O]g!V!Z!f!{#O#Z#_#w#xfQO]g!Z!f!{#O#Z#_#w#xvjQVW`iny|}!O!P!j!o!u!v!w!x#R#iR!w!VfWO]g!Z!f!{#O#Z#_#w#xvXQVW`iny|}!O!P!j!o!u!v!w!x#R#iQ!aoR!x!Vd[Og!Z!f!{#O#Z#_#w#xQ!S]Q!p!OR!s!P!_XOQVW]`giny|}!O!P!Z!f!j!o!u!v!w!x!{#O#R#Z#_#i#w#xTqRsYlQWn!w!xQzVQ!hyX!kz!h!l#PdcOg!Z!f!{#O#Z#_#w#xYkQWn!w!xQ!T]R!_iRwSQ!T]Q!Y`Q#V!vR#p#iZlQWn!w!xecOg!Z!f!{#O#Z#_#w#xR#Y!{Q#e#ZQ#y#wR#z#xT#j#e#kQ#n#eR#s#kQgOR!]gQsRR!csQyVR!gyQvSR!evW#_#O#Z#w#xR#g#_Q!lzQ#P!hT#T!l#PQ!o|Q#R!jT#U!o#RWnQW!w!xR!`nS!W_!UR!z!WQ#k#eR#q#kTfOgSdOgQ!|!ZQ!}!fQ#X!{Z#^#O#Z#_#w#xd_Og!Z!f!{#O#Z#_#w#xQ!U]R!y!VdZOg!Z!f!{#O#Z#_#w#xYkQWn!w!xQ|VQ!R]Q!X`Q!_iQ!jyW!n|!j!o#RQ!p}Q!q!OQ!r!PQ#V!uQ#W!vR#o#idYOg!Z!f!{#O#Z#_#w#xvjQVW`iny|}!O!P!j!o!u!v!w!x#R#iR!Q]TrRssTOQW]gin!Z!f!w!x!{#O#Z#_#w#xQ#`#OV#d#Z#w#xZmQWn!w!xeaOg!Z!f!{#O#Z#_#w#x",
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 Dict NamedArg NamedArgPrefix FunctionDef Params colon keyword Underscore Array Null ConditionalOp PositionalArg operator IfExpr keyword SingleLineThenBlock ThenBlock ElseIfExpr keyword ElseExpr keyword Assign", nodeNames: "⚠ Star Slash Plus Minus And Or Eq Neq Lt Lte Gt Gte Modulo Identifier AssignableIdentifier Word IdentifierBeforeDot Do Program PipeExpr FunctionCall DotGet Number ParenExpr FunctionCallOrIdentifier BinOp String StringFragment Interpolation EscapeSeq Boolean Regex Dict NamedArg NamedArgPrefix FunctionDef Params colon keyword Underscore Array Null ConditionalOp PositionalArg operator IfExpr keyword SingleLineThenBlock ThenBlock ElseIfExpr keyword ElseExpr keyword Assign",
maxTerm: 93, maxTerm: 94,
context: trackScope, context: trackScope,
nodeProps: [ nodeProps: [
["closedBy", 37,"end"] ["closedBy", 38,"end"]
], ],
propSources: [highlighting], propSources: [highlighting],
skippedNodes: [0], skippedNodes: [0],
repeatNodeCount: 10, repeatNodeCount: 10,
tokenData: "AO~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#P6T#P#Q6Y#Q#R#{#R#S6s#S#T#{#T#Y7^#Y#Z8l#Z#b7^#b#c<z#c#f7^#f#g=q#g#h7^#h#i>h#i#o7^#o#p#{#p#q@`#q;'S#{;'S;=`$d<%l~#{~O#{~~@yS$QUkSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{S$gP;=`<%l#{^$qUkS!dYOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U%[UkS!vQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^%uZkS!eYOY%nYZ#{Zt%ntu&huw%nwx&hx#O%n#O#P&h#P;'S%n;'S;=`'P<%lO%nY&mS!eYOY&hZ;'S&h;'S;=`&y<%lO&hY&|P;=`<%l&h^'SP;=`<%l%n~'[O!o~~'aO!m~U'hUkS!jQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(RUkS!{QOt#{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#{U4fW!uQkSOt#{uw#{x!_#{!_!`5O!`#O#{#P;'S#{;'S;=`$d<%lO#{U5TVkSOt#{uw#{x#O#{#P#Q5j#Q;'S#{;'S;=`$d<%lO#{U5qU!tQkSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~6YO!p~U6aU!zQkSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U6zUkSwQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U7cYkSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#o7^#o;'S#{;'S;=`$d<%lO#{U8YUrQkSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U8qZkSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#U9d#U#o7^#o;'S#{;'S;=`$d<%lO#{U9i[kSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#`7^#`#a:_#a#o7^#o;'S#{;'S;=`$d<%lO#{U:d[kSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#g7^#g#h;Y#h#o7^#o;'S#{;'S;=`$d<%lO#{U;_[kSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#X7^#X#Y<T#Y#o7^#o;'S#{;'S;=`$d<%lO#{U<[YnQkSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#o7^#o;'S#{;'S;=`$d<%lO#{^=RY!qWkSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#o7^#o;'S#{;'S;=`$d<%lO#{^=xY!sWkSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#o7^#o;'S#{;'S;=`$d<%lO#{^>o[!rWkSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#f7^#f#g?e#g#o7^#o;'S#{;'S;=`$d<%lO#{U?j[kSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#i7^#i#j;Y#j#o7^#o;'S#{;'S;=`$d<%lO#{U@gU|QkSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~AOO#P~", tokenData: "AO~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#P6T#P#Q6Y#Q#R#{#R#S6s#S#T#{#T#Y7^#Y#Z8l#Z#b7^#b#c<z#c#f7^#f#g=q#g#h7^#h#i>h#i#o7^#o#p#{#p#q@`#q;'S#{;'S;=`$d<%l~#{~O#{~~@yS$QUlSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{S$gP;=`<%l#{^$qUlS!eYOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U%[UlS!wQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^%uZlS!fYOY%nYZ#{Zt%ntu&huw%nwx&hx#O%n#O#P&h#P;'S%n;'S;=`'P<%lO%nY&mS!fYOY&hZ;'S&h;'S;=`&y<%lO&hY&|P;=`<%l&h^'SP;=`<%l%n~'[O!p~~'aO!n~U'hUlS!kQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(RUlS!|QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(jWlSOt#{uw#{x!Q#{!Q![)S![#O#{#P;'S#{;'S;=`$d<%lO#{U)ZYlSgQOt#{uw#{x!O#{!O!P)y!P!Q#{!Q![)S![#O#{#P;'S#{;'S;=`$d<%lO#{U*OWlSOt#{uw#{x!Q#{!Q![*h![#O#{#P;'S#{;'S;=`$d<%lO#{U*oWlSgQOt#{uw#{x!Q#{!Q![*h![#O#{#P;'S#{;'S;=`$d<%lO#{U+^WlSOt#{uw#{x!P#{!P!Q+v!Q#O#{#P;'S#{;'S;=`$d<%lO#{U+{^lSOY,wYZ#{Zt,wtu-zuw,wwx-zx!P,w!P!Q#{!Q!},w!}#O2m#O#P0Y#P;'S,w;'S;=`3n<%lO,wU-O^lSpQOY,wYZ#{Zt,wtu-zuw,wwx-zx!P,w!P!Q0o!Q!},w!}#O2m#O#P0Y#P;'S,w;'S;=`3n<%lO,wQ.PXpQOY-zZ!P-z!P!Q.l!Q!}-z!}#O/Z#O#P0Y#P;'S-z;'S;=`0i<%lO-zQ.oP!P!Q.rQ.wUpQ#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-zU0tWlSOt#{uw#{x!P#{!P!Q1^!Q#O#{#P;'S#{;'S;=`$d<%lO#{U1eblSpQOt#{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[lSOY2mYZ#{Zt2mtu/Zuw2mwx/Zx#O2m#O#P/s#P#Q,w#Q;'S2m;'S;=`3h<%lO2mU3kP;=`<%l2mU3qP;=`<%l,wU3{UlSvQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U4fW!vQlSOt#{uw#{x!_#{!_!`5O!`#O#{#P;'S#{;'S;=`$d<%lO#{U5TVlSOt#{uw#{x#O#{#P#Q5j#Q;'S#{;'S;=`$d<%lO#{U5qU!uQlSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~6YO!q~U6aU!{QlSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U6zUlSxQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U7cYlSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#o7^#o;'S#{;'S;=`$d<%lO#{U8YUsQlSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U8qZlSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#U9d#U#o7^#o;'S#{;'S;=`$d<%lO#{U9i[lSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#`7^#`#a:_#a#o7^#o;'S#{;'S;=`$d<%lO#{U:d[lSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#g7^#g#h;Y#h#o7^#o;'S#{;'S;=`$d<%lO#{U;_[lSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#X7^#X#Y<T#Y#o7^#o;'S#{;'S;=`$d<%lO#{U<[YoQlSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#o7^#o;'S#{;'S;=`$d<%lO#{^=RY!rWlSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#o7^#o;'S#{;'S;=`$d<%lO#{^=xY!tWlSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#o7^#o;'S#{;'S;=`$d<%lO#{^>o[!sWlSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#f7^#f#g?e#g#o7^#o;'S#{;'S;=`$d<%lO#{U?j[lSOt#{uw#{x!_#{!_!`8R!`#O#{#P#T#{#T#i7^#i#j;Y#j#o7^#o;'S#{;'S;=`$d<%lO#{U@gU}QlSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~AOO#Q~",
tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO!i~~", 11)], tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO!j~~", 11)],
topRules: {"Program":[0,18]}, topRules: {"Program":[0,19]},
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: 14, get: (value: any, stack: any) => (specializeKeyword(value, stack) << 1), external: specializeKeyword},{term: 14, get: (value: keyof typeof spec_Identifier) => spec_Identifier[value] || -1}],
tokenPrec: 1008 tokenPrec: 1069
}) })

View File

@ -408,6 +408,15 @@ describe('BinOp', () => {
`) `)
}) })
test('modulo tests', () => {
expect('4 % 3').toMatchTree(`
BinOp
Number 4
Modulo %
Number 3
`)
})
test('mixed operations with precedence', () => { test('mixed operations with precedence', () => {
expect('2 + 3 * 4 - 5 / 1').toMatchTree(` expect('2 + 3 * 4 - 5 / 1').toMatchTree(`
BinOp BinOp