aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2021-04-08 00:36:22 +0900
committerRyo Nihei <nihei.dev@gmail.com>2021-04-08 00:36:22 +0900
commit91b93662e8ec8a92d763fad74da56b360bba2660 (patch)
tree231e3728a0b682d9376bbe84c7a7a6ce55ff4177
parentPrint the result of the lex command in JSON format (diff)
downloadtre-91b93662e8ec8a92d763fad74da56b360bba2660.tar.gz
tre-91b93662e8ec8a92d763fad74da56b360bba2660.tar.xz
Add logging to compile command
compile command writes logs out to the maleeni-compile.log file. When you use compiler.Compile(), you can choose whether the lexer writes logs or not.
-rw-r--r--cli/cmd/compile.go27
-rw-r--r--compiler/ast.go37
-rw-r--r--compiler/compiler.go80
-rw-r--r--compiler/parser_test.go38
4 files changed, 133 insertions, 49 deletions
diff --git a/cli/cmd/compile.go b/cli/cmd/compile.go
index 23aa120..7815129 100644
--- a/cli/cmd/compile.go
+++ b/cli/cmd/compile.go
@@ -3,8 +3,10 @@ package cmd
import (
"encoding/json"
"fmt"
+ "io"
"io/ioutil"
"os"
+ "time"
"github.com/nihei9/maleeni/compiler"
"github.com/nihei9/maleeni/spec"
@@ -22,7 +24,7 @@ func init() {
rootCmd.AddCommand(cmd)
}
-func runCompile(cmd *cobra.Command, args []string) error {
+func runCompile(cmd *cobra.Command, args []string) (retErr error) {
var lspec *spec.LexSpec
{
data, err := ioutil.ReadAll(os.Stdin)
@@ -35,7 +37,28 @@ func runCompile(cmd *cobra.Command, args []string) error {
return err
}
}
- clspec, err := compiler.Compile(lspec)
+ var w io.Writer
+ {
+ f, err := os.OpenFile("maleeni-compile.log", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ w = f
+ }
+ fmt.Fprintf(w, `maleeni compile starts.
+Date time: %v
+---
+`, time.Now().Format(time.RFC3339))
+ defer func() {
+ fmt.Fprintf(w, "---\n")
+ if retErr != nil {
+ fmt.Fprintf(w, "maleeni compile failed: %v\n", retErr)
+ } else {
+ fmt.Fprintf(w, "maleeni compile succeeded.\n")
+ }
+ }()
+ clspec, err := compiler.Compile(lspec, compiler.EnableLogging(w))
if err != nil {
return err
}
diff --git a/compiler/ast.go b/compiler/ast.go
index 0b72f8d..e9c1b50 100644
--- a/compiler/ast.go
+++ b/compiler/ast.go
@@ -2,6 +2,7 @@ package compiler
import (
"fmt"
+ "io"
"sort"
"strings"
)
@@ -421,3 +422,39 @@ func positionSymbols(node astNode, n uint8) uint8 {
}
return p
}
+
+func printAST(w io.Writer, ast astNode, ruledLine string, childRuledLinePrefix string, withAttrs bool) {
+ if ast == nil {
+ return
+ }
+ fmt.Fprintf(w, ruledLine)
+ fmt.Fprintf(w, "node: %v", ast)
+ if withAttrs {
+ fmt.Fprintf(w, ", nullable: %v, first: %v, last: %v", ast.nullable(), ast.first(), ast.last())
+ }
+ fmt.Fprintf(w, "\n")
+ left, right := ast.children()
+ children := []astNode{}
+ if left != nil {
+ children = append(children, left)
+ }
+ if right != nil {
+ children = append(children, right)
+ }
+ num := len(children)
+ for i, child := range children {
+ line := "└─ "
+ if num > 1 {
+ if i == 0 {
+ line = "├─ "
+ } else if i < num-1 {
+ line = "│ "
+ }
+ }
+ prefix := "│ "
+ if i >= num-1 {
+ prefix = " "
+ }
+ printAST(w, child, childRuledLinePrefix+line, childRuledLinePrefix+prefix, withAttrs)
+ }
+}
diff --git a/compiler/compiler.go b/compiler/compiler.go
index 3ae647e..02cda43 100644
--- a/compiler/compiler.go
+++ b/compiler/compiler.go
@@ -1,8 +1,41 @@
package compiler
-import "github.com/nihei9/maleeni/spec"
+import (
+ "io"
+ "strings"
+
+ "github.com/nihei9/maleeni/log"
+ "github.com/nihei9/maleeni/spec"
+)
+
+type compilerOption func(c *compilerConfig) error
+
+func EnableLogging(w io.Writer) compilerOption {
+ return func(c *compilerConfig) error {
+ logger, err := log.NewLogger(w)
+ if err != nil {
+ return err
+ }
+ c.logger = logger
+ return nil
+ }
+}
+
+type compilerConfig struct {
+ logger log.Logger
+}
+
+func Compile(lexspec *spec.LexSpec, opts ...compilerOption) (*spec.CompiledLexSpec, error) {
+ config := &compilerConfig{
+ logger: log.NewNopLogger(),
+ }
+ for _, opt := range opts {
+ err := opt(config)
+ if err != nil {
+ return nil, err
+ }
+ }
-func Compile(lexspec *spec.LexSpec) (*spec.CompiledLexSpec, error) {
var kinds []string
var patterns map[int][]byte
{
@@ -12,16 +45,45 @@ func Compile(lexspec *spec.LexSpec) (*spec.CompiledLexSpec, error) {
kinds = append(kinds, e.Kind)
patterns[i+1] = []byte(e.Pattern)
}
+
+ config.logger.Log("Patterns:")
+ for i, p := range patterns {
+ config.logger.Log(" #%v %v", i, string(p))
+ }
}
- root, symTab, err := parse(patterns)
- if err != nil {
- return nil, err
+
+ var root astNode
+ var symTab *symbolTable
+ {
+ var err error
+ root, symTab, err = parse(patterns)
+ if err != nil {
+ return nil, err
+ }
+
+ var b strings.Builder
+ printAST(&b, root, "", "", false)
+ config.logger.Log("AST:\n%v", b.String())
}
- dfa := genDFA(root, symTab)
- tranTab, err := genTransitionTable(dfa)
- if err != nil {
- return nil, err
+
+ var tranTab *spec.TransitionTable
+ {
+ dfa := genDFA(root, symTab)
+ var err error
+ tranTab, err = genTransitionTable(dfa)
+ if err != nil {
+ return nil, err
+ }
+
+ config.logger.Log(`DFA:
+ States: %v states
+ Initial State: %v`, len(tranTab.Transition), tranTab.InitialState)
+ config.logger.Log(" Accepting States:")
+ for state, symbol := range tranTab.AcceptingStates {
+ config.logger.Log(" %v: %v", state, symbol)
+ }
}
+
return &spec.CompiledLexSpec{
Kinds: kinds,
DFA: tranTab,
diff --git a/compiler/parser_test.go b/compiler/parser_test.go
index 5c2d813..3bad222 100644
--- a/compiler/parser_test.go
+++ b/compiler/parser_test.go
@@ -1,49 +1,11 @@
package compiler
import (
- "fmt"
- "io"
"os"
"reflect"
"testing"
)
-func printAST(w io.Writer, ast astNode, ruledLine string, childRuledLinePrefix string, withAttrs bool) {
- if ast == nil {
- return
- }
- fmt.Fprintf(w, ruledLine)
- fmt.Fprintf(w, "node: %v", ast)
- if withAttrs {
- fmt.Fprintf(w, ", nullable: %v, first: %v, last: %v", ast.nullable(), ast.first(), ast.last())
- }
- fmt.Fprintf(w, "\n")
- left, right := ast.children()
- children := []astNode{}
- if left != nil {
- children = append(children, left)
- }
- if right != nil {
- children = append(children, right)
- }
- num := len(children)
- for i, child := range children {
- line := "└─ "
- if num > 1 {
- if i == 0 {
- line = "├─ "
- } else if i < num-1 {
- line = "│ "
- }
- }
- prefix := "│ "
- if i >= num-1 {
- prefix = " "
- }
- printAST(w, child, childRuledLinePrefix+line, childRuledLinePrefix+prefix, withAttrs)
- }
-}
-
func TestParser(t *testing.T) {
rune2Byte := func(char rune, index int) byte {
return []byte(string(char))[index]