Fancy compiler errors

This commit is contained in:
MrLetsplay 2024-03-21 20:37:21 +01:00
parent 1d79aeaa0b
commit 56c36f01dd
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
4 changed files with 75 additions and 14 deletions

View File

@ -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
}

78
main.go
View File

@ -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] + " <file>")
}
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)

View File

@ -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

View File

@ -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))