Repository: openllb/hlb (go)

Issue:
wrong syntax error message
With input:
```
fs default() {
        mkfile "foo" 0644 "content"
}
```
we see:
```
$ hlb run ./test.hlb
./test.hlb:2:2: expected 3 args, found 2
```

The arg count is not the problem, it is that hlb is not recognizing the `0644` input (typo, should be `0o644`) so the error message is confusing.



Pull request description:
Break up bad lexemes by spaces so that we can return the correct syntax error
Fixes #144

- Before, the bad regex consumed too much `0644 \"content\"`, we should delimit bad tokens by whitespace

New error:
```sh
❯ hlb run test.hlb
test.hlb:2:22: unable to parse "0644"
```

Patch:
diff --git a/checker/checker.go b/checker/checker.go
index 05cffe5..edd10a0 100644
--- a/checker/checker.go
+++ b/checker/checker.go
@@ -35,7 +35,7 @@ func (c *checker) Check(mod *parser.Module) error {
 		switch n := node.(type) {
 		case *parser.Decl:
 			if n.Bad != nil {
-				c.errs = append(c.errs, ErrBadParse{n})
+				c.errs = append(c.errs, ErrBadParse{n, n.Bad.Lexeme})
 				return false
 			}
 		case *parser.ImportDecl:
@@ -286,7 +286,7 @@ func (c *checker) checkBlockStmt(scope *parser.Scope, typ parser.ObjType, block
 
 	for _, stmt := range block.NonEmptyStmts() {
 		if stmt.Bad != nil {
-			c.errs = append(c.errs, ErrBadParse{stmt})
+			c.errs = append(c.errs, ErrBadParse{stmt, stmt.Bad.Lexeme})
 			continue
 		}
 
@@ -476,7 +476,7 @@ func (c *checker) checkExpr(scope *parser.Scope, typ parser.ObjType, expr *parse
 	var err error
 	switch {
 	case expr.Bad != nil:
-		err = ErrBadParse{expr}
+		err = ErrBadParse{expr, expr.Bad.Lexeme}
 	case expr.Selector != nil:
 		// Do nothing for now.
 	case expr.Ident != nil:
diff --git a/checker/errors.go b/checker/errors.go
index 7e359a6..5bca4e7 100644
--- a/checker/errors.go
+++ b/checker/errors.go
@@ -128,11 +128,12 @@ func (e ErrImportNotExist) Error() string {
 }
 
 type ErrBadParse struct {
-	Node parser.Node
+	Node   parser.Node
+	Lexeme string
 }
 
 func (e ErrBadParse) Error() string {
-	return fmt.Sprintf("%s unable to parse", FormatPos(e.Node.Position()))
+	return fmt.Sprintf("%s unable to parse %q", FormatPos(e.Node.Position()), e.Lexeme)
 }
 
 type ErrUseModuleWithoutSelector struct {
diff --git a/parser/cst.go b/parser/cst.go
index 2cd90ca..5791c83 100644
--- a/parser/cst.go
+++ b/parser/cst.go
@@ -30,7 +30,7 @@ var (
 		Newline  = \n
 		Operator = {|}|\(|\)|,|;
 		Comment  = #[^\n]*\n
-		Bad      = .*
+		Bad      = [^\r\t\n ]*
 	`)))
 
 	// Parser parses HLB into a concrete syntax tree rooted from a Module.


Test patch:
diff --git a/checker/checker_test.go b/checker/checker_test.go
index 7ad8925..a6c6862 100644
--- a/checker/checker_test.go
+++ b/checker/checker_test.go
@@ -373,6 +373,23 @@ func TestChecker_Check(t *testing.T) {
 		"no error when input doesn't end with newline",
 		`# comment\nfs default() {\n  scratch\n}\n# comment`,
 		nil,
+	}, {
+		"errors when go-style filemode is used as arg",
+		`
+		fs default() {
+			mkfile "foo" 0644 "content"
+		}
+		`,
+		ErrBadParse{
+			Node: &parser.Bad{
+				Pos: lexer.Position{
+					Filename: "<stdin>",
+					Line:     2,
+					Column:   14,
+				},
+			},
+			Lexeme: "0644",
+		},
 	}} {
 		tc := tc
 		t.Run(tc.name, func(t *testing.T) {