hex and binary numbers
This commit is contained in:
parent
7da437212d
commit
4eafa00648
|
|
@ -105,11 +105,21 @@ export class Compiler {
|
|||
|
||||
switch (node.type.id) {
|
||||
case terms.Number:
|
||||
const number = Number(value)
|
||||
if (Number.isNaN(number))
|
||||
// Handle sign prefix for hex and binary literals
|
||||
// Number() doesn't parse '-0xFF' or '+0xFF' correctly
|
||||
let numberValue: number
|
||||
if (value.startsWith('-') && (value.includes('0x') || value.includes('0b'))) {
|
||||
numberValue = -Number(value.slice(1))
|
||||
} else if (value.startsWith('+') && (value.includes('0x') || value.includes('0b'))) {
|
||||
numberValue = Number(value.slice(1))
|
||||
} else {
|
||||
numberValue = Number(value)
|
||||
}
|
||||
|
||||
if (Number.isNaN(numberValue))
|
||||
throw new CompilerError(`Invalid number literal: ${value}`, node.from, node.to)
|
||||
|
||||
return [[`PUSH`, number]]
|
||||
return [[`PUSH`, numberValue]]
|
||||
|
||||
case terms.String: {
|
||||
const { parts, hasInterpolation } = getStringParts(node, input)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,44 @@
|
|||
import { describe } from 'bun:test'
|
||||
import { expect, test } from 'bun:test'
|
||||
|
||||
describe('number literals', () => {
|
||||
test('binary literals', () => {
|
||||
expect('0b110').toEvaluateTo(6)
|
||||
expect('0b1010').toEvaluateTo(10)
|
||||
expect('0b11111111').toEvaluateTo(255)
|
||||
expect('0b0').toEvaluateTo(0)
|
||||
expect('0b1').toEvaluateTo(1)
|
||||
})
|
||||
|
||||
test('hex literals', () => {
|
||||
expect('0xdeadbeef').toEvaluateTo(0xdeadbeef)
|
||||
expect('0xdeadbeef').toEvaluateTo(3735928559)
|
||||
expect('0xFF').toEvaluateTo(255)
|
||||
expect('0xff').toEvaluateTo(255)
|
||||
expect('0x10').toEvaluateTo(16)
|
||||
expect('0x0').toEvaluateTo(0)
|
||||
expect('0xABCDEF').toEvaluateTo(0xabcdef)
|
||||
})
|
||||
|
||||
test('decimal literals still work', () => {
|
||||
expect('42').toEvaluateTo(42)
|
||||
expect('3.14').toEvaluateTo(3.14)
|
||||
expect('0').toEvaluateTo(0)
|
||||
expect('999999').toEvaluateTo(999999)
|
||||
})
|
||||
|
||||
test('negative hex and binary', () => {
|
||||
expect('-0xFF').toEvaluateTo(-255)
|
||||
expect('-0b1010').toEvaluateTo(-10)
|
||||
})
|
||||
|
||||
test('positive prefix', () => {
|
||||
expect('+0xFF').toEvaluateTo(255)
|
||||
expect('+0b110').toEvaluateTo(6)
|
||||
expect('+42').toEvaluateTo(42)
|
||||
})
|
||||
})
|
||||
|
||||
describe('array literals', () => {
|
||||
test('work with numbers', () => {
|
||||
expect('[1 2 3]').toEvaluateTo([1, 2, 3])
|
||||
|
|
|
|||
|
|
@ -13,7 +13,11 @@
|
|||
|
||||
StringFragment { !['\\$]+ }
|
||||
NamedArgPrefix { $[a-z-]+ "=" }
|
||||
Number { ("-" | "+")? $[0-9]+ ('.' $[0-9]+)? }
|
||||
Number {
|
||||
("-" | "+")? "0x" $[0-9a-fA-F]+ |
|
||||
("-" | "+")? "0b" $[01]+ |
|
||||
("-" | "+")? $[0-9]+ ('.' $[0-9]+)?
|
||||
}
|
||||
Boolean { "true" | "false" }
|
||||
newlineOrSemicolon { "\n" | ";" }
|
||||
eof { @eof }
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export const parser = LRParser.deserialize({
|
|||
propSources: [highlighting],
|
||||
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$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#{^%uZiY|SOY%nYZ#{Zt%ntu&huw%nwx&hx#O%n#O#P&h#P;'S%n;'S;=`'P<%lO%nY&mSiYOY&hZ;'S&h;'S;=`&y<%lO&hY&|P;=`<%l&h^'SP;=`<%l%n~'[O#T~~'aO#R~U'hU|S!}QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(RU|S#]QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(jW|SOt#{uw#{x!Q#{!Q![)S![#O#{#P;'S#{;'S;=`$d<%lO#{U)ZY|SuQOt#{uw#{x!O#{!O!P)y!P!Q#{!Q![)S![#O#{#P;'S#{;'S;=`$d<%lO#{U*OW|SOt#{uw#{x!Q#{!Q![*h![#O#{#P;'S#{;'S;=`$d<%lO#{U*oW|SuQOt#{uw#{x!Q#{!Q![*h![#O#{#P;'S#{;'S;=`$d<%lO#{U+^^|SOt#{uw#{x}#{}!O,Y!O!Q#{!Q![)S![!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{U,_[|SOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{U-[UzQ|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U-sW|SOt#{uw#{x!P#{!P!Q.]!Q#O#{#P;'S#{;'S;=`$d<%lO#{U.b^|SOY/^YZ#{Zt/^tu0auw/^wx0ax!P/^!P!Q#{!Q!}/^!}#O5S#O#P2o#P;'S/^;'S;=`6T<%lO/^U/e^|S!aQOY/^YZ#{Zt/^tu0auw/^wx0ax!P/^!P!Q3U!Q!}/^!}#O5S#O#P2o#P;'S/^;'S;=`6T<%lO/^Q0fX!aQOY0aZ!P0a!P!Q1R!Q!}0a!}#O1p#O#P2o#P;'S0a;'S;=`3O<%lO0aQ1UP!P!Q1XQ1^U!aQ#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;=`<%l0aU3ZW|SOt#{uw#{x!P#{!P!Q3s!Q#O#{#P;'S#{;'S;=`$d<%lO#{U3zb|S!aQOt#{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[|SOY5SYZ#{Zt5Stu1puw5Swx1px#O5S#O#P2Y#P#Q/^#Q;'S5S;'S;=`5}<%lO5SU6QP;=`<%l5SU6WP;=`<%l/^U6bU|S!RQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U6{W#_Q|SOt#{uw#{x!_#{!_!`7e!`#O#{#P;'S#{;'S;=`$d<%lO#{U7jV|SOt#{uw#{x#O#{#P#Q8P#Q;'S#{;'S;=`$d<%lO#{U8WU#^Q|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~8oO#U~U8vU#`Q|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U9aU|S!YQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U9x]|SOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#U:q#U#o,Y#o;'S#{;'S;=`$d<%lO#{U:v^|SOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#`,Y#`#a;r#a#o,Y#o;'S#{;'S;=`$d<%lO#{U;w^|SOt#{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^|SOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#X,Y#X#Y=t#Y#o,Y#o;'S#{;'S;=`$d<%lO#{U={[!PQ|SOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{^>x[#VW|SOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{^?u[#XW|SOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#o,Y#o;'S#{;'S;=`$d<%lO#{^@r^#WW|SOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#f,Y#f#gAn#g#o,Y#o;'S#{;'S;=`$d<%lO#{UAs^|SOt#{uw#{x}#{}!O,Y!O!_#{!_!`-T!`#O#{#P#T#{#T#i,Y#i#j<s#j#o,Y#o;'S#{;'S;=`$d<%lO#{UBvUlQ|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~C_O#a~",
|
||||
tokenData: "Gw~R}OX$OXY$mYZ%WZp$Opq$mqs$Ost%qtu'Yuw$Owx'_xy'dyz'}z{$O{|(h|}$O}!O/n!O!P$O!P!Q2W!Q!R)Y!R![+k![!]:s!]!^%W!^!}$O!}#O;^#O#P=S#P#Q=X#Q#R$O#R#S=r#S#T$O#T#Y0r#Y#Z>]#Z#b0r#b#cCZ#c#f0r#f#gDW#g#h0r#h#iET#i#o0r#o#p$O#p#qGX#q;'S$O;'S;=`$g<%l~$O~O$O~~GrS$TU|SOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OS$jP;=`<%l$O^$tU|S!xYOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU%_U|S#YQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O^%xZiY|SOY%qYZ$OZt%qtu&kuw%qwx&kx#O%q#O#P&k#P;'S%q;'S;=`'S<%lO%qY&pSiYOY&kZ;'S&k;'S;=`&|<%lO&kY'PP;=`<%l&k^'VP;=`<%l%q~'_O#T~~'dO#R~U'kU|S!}QOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU(UU|S#]QOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU(mX|SOt$Ouw$Ox!Q$O!Q!R)Y!R![+k![#O$O#P;'S$O;'S;=`$g<%lO$OU)a^|SuQOt$Ouw$Ox!O$O!O!P*]!P!Q$O!Q![+k![#O$O#P#U$O#U#V,b#V#l$O#l#m-v#m;'S$O;'S;=`$g<%lO$OU*bW|SOt$Ouw$Ox!Q$O!Q![*z![#O$O#P;'S$O;'S;=`$g<%lO$OU+RW|SuQOt$Ouw$Ox!Q$O!Q![*z![#O$O#P;'S$O;'S;=`$g<%lO$OU+rY|SuQOt$Ouw$Ox!O$O!O!P*]!P!Q$O!Q![+k![#O$O#P;'S$O;'S;=`$g<%lO$OU,gX|SOt$Ouw$Ox!Q$O!Q!R-S!R!S-S!S#O$O#P;'S$O;'S;=`$g<%lO$OU-ZX|SuQOt$Ouw$Ox!Q$O!Q!R-S!R!S-S!S#O$O#P;'S$O;'S;=`$g<%lO$OU-{[|SOt$Ouw$Ox!Q$O!Q![.q![!c$O!c!i.q!i#O$O#P#T$O#T#Z.q#Z;'S$O;'S;=`$g<%lO$OU.x[|SuQOt$Ouw$Ox!Q$O!Q![.q![!c$O!c!i.q!i#O$O#P#T$O#T#Z.q#Z;'S$O;'S;=`$g<%lO$OU/s_|SOt$Ouw$Ox}$O}!O0r!O!Q$O!Q!R)Y!R![+k![!_$O!_!`1m!`#O$O#P#T$O#T#o0r#o;'S$O;'S;=`$g<%lO$OU0w[|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#o0r#o;'S$O;'S;=`$g<%lO$OU1tUzQ|SOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU2]W|SOt$Ouw$Ox!P$O!P!Q2u!Q#O$O#P;'S$O;'S;=`$g<%lO$OU2z^|SOY3vYZ$OZt3vtu4yuw3vwx4yx!P3v!P!Q$O!Q!}3v!}#O9l#O#P7X#P;'S3v;'S;=`:m<%lO3vU3}^|S!aQOY3vYZ$OZt3vtu4yuw3vwx4yx!P3v!P!Q7n!Q!}3v!}#O9l#O#P7X#P;'S3v;'S;=`:m<%lO3vQ5OX!aQOY4yZ!P4y!P!Q5k!Q!}4y!}#O6Y#O#P7X#P;'S4y;'S;=`7h<%lO4yQ5nP!P!Q5qQ5vU!aQ#Z#[5q#]#^5q#a#b5q#g#h5q#i#j5q#m#n5qQ6]VOY6YZ#O6Y#O#P6r#P#Q4y#Q;'S6Y;'S;=`7R<%lO6YQ6uSOY6YZ;'S6Y;'S;=`7R<%lO6YQ7UP;=`<%l6YQ7[SOY4yZ;'S4y;'S;=`7h<%lO4yQ7kP;=`<%l4yU7sW|SOt$Ouw$Ox!P$O!P!Q8]!Q#O$O#P;'S$O;'S;=`$g<%lO$OU8db|S!aQOt$Ouw$Ox#O$O#P#Z$O#Z#[8]#[#]$O#]#^8]#^#a$O#a#b8]#b#g$O#g#h8]#h#i$O#i#j8]#j#m$O#m#n8]#n;'S$O;'S;=`$g<%lO$OU9q[|SOY9lYZ$OZt9ltu6Yuw9lwx6Yx#O9l#O#P6r#P#Q3v#Q;'S9l;'S;=`:g<%lO9lU:jP;=`<%l9lU:pP;=`<%l3vU:zU|S!RQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU;eW#_Q|SOt$Ouw$Ox!_$O!_!`;}!`#O$O#P;'S$O;'S;=`$g<%lO$OU<SV|SOt$Ouw$Ox#O$O#P#Q<i#Q;'S$O;'S;=`$g<%lO$OU<pU#^Q|SOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O~=XO#U~U=`U#`Q|SOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU=yU|S!YQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU>b]|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#U?Z#U#o0r#o;'S$O;'S;=`$g<%lO$OU?`^|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#`0r#`#a@[#a#o0r#o;'S$O;'S;=`$g<%lO$OU@a^|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#g0r#g#hA]#h#o0r#o;'S$O;'S;=`$g<%lO$OUAb^|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#X0r#X#YB^#Y#o0r#o;'S$O;'S;=`$g<%lO$OUBe[!PQ|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#o0r#o;'S$O;'S;=`$g<%lO$O^Cb[#VW|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#o0r#o;'S$O;'S;=`$g<%lO$O^D_[#XW|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#o0r#o;'S$O;'S;=`$g<%lO$O^E[^#WW|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#f0r#f#gFW#g#o0r#o;'S$O;'S;=`$g<%lO$OUF]^|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#i0r#i#jA]#j#o0r#o;'S$O;'S;=`$g<%lO$OUG`UlQ|SOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O~GwO#a~",
|
||||
tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO#P~~", 11)],
|
||||
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}],
|
||||
|
|
|
|||
|
|
@ -2,6 +2,65 @@ import { expect, describe, test } from 'bun:test'
|
|||
|
||||
import '../shrimp.grammar' // Importing this so changes cause it to retest!
|
||||
|
||||
describe('number literals', () => {
|
||||
test('binary numbers', () => {
|
||||
expect('0b110').toMatchTree(`
|
||||
Number 0b110
|
||||
`)
|
||||
})
|
||||
|
||||
test('hex numbers', () => {
|
||||
expect('0xdeadbeef').toMatchTree(`
|
||||
Number 0xdeadbeef
|
||||
`)
|
||||
})
|
||||
|
||||
test('hex numbers uppercase', () => {
|
||||
expect('0xFF').toMatchTree(`
|
||||
Number 0xFF
|
||||
`)
|
||||
})
|
||||
|
||||
test('decimal numbers still work', () => {
|
||||
expect('42').toMatchTree(`
|
||||
Number 42
|
||||
`)
|
||||
})
|
||||
|
||||
test('negative binary', () => {
|
||||
expect('-0b110').toMatchTree(`
|
||||
Number -0b110
|
||||
`)
|
||||
})
|
||||
|
||||
test('negative hex', () => {
|
||||
expect('-0xFF').toMatchTree(`
|
||||
Number -0xFF
|
||||
`)
|
||||
})
|
||||
|
||||
test('positive prefix binary', () => {
|
||||
expect('+0b110').toMatchTree(`
|
||||
Number +0b110
|
||||
`)
|
||||
})
|
||||
|
||||
test('positive prefix hex', () => {
|
||||
expect('+0xFF').toMatchTree(`
|
||||
Number +0xFF
|
||||
`)
|
||||
})
|
||||
|
||||
test('hex and binary in arrays', () => {
|
||||
expect('[0xFF 0b110 42]').toMatchTree(`
|
||||
Array
|
||||
Number 0xFF
|
||||
Number 0b110
|
||||
Number 42
|
||||
`)
|
||||
})
|
||||
})
|
||||
|
||||
describe('array literals', () => {
|
||||
test('work with numbers', () => {
|
||||
expect('[1 2 3]').toMatchTree(`
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user