aboutsummaryrefslogtreecommitdiff
path: root/cmd/vartan/compile.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/vartan/compile.go')
-rw-r--r--cmd/vartan/compile.go108
1 files changed, 89 insertions, 19 deletions
diff --git a/cmd/vartan/compile.go b/cmd/vartan/compile.go
index 7e594a8..b8b97b1 100644
--- a/cmd/vartan/compile.go
+++ b/cmd/vartan/compile.go
@@ -3,10 +3,10 @@ package main
import (
"encoding/json"
"fmt"
+ "io"
"io/ioutil"
"os"
"path/filepath"
- "strings"
verr "github.com/nihei9/vartan/error"
"github.com/nihei9/vartan/grammar"
@@ -84,20 +84,31 @@ func runCompile(cmd *cobra.Command, args []string) (retErr error) {
return err
}
- var reportFileName string
- {
- _, grmFileName := filepath.Split(grmPath)
- reportFileName = fmt.Sprintf("%v-report.json", strings.TrimSuffix(grmFileName, ".vartan"))
- }
-
- cgram, err := grammar.Compile(gram, grammar.EnableReporting(reportFileName))
+ cgram, report, err := grammar.Compile(gram, grammar.EnableReporting())
if err != nil {
return err
}
- err = writeCompiledGrammar(cgram, *compileFlags.output)
+ err = writeCompiledGrammarAndReport(cgram, report, *compileFlags.output)
if err != nil {
- return fmt.Errorf("Cannot write a compiled grammar: %w", err)
+ return fmt.Errorf("Cannot write an output files: %w", err)
+ }
+
+ var implicitlyResolvedCount int
+ for _, s := range report.States {
+ for _, c := range s.SRConflict {
+ if c.ResolvedBy == grammar.ResolvedByShift.Int() {
+ implicitlyResolvedCount++
+ }
+ }
+ for _, c := range s.RRConflict {
+ if c.ResolvedBy == grammar.ResolvedByProdOrder.Int() {
+ implicitlyResolvedCount++
+ }
+ }
+ }
+ if implicitlyResolvedCount > 0 {
+ fmt.Fprintf(os.Stdout, "%v conflicts\n", implicitlyResolvedCount)
}
return nil
@@ -121,20 +132,79 @@ func readGrammar(path string) (grm *grammar.Grammar, retErr error) {
return b.Build()
}
-func writeCompiledGrammar(cgram *spec.CompiledGrammar, path string) error {
- out, err := json.Marshal(cgram)
+// writeCompiledGrammarAndReport writes a compiled grammar and a report to a files located at a specified path.
+// This function selects one of the following output methods depending on how the path is specified.
+//
+// 1. When the path is a directory path, this function writes the compiled grammar and the report to
+// <path>/<grammar-name>.json and <path>/<grammar-name>-report.json files, respectively.
+// <grammar-name>-report.json as the output files.
+// 2. When the path is a file path or a non-exitent path, this function asumes that the path represents a file
+// path for the compiled grammar. Then it also writes the report in the same directory as the compiled grammar.
+// The report file is named <grammar-name>.json.
+// 3. When the path is an empty string, this function writes the compiled grammar to the stdout and writes
+// the report to a file named <current-directory>/<grammar-name>-report.json.
+func writeCompiledGrammarAndReport(cgram *spec.CompiledGrammar, report *spec.Report, path string) error {
+ cgramPath, reportPath, err := makeOutputFilePaths(cgram.Name, path)
if err != nil {
return err
}
- w := os.Stdout
- if path != "" {
- f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+
+ {
+ var cgramW io.Writer
+ if cgramPath != "" {
+ cgramFile, err := os.OpenFile(cgramPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+ if err != nil {
+ return err
+ }
+ defer cgramFile.Close()
+ cgramW = cgramFile
+ } else {
+ cgramW = os.Stdout
+ }
+
+ b, err := json.Marshal(cgram)
if err != nil {
- return fmt.Errorf("Cannot open the output file %s: %w", path, err)
+ return err
}
- defer f.Close()
- w = f
+ fmt.Fprintf(cgramW, "%v\n", string(b))
}
- fmt.Fprintf(w, "%v\n", string(out))
+
+ {
+ reportFile, err := os.OpenFile(reportPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+ if err != nil {
+ return err
+ }
+ defer reportFile.Close()
+
+ b, err := json.Marshal(report)
+ if err != nil {
+ return err
+ }
+ fmt.Fprintf(reportFile, "%v\n", string(b))
+ }
+
return nil
}
+
+func makeOutputFilePaths(gramName string, path string) (string, string, error) {
+ reportFileName := gramName + "-report.json"
+
+ if path == "" {
+ wd, err := os.Getwd()
+ if err != nil {
+ return "", "", err
+ }
+ return "", filepath.Join(wd, reportFileName), nil
+ }
+
+ fi, err := os.Stat(path)
+ if err != nil && !os.IsNotExist(err) {
+ return "", "", err
+ }
+ if os.IsNotExist(err) || !fi.IsDir() {
+ dir, _ := filepath.Split(path)
+ return path, filepath.Join(dir, reportFileName), nil
+ }
+
+ return filepath.Join(path, gramName+".json"), filepath.Join(path, reportFileName), nil
+}