package main import ( "bufio" "flag" "fmt" "os" ) var ( file string ) func main() { flag.Parse() args := flag.Args() if len(args) > 1 { fmt.Printf("Usage: %s [script]", args[0]) os.Exit(64) } else if len(args) == 1 { runFile(args[0]) } else { repl() } } func runFile(filename string) { bs, err := os.ReadFile(filename) if err != nil { fmt.Printf("unable to read file '%s':\n\t%s", filename, err.Error()) os.Exit(64) } if !run(string(bs)) { os.Exit(65) } } func repl() { s := bufio.NewScanner(os.Stdin) for { fmt.Printf("repl> ") s.Scan() text := s.Text() if text == ":q" { return } run(text) if err := s.Err(); err != nil { panic(err) } } } func run(source string) bool { s := newScanner(source) tokens, ok := s.ScanTokens() if !ok { return false } p := newParser(tokens) expr, err := p.Parse() if err != nil { return false } printer := &astPrinter{} fmt.Println(printer.print(expr)) return true } func reportErr(line int, message string) { report(line, "", message) } func reportSyntaxError(token *token, message string) { if token.Type == tokenTypeEOF { report(token.Line, "at EOF", message) } else { report(token.Line, "at \""+token.Lexeme+"\"", message) } } func report(line int, where, message string) { fmt.Printf("[line %d] Error%s: %s\n", line, where, message) }