add debugging
This commit is contained in:
parent
02103782eb
commit
cc9d18219a
@ -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)}
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package parsec
|
||||
package goparsify
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
11
debugoff.go
Normal file
11
debugoff.go
Normal file
@ -0,0 +1,11 @@
|
||||
// +build !debug
|
||||
|
||||
package goparsify
|
||||
|
||||
func NewParser(description string, p Parser) Parser {
|
||||
return p
|
||||
}
|
||||
|
||||
func DumpDebugStats() {
|
||||
|
||||
}
|
83
debugon.go
Normal file
83
debugon.go
Normal file
@ -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)
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
20
parser.go
20
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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package parsec
|
||||
package goparsify
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
@ -1,4 +1,4 @@
|
||||
package parsec
|
||||
package goparsify
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
Loading…
Reference in New Issue
Block a user