summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuleyman Farajli <suleyman@farajli.net>2025-01-06 15:39:47 +0400
committerSuleyman Farajli <suleyman@farajli.net>2025-01-06 15:39:47 +0400
commit4770b77353acd57f7ba6ca3e50dae02c2a610088 (patch)
treee508f3e637a4db2404b3cbe8a92380591034661d
parent6030cdde103e889b17a3453b2a10526ee1f8ce1b (diff)
Better error messages
-rw-r--r--src/main.go58
1 files changed, 36 insertions, 22 deletions
diff --git a/src/main.go b/src/main.go
index e45500a..b14e713 100644
--- a/src/main.go
+++ b/src/main.go
@@ -31,13 +31,16 @@ type Macro struct {
tokens[] Token
}
+var progname string;
+
func tokenize(path string) []Token {
var tokens []Token;
reg := regexp.MustCompile(`\n`)
dat, err := os.ReadFile(path);
if (err != nil) {
- panic("Failed to read file");
+ fmt.Fprintf(os.Stderr, "%s: Error: failed read file '%s'.\n", progname, path)
+ os.Exit(1)
}
lines := reg.Split(string(dat), -1);
@@ -74,12 +77,13 @@ func tokenize(path string) []Token {
buf = ""
}
if isStr {
- panic("invalid syntax")
+ fmt.Fprintf(os.Stderr, "%s: Error: expected `\"`: '%s'.\n", progname, path)
+ os.Exit(1)
}
}
return tokens
}
-/* FIXME: handle recursive includes */
+
func preprocess(rawTokens[] Token) []Token {
incDepth := 0
const incDepthLim = 200
@@ -90,8 +94,9 @@ func preprocess(rawTokens[] Token) []Token {
case "define":
var macroBuf Macro
if i + 1 >= len(rawTokens) {
- /*FIXME: better error message */
- panic("invalid define syntax")
+ fmt.Fprintf(os.Stderr, "%s: Error: invalid syntax for define: %s: %d:%d.\n",
+ progname, rawTokens[i].file, rawTokens[i].line, rawTokens[i].offset)
+ os.Exit(1)
}
macroBuf.name = rawTokens[i + 1].str
@@ -102,21 +107,27 @@ func preprocess(rawTokens[] Token) []Token {
macroBuf.tokens = append(macroBuf.tokens, rawTokens[i])
}
if i == len(rawTokens) {
- /*FIXME: better error message */
- panic("expected `end` at the end")
+ fmt.Fprintf(os.Stderr, "%s: Error: expected `end`: '%s'.\n", progname, rawTokens[i].file)
+ os.Exit(1)
}
macros = append(macros, macroBuf)
continue
case "include":
if i + 1 >= len(rawTokens) {
- panic("invalid syntax for include")
+ fmt.Fprintf(os.Stderr, "%s: Error: invalid syntax for include: %s: %d:%d.\n",
+ progname, rawTokens[i].file, rawTokens[i].line, rawTokens[i].offset)
+ os.Exit(1)
}
if rawTokens[i + 1].str[0] != '"' {
- panic("include file must be wrapped with quotes")
+ fmt.Fprintf(os.Stderr, "%s: Error: included file must be wrapped with quotes: %s: %d:%d.\n",
+ progname, rawTokens[i].file, rawTokens[i].line, rawTokens[i].offset)
+ os.Exit(1)
}
if incDepth == incDepthLim {
- panic("nested depth exceeds 200")
+ fmt.Fprintf(os.Stderr, "%s: Error: include depth exceeds 200: %s: %d:%d.\n",
+ progname, rawTokens[i].file)
+ os.Exit(1)
}
tmp := rawTokens[i + 1].str
@@ -212,8 +223,10 @@ func parse(tokens[]Token) []Operation {
case "push":
if i + 1 >= len(tokens) {
- /* FIXME: Better error message */
- panic("invalid push usage")
+ fmt.Fprintf(os.Stderr, "%s: Error: push expected variable: %s: %d: %d.\n",
+ progname, tokens[i].file, tokens[i].line, tokens[i].offset)
+ os.Exit(1)
+
}
variableIndex := -1
for y := 0; y < len(variables); y++ {
@@ -222,19 +235,21 @@ func parse(tokens[]Token) []Operation {
}
}
if variableIndex == -1 {
- panic("undeclared variable")
+ fmt.Fprintf(os.Stderr, "%s: Error: variable not declared '%s': %s: %d:%d.\n",
+ progname, tokens[i].str, tokens[i].file, tokens[i].line, tokens[i].offset)
+ os.Exit(1)
}
op.name = "push"
op.strData = variables[variableIndex]
i++
- /* FIXME: better solution */
ops = append(ops, op)
continue
case "pull":
if i + 1 >= len(tokens) {
- /* FIXME: Better error message */
- panic("invalid pull usage")
+ fmt.Fprintf(os.Stderr, "%s: Error: pull expected variable: %s: %d:%d.\n",
+ progname, tokens[i].file, tokens[i].line, tokens[i].offset)
+ os.Exit(1)
}
variableIndex := -1
for y := 0; y < len(variables); y++ {
@@ -254,8 +269,9 @@ func parse(tokens[]Token) []Operation {
case "var":
if i + 1 >= len(tokens) {
- /* FIXME: Better error message */
- panic("invalid var usage")
+ fmt.Fprintf(os.Stderr, "%s: Error: var expected variable: %s: %d:%d.\n",
+ progname, tokens[i].file, tokens[i].line, tokens[i].offset)
+ os.Exit(1)
}
op.name = "variable"
op.strData = tokens[i + 1].str
@@ -493,7 +509,6 @@ func mapX86_64linux(op Operation) string{
buf += "\tpush r10\n"
case "syscall":
- /* FIXME: Consider making it more consise */
switch op.intData {
case 7:
buf += "\tpop rax\n"
@@ -583,14 +598,13 @@ func compile(ops[] Operation, w io.Writer) {
func main() {
argv := os.Args;
argc := len(argv);
- progname := argv[0]
+ progname = argv[0]
suffix := ".gorth"
if argc != 2 {
fmt.Fprintf(os.Stderr, "%s: Error: expected one input file.\n", progname)
os.Exit(1)
}
-
srcFile := argv[argc - 1]
if !strings.HasSuffix(srcFile, suffix) || len(srcFile) < 7 {
fmt.Fprintf(os.Stderr, "%s: Error: invalid file format '%s'.\n", progname, srcFile)
@@ -604,8 +618,8 @@ func main() {
assemFile := srcFile[:len(srcFile) - 6] + ".s"
file, err := os.Create(assemFile)
if err != nil {
- /* FIXME: better error message*/
fmt.Fprintf(os.Stderr, "%s: Error: failed create output file '%s'.\n", progname, file)
+ os.Exit(1)
}
tokens := tokenize(argv[argc - 1])
tokens = preprocess(tokens)