package lox import ( "bufio" "fmt" "golox/interpreter" "golox/parser" "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 } l.interpreter.Interpret(stmts) }