add debugging
This commit is contained in:
parent
02103782eb
commit
cc9d18219a
@ -1,17 +1,17 @@
|
|||||||
package parsec
|
package goparsify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Nil(ps *State) *Node {
|
var Nil = NewParser("Nil", func(ps *State) *Node {
|
||||||
return nil
|
return nil
|
||||||
}
|
})
|
||||||
|
|
||||||
func Never(ps *State) *Node {
|
var Never = NewParser("Never", func(ps *State) *Node {
|
||||||
ps.ErrorHere("not anything")
|
ps.ErrorHere("not anything")
|
||||||
return nil
|
return nil
|
||||||
}
|
})
|
||||||
|
|
||||||
func And(parsers ...Parserish) Parser {
|
func And(parsers ...Parserish) Parser {
|
||||||
if len(parsers) == 0 {
|
if len(parsers) == 0 {
|
||||||
@ -20,7 +20,7 @@ func And(parsers ...Parserish) Parser {
|
|||||||
|
|
||||||
parserfied := ParsifyAll(parsers...)
|
parserfied := ParsifyAll(parsers...)
|
||||||
|
|
||||||
return func(ps *State) *Node {
|
return NewParser("And", func(ps *State) *Node {
|
||||||
var nodes = make([]*Node, 0, len(parserfied))
|
var nodes = make([]*Node, 0, len(parserfied))
|
||||||
startpos := ps.Pos
|
startpos := ps.Pos
|
||||||
for _, parser := range parserfied {
|
for _, parser := range parserfied {
|
||||||
@ -34,7 +34,7 @@ func And(parsers ...Parserish) Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &Node{Children: nodes}
|
return &Node{Children: nodes}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Any(parsers ...Parserish) Parser {
|
func Any(parsers ...Parserish) Parser {
|
||||||
@ -44,7 +44,7 @@ func Any(parsers ...Parserish) Parser {
|
|||||||
|
|
||||||
parserfied := ParsifyAll(parsers...)
|
parserfied := ParsifyAll(parsers...)
|
||||||
|
|
||||||
return func(ps *State) *Node {
|
return NewParser("Any", func(ps *State) *Node {
|
||||||
longestError := Error{}
|
longestError := Error{}
|
||||||
startpos := ps.Pos
|
startpos := ps.Pos
|
||||||
for _, parser := range parserfied {
|
for _, parser := range parserfied {
|
||||||
@ -62,23 +62,23 @@ func Any(parsers ...Parserish) Parser {
|
|||||||
ps.Error = longestError
|
ps.Error = longestError
|
||||||
ps.Pos = startpos
|
ps.Pos = startpos
|
||||||
return nil
|
return nil
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Kleene(opScan Parserish, sepScan ...Parserish) Parser {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
func Maybe(parser Parserish) Parser {
|
||||||
parserfied := Parsify(parser)
|
parserfied := Parsify(parser)
|
||||||
|
|
||||||
return func(ps *State) *Node {
|
return NewParser("Maybe", func(ps *State) *Node {
|
||||||
node := parserfied(ps)
|
node := parserfied(ps)
|
||||||
if ps.Errored() {
|
if ps.Errored() {
|
||||||
ps.ClearError()
|
ps.ClearError()
|
||||||
@ -140,19 +140,19 @@ func Maybe(parser Parserish) Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return node
|
return node
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Map(parser Parserish, f func(n *Node) *Node) Parser {
|
func Map(parser Parserish, f func(n *Node) *Node) Parser {
|
||||||
p := Parsify(parser)
|
p := Parsify(parser)
|
||||||
|
|
||||||
return func(ps *State) *Node {
|
return NewParser("Map", func(ps *State) *Node {
|
||||||
node := p(ps)
|
node := p(ps)
|
||||||
if ps.Errored() {
|
if ps.Errored() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return f(node)
|
return f(node)
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func flatten(n *Node) string {
|
func flatten(n *Node) string {
|
||||||
@ -172,7 +172,7 @@ func flatten(n *Node) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Merge(parser Parserish) Parser {
|
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)}
|
return &Node{Token: flatten(n)}
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package parsec
|
package goparsify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"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"
|
parsecJson "github.com/prataprc/goparsec/json"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/vektah/goparsify"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUnmarshal(t *testing.T) {
|
func TestUnmarshal(t *testing.T) {
|
||||||
@ -58,6 +59,7 @@ func BenchmarkUnmarshalParsify(b *testing.B) {
|
|||||||
_, err := Unmarshal(benchmarkString)
|
_, err := Unmarshal(benchmarkString)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
}
|
}
|
||||||
|
goparsify.DumpDebugStats()
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkUnmarshalStdlib(b *testing.B) {
|
func BenchmarkUnmarshalStdlib(b *testing.B) {
|
||||||
|
20
parser.go
20
parser.go
@ -1,4 +1,4 @@
|
|||||||
package parsec
|
package goparsify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -33,8 +33,8 @@ type Parserish interface{}
|
|||||||
|
|
||||||
func Parsify(p Parserish) Parser {
|
func Parsify(p Parserish) Parser {
|
||||||
switch p := p.(type) {
|
switch p := p.(type) {
|
||||||
case func(*State) *Node:
|
//case func(*State) *Node:
|
||||||
return Parser(p)
|
// return NewParser("anonymous func", p)
|
||||||
case Parser:
|
case Parser:
|
||||||
return p
|
return p
|
||||||
case *Parser:
|
case *Parser:
|
||||||
@ -70,7 +70,7 @@ func ParseString(parser Parserish, input string) (result interface{}, remaining
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Exact(match string) Parser {
|
func Exact(match string) Parser {
|
||||||
return func(ps *State) *Node {
|
return NewParser(match, func(ps *State) *Node {
|
||||||
if !strings.HasPrefix(ps.Get(), match) {
|
if !strings.HasPrefix(ps.Get(), match) {
|
||||||
ps.ErrorHere(match)
|
ps.ErrorHere(match)
|
||||||
return nil
|
return nil
|
||||||
@ -79,7 +79,7 @@ func Exact(match string) Parser {
|
|||||||
ps.Advance(len(match))
|
ps.Advance(len(match))
|
||||||
|
|
||||||
return &Node{Token: match}
|
return &Node{Token: match}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseRepetition(defaultMin, defaultMax int, repetition ...int) (min int, max int) {
|
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 {
|
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 {
|
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 {
|
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 {
|
func WS(ps *State) *Node {
|
||||||
ws(ps)
|
ws(ps)
|
||||||
@ -181,7 +181,7 @@ func WS(ps *State) *Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func String(quote rune) Parser {
|
func String(quote rune) Parser {
|
||||||
return func(ps *State) *Node {
|
return NewParser("string", func(ps *State) *Node {
|
||||||
var r rune
|
var r rune
|
||||||
var w int
|
var w int
|
||||||
var matched int
|
var matched int
|
||||||
@ -213,5 +213,5 @@ func String(quote rune) Parser {
|
|||||||
|
|
||||||
ps.ErrorHere("\"")
|
ps.ErrorHere("\"")
|
||||||
return nil
|
return nil
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package parsec
|
package goparsify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package parsec
|
package goparsify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
Loading…
Reference in New Issue
Block a user