Fix parser edge-cases, fix wasm, refactor

This commit is contained in:
Neemek 2025-04-04 09:52:41 +02:00
parent c364e09fc9
commit be7809d467
Signed by: neemek
GPG key ID: 28360A8951CD0E9B
5 changed files with 38 additions and 25 deletions

View file

@ -130,13 +130,13 @@ func TestAll(t *testing.T) {
}
t.Log("Initializing parser")
p := NewParser(tokens)
p := NewParser(tc.src, tokens)
t.Log("Parsing tokens")
tree, err := p.Parse()
tree, err := p.Parse(tc.src)
if err != nil {
print(err.(ParsingError).Format([]rune(tc.src)))
print(err.(ParsingError).Format())
t.Fatalf("parser had an error")
}
@ -144,7 +144,7 @@ func TestAll(t *testing.T) {
c := NewCompiler([]rune(tc.src))
t.Log("Compiling parse tree")
err = c.compile(tree)
err = c.Compile(tree)
if err != nil {
t.Fatalf("Compiler had an error: %s", err)
}
@ -173,11 +173,11 @@ func BenchmarkAll(b *testing.B) {
l := NewLexer(tc.src)
tokens, _ := l.Tokenize()
p := NewParser(tokens)
tree, _ := p.Parse()
p := NewParser(tc.src, tokens)
tree, _ := p.Parse(tc.src)
c := NewCompiler([]rune(tc.src))
_ = c.compile(tree)
_ = c.Compile(tree)
vm := NewVM(c.Chunk, 256, 256)

View file

@ -215,7 +215,7 @@ func (c *Compiler) compile(tree Node) error {
}
case ReferenceNodeType:
c.getVar(tree.(*ReferenceNode).name)
c.addGetVar(tree.(*ReferenceNode).name)
case BinaryNodeType:
err := c.compileBinary(tree.(*BinaryNode))
@ -275,7 +275,7 @@ func (c *Compiler) compile(tree Node) error {
return err
}
if sig.Type() != TypeBoolean {
return c.error(fmt.Sprintf("condition cannot give non-boolean type %s", sig), n.condition)
return c.error(fmt.Sprintf("conditional requires boolean; cannot use non-boolean type %s", sig), n.condition)
}
// the stack should have whether the condition was truthful
@ -365,7 +365,7 @@ func (c *Compiler) compile(tree Node) error {
return c.error(fmt.Sprintf("%s is already declared in this scope", n.name), n)
}
err := c.setVar(n.name, n.value, n.declare)
err := c.addSetVar(n.name, n.value, n.declare)
if err != nil {
return err
}
@ -871,7 +871,7 @@ func (c *Compiler) isVarDeclaredHere(name string) bool {
return false
}
func (c *Compiler) getVar(name string) {
func (c *Compiler) addGetVar(name string) {
if c.isGlobal(name) {
c.add(InstructionGetGlobal)
c.addConstant(&StringValue{
@ -885,7 +885,7 @@ func (c *Compiler) getVar(name string) {
}
}
func (c *Compiler) setVar(name string, value Node, declare bool) error {
func (c *Compiler) addSetVar(name string, value Node, declare bool) error {
err := c.compile(value)
if err != nil {
return err

View file

@ -129,7 +129,9 @@ func (p *Parser) Parse(path string) (*Program, error) {
return nil, err
}
statements = append(statements, b)
if b != nil {
statements = append(statements, b)
}
}
return &Program{
@ -774,16 +776,23 @@ func (p *Parser) statement() (Node, error) {
return &BreakpointNode{}, nil
case TokenImport:
defer p.advance()
return nil, p.error("import statements must be top-level", p.curr)
default:
err := p.error("invalid statement", p.curr)
p.advance()
return nil, err
defer p.advance()
return nil, p.error("invalid statement", p.curr)
}
}
func (p *Parser) block(canBeStatement bool) (Node, error) {
if canBeStatement {
if !p.accept(TokenOpenBrace) {
if p.curr.Type == TokenEOF {
return nil, nil
}
return p.statement()
}
} else {

View file

@ -10,7 +10,7 @@ import (
func TestNewParser(t *testing.T) {
tokens := make([]Token, 0)
p := NewParser(tokens)
p := NewParser("", tokens)
if p == nil {
t.Fatal("parser should not be nil")
@ -34,7 +34,7 @@ func TestNewParser(t *testing.T) {
func BenchmarkNewParser(b *testing.B) {
tokens := make([]Token, 0)
for i := 0; i < b.N; i++ {
_ = NewParser(tokens)
_ = NewParser("", tokens)
}
}
@ -908,17 +908,17 @@ func TestParser_Parse(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Logf("Initializing parser")
p := NewParser(data.tokens)
p := NewParser("", data.tokens)
t.Logf("Parsing main")
tree, err := p.Parse()
tree, err := p.Parse("")
if err != nil {
t.Fatalf("Unexpected error(s): %s", err.(ParsingError).Format([]rune(SerializeTokens(data.tokens))))
t.Fatalf("Unexpected error(s): %s", err.(ParsingError).Format())
}
t.Logf("Checking parsed tree")
NodeEquality(t, tree, data.tree)
NodeEquality(t, tree.Block, data.tree)
})
}
}
@ -929,9 +929,9 @@ func BenchmarkParser_Parse(b *testing.B) {
for name, data := range tokenData {
b.Run(name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
p := NewParser(data.tokens)
p := NewParser("", data.tokens)
_, _ = p.Parse()
_, _ = p.Parse("")
}
})
}

View file

@ -13,6 +13,10 @@ type JsResolver struct {
jsResolver js.Value
}
func (r *JsResolver) IsSame(a, b string) bool {
return a == b
}
func (r *JsResolver) Resolve(name string) (string, error) {
jsv := r.jsResolver.Invoke(name)
@ -56,7 +60,7 @@ func run(_ js.Value, args []js.Value) interface{} {
parser := core.NewParser(source, tokens)
tree, err := parser.Parse()
tree, err := parser.Parse(source)
if err != nil {
var e core.FormatedError