diff --git a/src/compiler/compiler.ts b/src/compiler/compiler.ts index 212da55..b7e6274 100644 --- a/src/compiler/compiler.ts +++ b/src/compiler/compiler.ts @@ -303,7 +303,8 @@ export class Compiler { return instructions } - case terms.ThenBlock: { + case terms.ThenBlock: + case terms.SingleLineThenBlock: { const instructions = getAllChildren(node) .map((child) => this.#compileNode(child, input)) .flat() @@ -468,7 +469,11 @@ export class Compiler { } default: - throw new CompilerError(`Unsupported syntax node: ${node.type.name}`, node.from, node.to) + throw new CompilerError( + `Compiler doesn't know how to handle a "${node.type.name}" node.`, + node.from, + node.to + ) } } } diff --git a/src/compiler/tests/compiler.test.ts b/src/compiler/tests/compiler.test.ts index 652b29c..46ee0b7 100644 --- a/src/compiler/tests/compiler.test.ts +++ b/src/compiler/tests/compiler.test.ts @@ -154,6 +154,10 @@ describe('compiler', () => { scattered end`).toEvaluateTo('dwarf') }) + + test('single line if', () => { + expect(`if 3 < 9: shire end`).toEvaluateTo('shire') + }) }) describe('errors', () => { diff --git a/src/parser/shrimp.grammar b/src/parser/shrimp.grammar index 3dbddd8..35fdcbc 100644 --- a/src/parser/shrimp.grammar +++ b/src/parser/shrimp.grammar @@ -2,7 +2,7 @@ @context trackScope from "./scopeTracker" -@skip { space } +@skip { space | comment } @top Program { item* } @@ -18,6 +18,7 @@ newlineOrSemicolon { "\n" | ";" } eof { @eof } space { " " | "\t" } + comment { "#" ![\n]* } leftParen { "(" } rightParen { ")" } colon[closedBy="end", @name="colon"] { ":" } @@ -104,7 +105,7 @@ IfExpr { } singleLineIf { - @specialize[@name=keyword] (ConditionalOp | expression) colon ThenBlock { consumeToTerminator } + @specialize[@name=keyword] (ConditionalOp | expression) colon SingleLineThenBlock @specialize[@name=keyword] } multilineIf { @@ -123,6 +124,10 @@ ThenBlock { block } +SingleLineThenBlock { + consumeToTerminator +} + ConditionalOp { expression Eq expression | expression Neq expression | diff --git a/src/parser/shrimp.terms.ts b/src/parser/shrimp.terms.ts index 75f88be..2b65bbc 100644 --- a/src/parser/shrimp.terms.ts +++ b/src/parser/shrimp.terms.ts @@ -41,6 +41,7 @@ export const NamedArg = 40, NamedArgPrefix = 41, IfExpr = 43, + SingleLineThenBlock = 45, ThenBlock = 46, ElseIfExpr = 47, ElseExpr = 49, diff --git a/src/parser/tests/basics.test.ts b/src/parser/tests/basics.test.ts index 3299ff3..6cc5989 100644 --- a/src/parser/tests/basics.test.ts +++ b/src/parser/tests/basics.test.ts @@ -348,3 +348,27 @@ describe('DotGet whitespace sensitivity', () => { expect('readme.txt').toMatchTree(`Word readme.txt`) }) }) + +describe('Comments', () => { + test('are barely there', () => { + expect(`x = 5 # one banana\ny = 2 # two bananas`).toMatchTree(` + Assign + AssignableIdentifier x + Eq = + Number 5 + Assign + AssignableIdentifier y + Eq = + Number 2`) + + expect('# some comment\nbasename = 5 # very astute\n basename / prop\n# good info').toMatchTree(` + Assign + AssignableIdentifier basename + Eq = + Number 5 + BinOp + Identifier basename + Slash / + Identifier prop`) + }) +}) \ No newline at end of file diff --git a/src/parser/tests/control-flow.test.ts b/src/parser/tests/control-flow.test.ts index df1bc3c..11c81d0 100644 --- a/src/parser/tests/control-flow.test.ts +++ b/src/parser/tests/control-flow.test.ts @@ -4,7 +4,7 @@ import '../shrimp.grammar' // Importing this so changes cause it to retest! describe('if/elseif/else', () => { test('parses single line if', () => { - expect(`if y = 1: 'cool'`).toMatchTree(` + expect(`if y = 1: 'cool' end`).toMatchTree(` IfExpr keyword if ConditionalOp @@ -12,12 +12,13 @@ describe('if/elseif/else', () => { Eq = Number 1 colon : - ThenBlock + SingleLineThenBlock String StringFragment cool + keyword end `) - expect('a = if x: 2').toMatchTree(` + expect('a = if x: 2 end').toMatchTree(` Assign AssignableIdentifier a Eq = @@ -25,8 +26,9 @@ describe('if/elseif/else', () => { keyword if Identifier x colon : - ThenBlock + SingleLineThenBlock Number 2 + keyword end `) }) @@ -138,7 +140,7 @@ describe('if/elseif/else', () => { }) test('does not parse identifiers that start with if', () => { - expect('iffy = if true: 2').toMatchTree(` + expect('iffy = if true: 2 end').toMatchTree(` Assign AssignableIdentifier iffy Eq = @@ -146,8 +148,9 @@ describe('if/elseif/else', () => { keyword if Boolean true colon : - ThenBlock + SingleLineThenBlock Number 2 + keyword end `) }) })