summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Scarr <adam@vektah.net>2017-08-07 20:07:29 +1000
committerAdam Scarr <adam@vektah.net>2017-08-07 20:07:29 +1000
commitcc9d18219af9375ad89eaa8a23f1e0bcffa5734e (patch)
tree4aaf4771b90fbf622f1ebb80a8dabd6a149deb69
parent02103782eb22edeca876936596674fa07442daf4 (diff)
add debugging
-rw-r--r--combinator.go38
-rw-r--r--combinator_test.go2
-rw-r--r--debugoff.go11
-rw-r--r--debugon.go83
-rw-r--r--json/json_test.go2
-rw-r--r--parser.go20
-rw-r--r--parser_test.go2
-rw-r--r--state.go2
-rw-r--r--state_test.go2
9 files changed, 129 insertions, 33 deletions
diff --git a/combinator.go b/combinator.go
index 3cb8c6d..7dc4147 100644
--- a/combinator.go
+++ b/combinator.go
@@ -1,17 +1,17 @@
-package parsec
+package goparsify
import (
"bytes"
)
-func Nil(ps *State) *Node {
+var Nil = NewParser("Nil", func(ps *State) *Node {
return nil
-}
+})
-func Never(ps *State) *Node {
+var Never = NewParser("Never", func(ps *State) *Node {
ps.ErrorHere("not anything")
return nil
-}
+})
func And(parsers ...Parserish) Parser {
if len(parsers) == 0 {
@@ -20,7 +20,7 @@ func And(parsers ...Parserish) Parser {
parserfied := ParsifyAll(parsers...)
- return func(ps *State) *Node {
+ return NewParser("And", func(ps *State) *Node {
var nodes = make([]*Node, 0, len(parserfied))
startpos := ps.Pos
for _, parser := range parserfied {
@@ -34,7 +34,7 @@ func And(parsers ...Parserish) Parser {
}
}
return &Node{Children: nodes}
- }
+ })
}
func Any(parsers ...Parserish) Parser {
@@ -44,7 +44,7 @@ func Any(parsers ...Parserish) Parser {
parserfied := ParsifyAll(parsers...)
- return func(ps *State) *Node {
+ return NewParser("Any", func(ps *State) *Node {
longestError := Error{}
startpos := ps.Pos
for _, parser := range parserfied {
@@ -62,23 +62,23 @@ func Any(parsers ...Parserish) Parser {
ps.Error = longestError
ps.Pos = startpos
return nil
- }
+ })
}
func Kleene(opScan Parserish, sepScan ...Parserish) Parser {
- return manyImpl(0, opScan, Never, sepScan...)
+ return NewParser("Kleene", manyImpl(0, opScan, Never, sepScan...))
}
func KleeneUntil(opScan Parserish, untilScan Parserish, sepScan ...Parserish) Parser {
- return manyImpl(0, opScan, untilScan, sepScan...)
+ return NewParser("KleeneUntil", manyImpl(0, opScan, untilScan, sepScan...))
}
func Many(opScan Parserish, sepScan ...Parserish) Parser {
- return manyImpl(1, opScan, Never, sepScan...)
+ return NewParser("Many", manyImpl(1, opScan, Never, sepScan...))
}
func ManyUntil(opScan Parserish, untilScan Parserish, sepScan ...Parserish) Parser {
- return manyImpl(1, opScan, untilScan, sepScan...)
+ return NewParser("ManyUntil", manyImpl(1, opScan, untilScan, sepScan...))
}
func manyImpl(min int, op Parserish, until Parserish, sep ...Parserish) Parser {
@@ -132,7 +132,7 @@ func manyImpl(min int, op Parserish, until Parserish, sep ...Parserish) Parser {
func Maybe(parser Parserish) Parser {
parserfied := Parsify(parser)
- return func(ps *State) *Node {
+ return NewParser("Maybe", func(ps *State) *Node {
node := parserfied(ps)
if ps.Errored() {
ps.ClearError()
@@ -140,19 +140,19 @@ func Maybe(parser Parserish) Parser {
}
return node
- }
+ })
}
func Map(parser Parserish, f func(n *Node) *Node) Parser {
p := Parsify(parser)
- return func(ps *State) *Node {
+ return NewParser("Map", func(ps *State) *Node {
node := p(ps)
if ps.Errored() {
return nil
}
return f(node)
- }
+ })
}
func flatten(n *Node) string {
@@ -172,7 +172,7 @@ func flatten(n *Node) string {
}
func Merge(parser Parserish) Parser {
- return Map(parser, func(n *Node) *Node {
+ return NewParser("Merge", Map(parser, func(n *Node) *Node {
return &Node{Token: flatten(n)}
- })
+ }))
}
diff --git a/combinator_test.go b/combinator_test.go
index 0cd5ea5..0f10b01 100644
--- a/combinator_test.go
+++ b/combinator_test.go
@@ -1,4 +1,4 @@
-package parsec
+package goparsify
import (
"testing"
diff --git a/debugoff.go b/debugoff.go
new file mode 100644
index 0000000..8eb4790
--- /dev/null
+++ b/debugoff.go
@@ -0,0 +1,11 @@
+// +build !debug
+
+package goparsify
+
+func NewParser(description string, p Parser) Parser {
+ return p
+}
+
+func DumpDebugStats() {
+
+}
diff --git a/debugon.go b/debugon.go
new file mode 100644
index 0000000..79acf0f
--- /dev/null
+++ b/debugon.go
@@ -0,0 +1,83 @@
+// +build debug
+
+package goparsify
+
+import (
+ "fmt"
+ "runtime"
+ "sort"
+ "strings"
+ "time"
+)
+
+var parsers []*DebugParser
+
+type DebugParser struct {
+ Description string
+ Caller string
+ Next Parser
+ Time time.Duration
+ Calls int
+}
+
+func (dp *DebugParser) Parse(ps *State) *Node {
+ start := time.Now()
+
+ ret := dp.Next(ps)
+
+ dp.Time = dp.Time + time.Since(start)
+ dp.Calls++
+
+ return ret
+}
+
+func getPackageName(f *runtime.Func) string {
+ parts := strings.Split(f.Name(), ".")
+ pl := len(parts)
+
+ if parts[pl-2][0] == '(' {
+ return strings.Join(parts[0:pl-2], ".")
+ } else {
+ return strings.Join(parts[0:pl-1], ".")
+ }
+}
+
+func NewParser(description string, p Parser) Parser {
+ fpcs := make([]uintptr, 1)
+ caller := ""
+
+ for i := 1; i < 10; i++ {
+ n := runtime.Callers(i, fpcs)
+
+ if n != 0 {
+ frame := runtime.FuncForPC(fpcs[0] - 1)
+ pkg := getPackageName(frame)
+
+ if pkg != "github.com/vektah/goparsify" {
+ file, line := frame.FileLine(fpcs[0] - 1)
+ caller = fmt.Sprintf("%s:%d", file, line)
+ break
+ }
+ }
+ }
+
+ dp := &DebugParser{
+ Description: description,
+ Next: p,
+ Caller: caller,
+ }
+
+ parsers = append(parsers, dp)
+ return dp.Parse
+}
+
+func DumpDebugStats() {
+ sort.Slice(parsers, func(i, j int) bool {
+ return parsers[i].Time >= parsers[j].Time
+ })
+
+ fmt.Println("Parser stats:")
+ for _, parser := range parsers {
+ fmt.Printf("%20s\t%10s\t%10d\tcalls\t%s\n", parser.Description, parser.Time.String(), parser.Calls, parser.Caller)
+ }
+}
diff --git a/json/json_test.go b/json/json_test.go
index 84fdd5c..8f2e148 100644
--- a/json/json_test.go
+++ b/json/json_test.go
@@ -6,6 +6,7 @@ import (
parsecJson "github.com/prataprc/goparsec/json"
"github.com/stretchr/testify/require"
+ "github.com/vektah/goparsify"
)
func TestUnmarshal(t *testing.T) {
@@ -58,6 +59,7 @@ func BenchmarkUnmarshalParsify(b *testing.B) {
_, err := Unmarshal(benchmarkString)
require.NoError(b, err)
}
+ goparsify.DumpDebugStats()
}
func BenchmarkUnmarshalStdlib(b *testing.B) {
diff --git a/parser.go b/parser.go
index 30a3a01..4db525b 100644
--- a/parser.go
+++ b/parser.go
@@ -1,4 +1,4 @@
-package parsec
+package goparsify
import (
"bytes"
@@ -33,8 +33,8 @@ type Parserish interface{}
func Parsify(p Parserish) Parser {
switch p := p.(type) {
- case func(*State) *Node:
- return Parser(p)
+ //case func(*State) *Node:
+ // return NewParser("anonymous func", p)
case Parser:
return p
case *Parser:
@@ -70,7 +70,7 @@ func ParseString(parser Parserish, input string) (result interface{}, remaining
}
func Exact(match string) Parser {
- return func(ps *State) *Node {
+ return NewParser(match, func(ps *State) *Node {
if !strings.HasPrefix(ps.Get(), match) {
ps.ErrorHere(match)
return nil
@@ -79,7 +79,7 @@ func Exact(match string) Parser {
ps.Advance(len(match))
return &Node{Token: match}
- }
+ })
}
func parseRepetition(defaultMin, defaultMax int, repetition ...int) (min int, max int) {
@@ -126,11 +126,11 @@ func parseMatcher(matcher string) (matches string, ranges [][]rune) {
}
func Chars(matcher string, repetition ...int) Parser {
- return charsImpl(matcher, false, repetition...)
+ return NewParser("["+matcher+"]", charsImpl(matcher, false, repetition...))
}
func NotChars(matcher string, repetition ...int) Parser {
- return charsImpl(matcher, true, repetition...)
+ return NewParser("!["+matcher+"]", charsImpl(matcher, true, repetition...))
}
func charsImpl(matcher string, stopOn bool, repetition ...int) Parser {
@@ -173,7 +173,7 @@ func charsImpl(matcher string, stopOn bool, repetition ...int) Parser {
}
}
-var ws = Chars("\t\n\v\f\r \x85\xA0", 0)
+var ws = NewParser("WS", Chars("\t\n\v\f\r \x85\xA0", 0))
func WS(ps *State) *Node {
ws(ps)
@@ -181,7 +181,7 @@ func WS(ps *State) *Node {
}
func String(quote rune) Parser {
- return func(ps *State) *Node {
+ return NewParser("string", func(ps *State) *Node {
var r rune
var w int
var matched int
@@ -213,5 +213,5 @@ func String(quote rune) Parser {
ps.ErrorHere("\"")
return nil
- }
+ })
}
diff --git a/parser_test.go b/parser_test.go
index acb569e..d7ab0d4 100644
--- a/parser_test.go
+++ b/parser_test.go
@@ -1,4 +1,4 @@
-package parsec
+package goparsify
import (
"testing"
diff --git a/state.go b/state.go
index f8df3f1..e7a5fe4 100644
--- a/state.go
+++ b/state.go
@@ -1,4 +1,4 @@
-package parsec
+package goparsify
import "fmt"
diff --git a/state_test.go b/state_test.go
index fe04a58..c735353 100644
--- a/state_test.go
+++ b/state_test.go
@@ -1,4 +1,4 @@
-package parsec
+package goparsify
import (
"testing"