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(` 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 `) }) test('empty arrays', () => { expect('[]').toMatchTree(` Array [] `) }) test('mixed types', () => { expect("[1 'two' three true null]").toMatchTree(` Array Number 1 String StringFragment two Identifier three Boolean true Null null `) }) test('semicolons as separators', () => { expect('[1; 2; 3]').toMatchTree(` Array Number 1 Number 2 Number 3 `) }) test('expressions in arrays', () => { expect('[(1 + 2) (3 * 4)]').toMatchTree(` Array ParenExpr BinOp Number 1 Plus + Number 2 ParenExpr BinOp Number 3 Star * Number 4 `) }) test('mixed separators - spaces and newlines', () => { expect(`[1 2 3 4]`).toMatchTree(` Array Number 1 Number 2 Number 3 Number 4 `) }) test('mixed separators - spaces and semicolons', () => { expect('[1 2; 3 4]').toMatchTree(` Array Number 1 Number 2 Number 3 Number 4 `) }) test('empty lines within arrays', () => { expect(`[1 2]`).toMatchTree(` Array Number 1 Number 2 `) }) test('comments within arrays', () => { expect(`[ # something... 1 # first 2 # second ]`).toMatchTree(` Array Comment # something... Number 1 Comment # first Number 2 Comment # second `) }) test('complex nested multiline', () => { expect(`[ [1 2] [3 4] [5 6] ]`).toMatchTree(` Array Array Number 1 Number 2 Array Number 3 Number 4 Array Number 5 Number 6 `) }) test('boolean and null literals', () => { expect('[true false null]').toMatchTree(` Array Boolean true Boolean false Null null `) }) test('regex literals', () => { expect('[//[0-9]+//]').toMatchTree(` Array Regex //[0-9]+// `) }) test('trailing newlines', () => { expect(`[ 1 2 ]`).toMatchTree(` Array Number 1 Number 2 `) }) }) describe('dict literals', () => { test('work with numbers', () => { expect('[a=1 b=2 c=3]').toMatchTree(` Dict NamedArg NamedArgPrefix a= Number 1 NamedArg NamedArgPrefix b= Number 2 NamedArg NamedArgPrefix c= Number 3 `) }) test('work with strings', () => { expect("[a='one' b='two' c='three']").toMatchTree(` Dict NamedArg NamedArgPrefix a= String StringFragment one NamedArg NamedArgPrefix b= String StringFragment two NamedArg NamedArgPrefix c= String StringFragment three `) }) test('work with identifiers', () => { expect('[a=one b=two c=three]').toMatchTree(` Dict NamedArg NamedArgPrefix a= Identifier one NamedArg NamedArgPrefix b= Identifier two NamedArg NamedArgPrefix c= Identifier three `) }) test('can be nested', () => { expect('[a=one b=[two [c=three]]]').toMatchTree(` Dict NamedArg NamedArgPrefix a= Identifier one NamedArg NamedArgPrefix b= Array Identifier two Dict NamedArg NamedArgPrefix c= Identifier three `) }) test('can span multiple lines', () => { expect(`[ a=1 b=2 c=3 ]`).toMatchTree(` Dict NamedArg NamedArgPrefix a= Number 1 NamedArg NamedArgPrefix b= Number 2 NamedArg NamedArgPrefix c= Number 3 `) }) test('empty dict', () => { expect('[=]').toMatchTree(` Dict [=] `) expect('[ = ]').toMatchTree(` Array Word = `) }) test('mixed types', () => { expect("[a=1 b='two' c=three d=true e=null]").toMatchTree(` Dict NamedArg NamedArgPrefix a= Number 1 NamedArg NamedArgPrefix b= String StringFragment two NamedArg NamedArgPrefix c= Identifier three NamedArg NamedArgPrefix d= Boolean true NamedArg NamedArgPrefix e= Null null `) }) test('semicolons as separators', () => { expect('[a=1; b=2; c=3]').toMatchTree(` Dict NamedArg NamedArgPrefix a= Number 1 NamedArg NamedArgPrefix b= Number 2 NamedArg NamedArgPrefix c= Number 3 `) }) test('expressions in dicts', () => { expect('[a=(1 + 2) b=(3 * 4)]').toMatchTree(` Dict NamedArg NamedArgPrefix a= ParenExpr BinOp Number 1 Plus + Number 2 NamedArg NamedArgPrefix b= ParenExpr BinOp Number 3 Star * Number 4 `) }) test('mixed separators - spaces and newlines', () => { expect(`[a=1 b=2 c=3]`).toMatchTree(` Dict NamedArg NamedArgPrefix a= Number 1 NamedArg NamedArgPrefix b= Number 2 NamedArg NamedArgPrefix c= Number 3 `) }) test('empty lines within dicts', () => { expect(`[a=1 b=2 c=3]`).toMatchTree(` Dict NamedArg NamedArgPrefix a= Number 1 NamedArg NamedArgPrefix b= Number 2 NamedArg NamedArgPrefix c= Number 3 `) }) test('comments within dicts', () => { expect(`[ # something... a=1 # first b=2 # second 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 `) }) test('complex nested multiline', () => { expect(`[ a=[a=1 b=2] b=[b=3 c=4] c=[c=5 d=6] ]`).toMatchTree(` Dict NamedArg NamedArgPrefix a= Dict NamedArg NamedArgPrefix a= Number 1 NamedArg NamedArgPrefix b= Number 2 NamedArg NamedArgPrefix b= Dict NamedArg NamedArgPrefix b= Number 3 NamedArg NamedArgPrefix c= Number 4 NamedArg NamedArgPrefix c= Dict NamedArg NamedArgPrefix c= Number 5 NamedArg NamedArgPrefix d= Number 6 `) }) test('boolean and null literals', () => { expect('[a=true b=false c=null]').toMatchTree(` Dict NamedArg NamedArgPrefix a= Boolean true NamedArg NamedArgPrefix b= Boolean false NamedArg NamedArgPrefix c= Null null `) }) test('regex literals', () => { expect('[pattern=//[0-9]+//]').toMatchTree(` Dict NamedArg NamedArgPrefix pattern= Regex //[0-9]+// `) }) test('trailing newlines', () => { expect(`[ a=1 b=2 c=3 ]`).toMatchTree(` Dict NamedArg NamedArgPrefix a= Number 1 NamedArg NamedArgPrefix b= Number 2 NamedArg NamedArgPrefix c= Number 3 `) }) })