Fancy compiler errors
This commit is contained in:
parent
1d79aeaa0b
commit
56c36f01dd
2
lexer.go
2
lexer.go
@ -186,7 +186,7 @@ func (l *Lexer) nextToken() (string, error) {
|
|||||||
token += string(*l.nextRune())
|
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
|
return string(*l.nextRune()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
78
main.go
78
main.go
@ -4,25 +4,75 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"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() {
|
func main() {
|
||||||
if len(os.Args) != 2 {
|
if len(os.Args) != 2 {
|
||||||
log.Fatalln("Usage: " + os.Args[0] + " <file>")
|
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 {
|
if err != nil {
|
||||||
log.Fatalln("Cannot open input file.", err)
|
log.Fatalln("Cannot open input file.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens, err := lexer(string(content))
|
source := string(content)
|
||||||
|
|
||||||
|
tokens, err := lexer(source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if c, ok := err.(CompilerError); ok {
|
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)
|
log.Printf("Tokens:\n%+#v\n\n", tokens)
|
||||||
@ -31,10 +81,12 @@ func main() {
|
|||||||
parsed, err := parser.parseFile()
|
parsed, err := parser.parseFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if c, ok := err.(CompilerError); ok {
|
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)
|
log.Printf("Parsed:\n%+#v\n\n", parsed)
|
||||||
@ -44,10 +96,14 @@ func main() {
|
|||||||
if len(errors) != 0 {
|
if len(errors) != 0 {
|
||||||
for _, err = range errors {
|
for _, err = range errors {
|
||||||
if c, ok := err.(CompilerError); ok {
|
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)
|
wat, err := backendWAT(*parsed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if c, ok := err.(CompilerError); ok {
|
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)
|
log.Println("WAT: " + wat)
|
||||||
|
@ -802,7 +802,7 @@ func (p *Parser) expectFunction() (*ParsedFunction, error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(parameters) > 0 {
|
if len(parameters) != 0 {
|
||||||
_, err := p.expectSeparator(Separator_Comma)
|
_, err := p.expectSeparator(Separator_Comma)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -182,7 +182,7 @@ func (v *Validator) validatePotentiallyVoidExpression(expr *Expression, block *B
|
|||||||
|
|
||||||
if fc.Parameters != nil {
|
if fc.Parameters != nil {
|
||||||
paramsErrors := v.validateExpression(fc.Parameters, block)
|
paramsErrors := v.validateExpression(fc.Parameters, block)
|
||||||
if len(paramsErrors) > 0 {
|
if len(paramsErrors) != 0 {
|
||||||
errors = append(errors, paramsErrors...)
|
errors = append(errors, paramsErrors...)
|
||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
@ -212,7 +212,7 @@ func (v *Validator) validatePotentiallyVoidExpression(expr *Expression, block *B
|
|||||||
neg := expr.Value.(NegateExpression)
|
neg := expr.Value.(NegateExpression)
|
||||||
|
|
||||||
valErrors := v.validateExpression(&neg.Value, block)
|
valErrors := v.validateExpression(&neg.Value, block)
|
||||||
if len(valErrors) > 0 {
|
if len(valErrors) != 0 {
|
||||||
errors = append(errors, valErrors...)
|
errors = append(errors, valErrors...)
|
||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
@ -230,6 +230,9 @@ func (v *Validator) validatePotentiallyVoidExpression(expr *Expression, block *B
|
|||||||
|
|
||||||
func (v *Validator) validateExpression(expr *Expression, block *Block) []error {
|
func (v *Validator) validateExpression(expr *Expression, block *Block) []error {
|
||||||
errors := v.validatePotentiallyVoidExpression(expr, block)
|
errors := v.validatePotentiallyVoidExpression(expr, block)
|
||||||
|
if len(errors) != 0 {
|
||||||
|
return errors
|
||||||
|
}
|
||||||
|
|
||||||
if expr.ValueType == nil {
|
if expr.ValueType == nil {
|
||||||
errors = append(errors, v.createError("expression must not evaluate to void", expr.Position))
|
errors = append(errors, v.createError("expression must not evaluate to void", expr.Position))
|
||||||
|
Loading…
Reference in New Issue
Block a user