You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
1.8 KiB
Go
114 lines
1.8 KiB
Go
package lox
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"golox/interpreter"
|
|
"golox/parser"
|
|
"golox/resolver"
|
|
"golox/scanner"
|
|
"golox/token"
|
|
"os"
|
|
)
|
|
|
|
type Lox struct {
|
|
hadError bool
|
|
hadRuntimeError bool
|
|
interpreter *interpreter.Interpreter
|
|
}
|
|
|
|
func New() *Lox {
|
|
l := &Lox{
|
|
hadError: false,
|
|
hadRuntimeError: false,
|
|
}
|
|
|
|
l.interpreter = interpreter.New(l)
|
|
|
|
return l
|
|
}
|
|
|
|
func (l *Lox) RunFile(path string) {
|
|
bytes, err := os.ReadFile(path)
|
|
if err != nil {
|
|
fmt.Println("Error reading file", path)
|
|
os.Exit(74)
|
|
}
|
|
|
|
l.run(string(bytes))
|
|
|
|
if l.hadError {
|
|
os.Exit(65)
|
|
}
|
|
|
|
if l.hadRuntimeError {
|
|
os.Exit(70)
|
|
}
|
|
}
|
|
|
|
func (l *Lox) RunPrompt() {
|
|
reader := bufio.NewReader(os.Stdin)
|
|
|
|
for {
|
|
fmt.Print("> ")
|
|
|
|
line, err := reader.ReadString('\n')
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
os.Exit(74)
|
|
}
|
|
|
|
if line == "\n" {
|
|
break
|
|
}
|
|
|
|
l.run(line)
|
|
l.hadError = false
|
|
}
|
|
}
|
|
|
|
func (l *Lox) Error(line int, message string) {
|
|
l.hadError = true
|
|
l.report(line, "", message)
|
|
}
|
|
|
|
func (l *Lox) ErrorAtToken(t token.Token, message string) {
|
|
l.hadError = true
|
|
if t.Type == token.EOF {
|
|
l.report(t.Line, " at end", message)
|
|
} else {
|
|
l.report(t.Line, " at '"+t.Lexeme+"'", message)
|
|
}
|
|
}
|
|
|
|
func (l *Lox) RuntimeError(message string) {
|
|
l.hadRuntimeError = true
|
|
fmt.Println(message)
|
|
}
|
|
|
|
func (l *Lox) report(line int, where string, message string) {
|
|
fmt.Printf("[line %d] Error %s: %s\n", line, where, message)
|
|
}
|
|
|
|
func (l *Lox) run(source string) {
|
|
scanner := scanner.New(source, l)
|
|
tokens := scanner.ScanTokens()
|
|
parser := parser.New(tokens, l)
|
|
stmts := parser.Parse()
|
|
|
|
// Stop if there was a syntax error.
|
|
if l.hadError {
|
|
return
|
|
}
|
|
|
|
resolver := resolver.New(l.interpreter, l)
|
|
resolver.Resolve(stmts)
|
|
|
|
// Stop if there was a resolution error.
|
|
if l.hadError {
|
|
return
|
|
}
|
|
|
|
l.interpreter.Interpret(stmts)
|
|
}
|