204 lines
4.8 KiB
Go
204 lines
4.8 KiB
Go
package parser_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.sharkk.net/Sharkk/Mako/parser"
|
|
)
|
|
|
|
func TestProgram(t *testing.T) {
|
|
input := `x = 42
|
|
y = "hello"
|
|
z = true + false`
|
|
|
|
l := parser.NewLexer(input)
|
|
p := parser.NewParser(l)
|
|
program := p.ParseProgram()
|
|
checkParserErrors(t, p)
|
|
|
|
if len(program.Statements) != 3 {
|
|
t.Fatalf("expected 3 statements, got %d", len(program.Statements))
|
|
}
|
|
|
|
expectedIdentifiers := []string{"x", "y", "z"}
|
|
for i, expectedIdent := range expectedIdentifiers {
|
|
stmt, ok := program.Statements[i].(*parser.AssignStatement)
|
|
if !ok {
|
|
t.Fatalf("statement %d: expected AssignStatement, got %T", i, program.Statements[i])
|
|
}
|
|
|
|
if stmt.Name.Value != expectedIdent {
|
|
t.Errorf("statement %d: expected identifier %s, got %s", i, expectedIdent, stmt.Name.Value)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMixedStatements(t *testing.T) {
|
|
input := `x = 42
|
|
if x then
|
|
y = "hello"
|
|
if true then
|
|
z = {1, 2, 3}
|
|
end
|
|
end
|
|
arr = {a = 1, b = 2}`
|
|
|
|
l := parser.NewLexer(input)
|
|
p := parser.NewParser(l)
|
|
program := p.ParseProgram()
|
|
checkParserErrors(t, p)
|
|
|
|
if len(program.Statements) != 3 {
|
|
t.Fatalf("expected 3 statements, got %d", len(program.Statements))
|
|
}
|
|
|
|
// First statement: assignment
|
|
stmt1, ok := program.Statements[0].(*parser.AssignStatement)
|
|
if !ok {
|
|
t.Fatalf("statement 0: expected AssignStatement, got %T", program.Statements[0])
|
|
}
|
|
if stmt1.Name.Value != "x" {
|
|
t.Errorf("expected identifier 'x', got %s", stmt1.Name.Value)
|
|
}
|
|
|
|
// Second statement: if statement
|
|
stmt2, ok := program.Statements[1].(*parser.IfStatement)
|
|
if !ok {
|
|
t.Fatalf("statement 1: expected IfStatement, got %T", program.Statements[1])
|
|
}
|
|
if len(stmt2.Body) != 2 {
|
|
t.Errorf("expected 2 body statements, got %d", len(stmt2.Body))
|
|
}
|
|
|
|
// Third statement: table assignment
|
|
stmt3, ok := program.Statements[2].(*parser.AssignStatement)
|
|
if !ok {
|
|
t.Fatalf("statement 2: expected AssignStatement, got %T", program.Statements[2])
|
|
}
|
|
table, ok := stmt3.Value.(*parser.TableLiteral)
|
|
if !ok {
|
|
t.Fatalf("expected TableLiteral value, got %T", stmt3.Value)
|
|
}
|
|
if table.IsArray() {
|
|
t.Error("expected hash table, got array")
|
|
}
|
|
}
|
|
|
|
func TestNestedConditionals(t *testing.T) {
|
|
input := `if a then
|
|
if b then
|
|
x = 1
|
|
elseif c then
|
|
x = 2
|
|
else
|
|
x = 3
|
|
end
|
|
y = 4
|
|
elseif d then
|
|
z = 5
|
|
else
|
|
w = 6
|
|
end`
|
|
|
|
l := parser.NewLexer(input)
|
|
p := parser.NewParser(l)
|
|
program := p.ParseProgram()
|
|
checkParserErrors(t, p)
|
|
|
|
if len(program.Statements) != 1 {
|
|
t.Fatalf("expected 1 statement, got %d", len(program.Statements))
|
|
}
|
|
|
|
outerIf, ok := program.Statements[0].(*parser.IfStatement)
|
|
if !ok {
|
|
t.Fatalf("expected IfStatement, got %T", program.Statements[0])
|
|
}
|
|
|
|
// Outer if should have 2 body statements: nested if and assignment
|
|
if len(outerIf.Body) != 2 {
|
|
t.Fatalf("expected 2 body statements, got %d", len(outerIf.Body))
|
|
}
|
|
|
|
// First body statement should be nested if
|
|
nestedIf, ok := outerIf.Body[0].(*parser.IfStatement)
|
|
if !ok {
|
|
t.Fatalf("expected nested IfStatement, got %T", outerIf.Body[0])
|
|
}
|
|
|
|
// Nested if should have 1 elseif and 1 else
|
|
if len(nestedIf.ElseIfs) != 1 {
|
|
t.Errorf("expected 1 elseif in nested if, got %d", len(nestedIf.ElseIfs))
|
|
}
|
|
|
|
if len(nestedIf.Else) != 1 {
|
|
t.Errorf("expected 1 else statement in nested if, got %d", len(nestedIf.Else))
|
|
}
|
|
|
|
// Outer if should have 1 elseif and 1 else
|
|
if len(outerIf.ElseIfs) != 1 {
|
|
t.Errorf("expected 1 elseif in outer if, got %d", len(outerIf.ElseIfs))
|
|
}
|
|
|
|
if len(outerIf.Else) != 1 {
|
|
t.Errorf("expected 1 else statement in outer if, got %d", len(outerIf.Else))
|
|
}
|
|
}
|
|
|
|
func TestComplexExpressions(t *testing.T) {
|
|
input := `result = (0xFF + 0b1010) * 1e2
|
|
if result then
|
|
table = {
|
|
hex = 0xDEAD,
|
|
bin = 0b1111,
|
|
sci = 1.5e-3,
|
|
str = [[multiline
|
|
string]]
|
|
}
|
|
end`
|
|
|
|
l := parser.NewLexer(input)
|
|
p := parser.NewParser(l)
|
|
program := p.ParseProgram()
|
|
checkParserErrors(t, p)
|
|
|
|
if len(program.Statements) != 2 {
|
|
t.Fatalf("expected 2 statements, got %d", len(program.Statements))
|
|
}
|
|
|
|
// First statement: complex expression assignment
|
|
stmt1, ok := program.Statements[0].(*parser.AssignStatement)
|
|
if !ok {
|
|
t.Fatalf("expected AssignStatement, got %T", program.Statements[0])
|
|
}
|
|
|
|
// Should be a complex infix expression
|
|
_, ok = stmt1.Value.(*parser.InfixExpression)
|
|
if !ok {
|
|
t.Fatalf("expected InfixExpression, got %T", stmt1.Value)
|
|
}
|
|
|
|
// Second statement: if with table assignment
|
|
stmt2, ok := program.Statements[1].(*parser.IfStatement)
|
|
if !ok {
|
|
t.Fatalf("expected IfStatement, got %T", program.Statements[1])
|
|
}
|
|
|
|
if len(stmt2.Body) != 1 {
|
|
t.Fatalf("expected 1 body statement, got %d", len(stmt2.Body))
|
|
}
|
|
|
|
bodyStmt, ok := stmt2.Body[0].(*parser.AssignStatement)
|
|
if !ok {
|
|
t.Fatalf("expected AssignStatement in body, got %T", stmt2.Body[0])
|
|
}
|
|
|
|
table, ok := bodyStmt.Value.(*parser.TableLiteral)
|
|
if !ok {
|
|
t.Fatalf("expected TableLiteral, got %T", bodyStmt.Value)
|
|
}
|
|
|
|
if len(table.Pairs) != 4 {
|
|
t.Errorf("expected 4 table pairs, got %d", len(table.Pairs))
|
|
}
|
|
}
|