aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/vartan/compile.go84
-rw-r--r--cmd/vartan/parse.go18
-rw-r--r--cmd/vartan/root.go10
-rw-r--r--error/error.go52
4 files changed, 139 insertions, 25 deletions
diff --git a/cmd/vartan/compile.go b/cmd/vartan/compile.go
index 769f143..3601f00 100644
--- a/cmd/vartan/compile.go
+++ b/cmd/vartan/compile.go
@@ -3,8 +3,11 @@ package main
import (
"encoding/json"
"fmt"
+ "io/ioutil"
"os"
+ "path/filepath"
+ verr "github.com/nihei9/vartan/error"
"github.com/nihei9/vartan/grammar"
"github.com/nihei9/vartan/spec"
"github.com/spf13/cobra"
@@ -28,7 +31,63 @@ func init() {
}
func runCompile(cmd *cobra.Command, args []string) (retErr error) {
- gram, err := readGrammar(*compileFlags.grammar)
+ var tmpDirPath string
+ defer func() {
+ if tmpDirPath == "" {
+ return
+ }
+ os.RemoveAll(tmpDirPath)
+ }()
+
+ grmPath := *compileFlags.grammar
+ defer func() {
+ v := recover()
+ if v != nil {
+ err, ok := v.(error)
+ if !ok {
+ retErr = fmt.Errorf("an unexpected error occurred: %v\n", v)
+ fmt.Fprintln(os.Stderr, retErr)
+ return
+ }
+
+ retErr = err
+ }
+
+ if retErr != nil {
+ specErr, ok := retErr.(*verr.SpecError)
+ if ok {
+ if *compileFlags.grammar != "" {
+ specErr.FilePath = grmPath
+ specErr.SourceName = grmPath
+ } else {
+ specErr.FilePath = grmPath
+ specErr.SourceName = "stdin"
+ }
+ }
+ fmt.Fprintln(os.Stderr, retErr)
+ }
+ }()
+
+ if grmPath == "" {
+ var err error
+ tmpDirPath, err = os.MkdirTemp("", "vartan-compile-*")
+ if err != nil {
+ return err
+ }
+
+ src, err := ioutil.ReadAll(os.Stdin)
+ if err != nil {
+ return err
+ }
+
+ grmPath = filepath.Join(tmpDirPath, "stdin.vr")
+ err = ioutil.WriteFile(grmPath, src, 0600)
+ if err != nil {
+ return err
+ }
+ }
+
+ gram, err := readGrammar(grmPath)
if err != nil {
return err
}
@@ -46,17 +105,22 @@ func runCompile(cmd *cobra.Command, args []string) (retErr error) {
return nil
}
-func readGrammar(path string) (*grammar.Grammar, error) {
- r := os.Stdin
- if path != "" {
- f, err := os.Open(path)
- if err != nil {
- return nil, fmt.Errorf("Cannot open the grammar file %s: %w", path, err)
+func readGrammar(path string) (grm *grammar.Grammar, retErr error) {
+ defer func() {
+ err := recover()
+ specErr, ok := err.(*verr.SpecError)
+ if ok {
+ specErr.FilePath = path
+ retErr = specErr
}
- defer f.Close()
- r = f
+ }()
+
+ f, err := os.Open(path)
+ if err != nil {
+ return nil, fmt.Errorf("Cannot open the grammar file %s: %w", path, err)
}
- ast, err := spec.Parse(r)
+ defer f.Close()
+ ast, err := spec.Parse(f)
if err != nil {
return nil, err
}
diff --git a/cmd/vartan/parse.go b/cmd/vartan/parse.go
index 8089c5e..ef22ff3 100644
--- a/cmd/vartan/parse.go
+++ b/cmd/vartan/parse.go
@@ -28,6 +28,24 @@ func init() {
}
func runParse(cmd *cobra.Command, args []string) (retErr error) {
+ defer func() {
+ v := recover()
+ if v != nil {
+ err, ok := v.(error)
+ if !ok {
+ retErr = fmt.Errorf("an unexpected error occurred: %v\n", v)
+ fmt.Fprintln(os.Stderr, retErr)
+ return
+ }
+
+ retErr = err
+ }
+
+ if retErr != nil {
+ fmt.Fprintln(os.Stderr, retErr)
+ }
+ }()
+
cgram, err := readCompiledGrammar(args[0])
if err != nil {
return fmt.Errorf("Cannot read a compiled grammar: %w", err)
diff --git a/cmd/vartan/root.go b/cmd/vartan/root.go
index ad163a6..a193577 100644
--- a/cmd/vartan/root.go
+++ b/cmd/vartan/root.go
@@ -1,9 +1,6 @@
package main
import (
- "fmt"
- "os"
-
"github.com/spf13/cobra"
)
@@ -19,10 +16,5 @@ var rootCmd = &cobra.Command{
}
func Execute() error {
- err := rootCmd.Execute()
- if err != nil {
- fmt.Fprintf(os.Stderr, "%v\n", err)
- return err
- }
- return nil
+ return rootCmd.Execute()
}
diff --git a/error/error.go b/error/error.go
index 1745c52..cc4fed5 100644
--- a/error/error.go
+++ b/error/error.go
@@ -1,15 +1,55 @@
package error
-import "fmt"
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "strings"
+)
type SpecError struct {
- Cause error
- Row int
+ Cause error
+ FilePath string
+ SourceName string
+ Row int
}
func (e *SpecError) Error() string {
- if e.Row == 0 {
- return fmt.Sprintf("error: %v", e.Cause)
+ var b strings.Builder
+ if e.SourceName != "" {
+ fmt.Fprintf(&b, "%v: ", e.SourceName)
}
- return fmt.Sprintf("%v: error: %v", e.Row, e.Cause)
+ if e.Row != 0 {
+ fmt.Fprintf(&b, "%v: ", e.Row)
+ }
+ fmt.Fprintf(&b, "error: %v", e.Cause)
+
+ line := readLine(e.FilePath, e.Row)
+ if line != "" {
+ fmt.Fprintf(&b, "\n %v", line)
+ }
+
+ return b.String()
+}
+
+func readLine(filePath string, row int) string {
+ if filePath == "" || row <= 0 {
+ return ""
+ }
+
+ f, err := os.Open(filePath)
+ if err != nil {
+ return ""
+ }
+
+ i := 1
+ s := bufio.NewScanner(f)
+ for s.Scan() {
+ if i == row {
+ return s.Text()
+ }
+ i++
+ }
+
+ return ""
}