summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--combinator.go7
-rw-r--r--debugon.go6
-rw-r--r--json/json_test.go3
-rw-r--r--readme.md14
-rw-r--r--result.go2
-rw-r--r--state.go10
6 files changed, 27 insertions, 15 deletions
diff --git a/combinator.go b/combinator.go
index ca62f30..d7be3f9 100644
--- a/combinator.go
+++ b/combinator.go
@@ -39,11 +39,11 @@ func Any(parsers ...Parserish) Parser {
predictor := [255]int{}
return NewParser("Any()", func(ps *State, node *Result) {
+ ps.WS(ps)
if ps.Pos >= len(ps.Input) {
ps.ErrorHere("!EOF")
return
}
- longestError := Error{}
startpos := ps.Pos
predictorChar := ps.Input[startpos]
predicted := predictor[predictorChar]
@@ -53,9 +53,7 @@ func Any(parsers ...Parserish) Parser {
return
}
- if ps.Error.pos >= longestError.pos {
- longestError = ps.Error
- }
+ longestError := ps.Error
if ps.Cut <= startpos {
ps.Recover()
} else {
@@ -159,7 +157,6 @@ func Bind(parser Parserish, val interface{}) Parser {
return
}
node.Result = val
- return
}
}
diff --git a/debugon.go b/debugon.go
index 302b0ec..ceb3c33 100644
--- a/debugon.go
+++ b/debugon.go
@@ -49,7 +49,11 @@ func (dp *debugParser) logf(ps *State, result *Result, format string, args ...in
if ps.Errored() {
buf.WriteString(fmt.Sprintf(" did not find %s", ps.Error.expected))
} else if result != nil {
- buf.WriteString(fmt.Sprintf(" found %s", result.String()))
+ resultStr := strconv.Quote(result.String())
+ if len(resultStr) > 20 {
+ resultStr = resultStr[0:20]
+ }
+ buf.WriteString(fmt.Sprintf(" found %s", resultStr))
}
buf.WriteRune('\n')
return buf.String()
diff --git a/json/json_test.go b/json/json_test.go
index f020a40..13f2e40 100644
--- a/json/json_test.go
+++ b/json/json_test.go
@@ -4,6 +4,8 @@ import (
stdlibJson "encoding/json"
"testing"
+ "os"
+
parsecJson "github.com/prataprc/goparsec/json"
"github.com/stretchr/testify/require"
"github.com/vektah/goparsify"
@@ -53,6 +55,7 @@ func BenchmarkUnmarshalParsec(b *testing.B) {
}
func BenchmarkUnmarshalParsify(b *testing.B) {
+ goparsify.EnableLogging(os.Stdout)
for i := 0; i < b.N; i++ {
_, err := Unmarshal(benchmarkString)
require.NoError(b, err)
diff --git a/readme.md b/readme.md
index ba35397..853dd6b 100644
--- a/readme.md
+++ b/readme.md
@@ -9,16 +9,18 @@ Run(parser, input, ASCIIWhitespace)
```
### benchmarks
-I dont have many benchmarks set up yet, but the json parser keeps up with the stdlib for raw speed:
+I dont have many benchmarks set up yet, but the json parser is 50% faster than the stdlib.
```
-$ go test -bench=. -benchtime=2s -benchmem ./json
-BenchmarkUnmarshalParsec-8 50000 66012 ns/op 50462 B/op 1318 allocs/op
-BenchmarkUnmarshalParsify-8 100000 46713 ns/op 44543 B/op 332 allocs/op
-BenchmarkUnmarshalStdlib-8 100000 46967 ns/op 13952 B/op 262 allocs/op
+$ go test -bench=. -benchmem -benchtime=5s ./json -run=none
+BenchmarkUnmarshalParsec-8 100000 65682 ns/op 50464 B/op 1318 allocs/op
+BenchmarkUnmarshalParsify-8 200000 32656 ns/op 42094 B/op 220 allocs/op
+BenchmarkUnmarshalStdlib-8 200000 48023 ns/op 13952 B/op 262 allocs/op
PASS
-ok github.com/vektah/goparsify/json 14.424s
+ok github.com/vektah/goparsify/json 24.314s
```
+Most of the remaining small allocs are from putting things in `interface{}` and are pretty unavoidable. https://www.darkcoding.net/software/go-the-price-of-interface/ is a good read.
+
### debugging parsers
When a parser isnt working as you intended you can build with debugging and enable logging to get a detailed log of exactly what the parser is doing.
diff --git a/result.go b/result.go
index cdad054..21440eb 100644
--- a/result.go
+++ b/result.go
@@ -5,6 +5,7 @@ import (
"strings"
)
+// TrashResult is used in places where the result isnt wanted, but something needs to be passed in to satisfy the interface.
var TrashResult = &Result{}
// Result is the output of a parser. Usually only one of its fields will be set and should be though of
@@ -16,6 +17,7 @@ type Result struct {
Result interface{}
}
+// String stringifies a node. This is only called from debug code.
func (r Result) String() string {
if r.Result != nil {
if rs, ok := r.Result.(fmt.Stringer); ok {
diff --git a/state.go b/state.go
index 1b7e9f2..5d35ac8 100644
--- a/state.go
+++ b/state.go
@@ -1,6 +1,7 @@
package goparsify
import (
+ "strconv"
"unicode"
"unicode/utf8"
)
@@ -72,11 +73,14 @@ func (s *State) Preview(x int) string {
if s.Pos >= len(s.Input) {
return ""
}
- if len(s.Input)-s.Pos >= x {
- return s.Input[s.Pos : s.Pos+x]
+
+ quoted := strconv.Quote(s.Get())
+ quoted = quoted[1 : len(quoted)-1]
+ if len(quoted) >= x {
+ return quoted[0:x]
}
- return s.Input[s.Pos:]
+ return quoted
}
// ErrorHere raises an error at the current position.