diff --git a/lexer.go b/lexer.go index 4d917ea..3675cec 100644 --- a/lexer.go +++ b/lexer.go @@ -186,7 +186,7 @@ func (l *Lexer) nextToken() (string, error) { token += string(*l.nextRune()) } - if len(token) == 0 && len(l.Runes) > 0 { + if len(token) == 0 && len(l.Runes) != 0 { return string(*l.nextRune()), nil } diff --git a/main.go b/main.go index df57c55..4b3a8ee 100644 --- a/main.go +++ b/main.go @@ -4,25 +4,75 @@ package main import ( "log" "os" + "strconv" + "strings" ) +const ERROR_LOG_LINES = 10 + +func countTabs(line string) int { + tabs := 0 + for _, rune := range line { + if rune == '\t' { + tabs++ + } + } + return tabs +} + +func printCompilerError(file string, source string, err CompilerError) { + sourceRunes := []rune(source) + lines := strings.Split(source, "\n") + line := 0 + col := 0 + var i uint64 + for i = 0; i < err.Position; i++ { + col++ + if sourceRunes[i] == '\n' { + line++ + col = 0 + } + } + + log.Println("Failed to compile: " + err.Message + " (at " + file + ":" + strconv.Itoa(line+1) + ":" + strconv.Itoa(col+1) + ")") + + linesStart := max(0, line-ERROR_LOG_LINES) + linesEnd := min(len(lines), line+ERROR_LOG_LINES+1) + + for _, line := range lines[linesStart:line] { + println(strings.Replace(line, "\t", " ", -1)) + } + + tabs := countTabs(lines[line]) + println(strings.Repeat(" ", col+tabs*3) + "v--- error occurs here ---") + + for _, line := range lines[line:linesEnd] { + println(strings.Replace(line, "\t", " ", -1)) + } +} + func main() { if len(os.Args) != 2 { log.Fatalln("Usage: " + os.Args[0] + " ") } - content, err := os.ReadFile(os.Args[1]) + file := os.Args[1] + content, err := os.ReadFile(file) if err != nil { log.Fatalln("Cannot open input file.", err) } - tokens, err := lexer(string(content)) + source := string(content) + + tokens, err := lexer(source) if err != nil { if c, ok := err.(CompilerError); ok { - log.Fatalln(err, "\nv- here\n"+string([]rune(string(content))[c.Position:])) + printCompilerError(file, source, c) + } else { + log.Println(err) } - log.Fatalln(err) + return } log.Printf("Tokens:\n%+#v\n\n", tokens) @@ -31,10 +81,12 @@ func main() { parsed, err := parser.parseFile() if err != nil { if c, ok := err.(CompilerError); ok { - log.Fatalln(err, "\nv- here\n"+string([]rune(string(content))[c.Position:])) + printCompilerError(file, source, c) + } else { + log.Println(err) } - log.Fatalln(err) + return } log.Printf("Parsed:\n%+#v\n\n", parsed) @@ -44,10 +96,14 @@ func main() { if len(errors) != 0 { for _, err = range errors { if c, ok := err.(CompilerError); ok { - log.Fatalln(err, "\nv- here\n"+string([]rune(string(content))[c.Position:])) + printCompilerError(file, source, c) + } else { + log.Println(err) } + } - log.Fatalln(err) + if len(errors) != 0 { + return } } @@ -56,10 +112,12 @@ func main() { wat, err := backendWAT(*parsed) if err != nil { if c, ok := err.(CompilerError); ok { - log.Fatalln(err, "\nv- here\n"+string([]rune(string(content))[c.Position:])) + printCompilerError(file, source, c) + } else { + log.Println(err) } - log.Fatalln(err) + return } log.Println("WAT: " + wat) diff --git a/parser.go b/parser.go index 6c44d99..8c1db03 100644 --- a/parser.go +++ b/parser.go @@ -802,7 +802,7 @@ func (p *Parser) expectFunction() (*ParsedFunction, error) { break } - if len(parameters) > 0 { + if len(parameters) != 0 { _, err := p.expectSeparator(Separator_Comma) if err != nil { return nil, err diff --git a/validator.go b/validator.go index d2119c3..12350de 100644 --- a/validator.go +++ b/validator.go @@ -182,7 +182,7 @@ func (v *Validator) validatePotentiallyVoidExpression(expr *Expression, block *B if fc.Parameters != nil { paramsErrors := v.validateExpression(fc.Parameters, block) - if len(paramsErrors) > 0 { + if len(paramsErrors) != 0 { errors = append(errors, paramsErrors...) return errors } @@ -212,7 +212,7 @@ func (v *Validator) validatePotentiallyVoidExpression(expr *Expression, block *B neg := expr.Value.(NegateExpression) valErrors := v.validateExpression(&neg.Value, block) - if len(valErrors) > 0 { + if len(valErrors) != 0 { errors = append(errors, valErrors...) return errors } @@ -230,6 +230,9 @@ func (v *Validator) validatePotentiallyVoidExpression(expr *Expression, block *B func (v *Validator) validateExpression(expr *Expression, block *Block) []error { errors := v.validatePotentiallyVoidExpression(expr, block) + if len(errors) != 0 { + return errors + } if expr.ValueType == nil { errors = append(errors, v.createError("expression must not evaluate to void", expr.Position))