Small perf tweaks
This commit is contained in:
parent
a656dc0d78
commit
132876fce4
@ -8,11 +8,6 @@ var Nil = NewParser("Nil", func(ps *State) *Node {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
var Never = NewParser("Never", func(ps *State) *Node {
|
|
||||||
ps.ErrorHere("not anything")
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
func And(parsers ...Parserish) Parser {
|
func And(parsers ...Parserish) Parser {
|
||||||
if len(parsers) == 0 {
|
if len(parsers) == 0 {
|
||||||
return Nil
|
return Nil
|
||||||
@ -20,7 +15,7 @@ func And(parsers ...Parserish) Parser {
|
|||||||
|
|
||||||
parserfied := ParsifyAll(parsers...)
|
parserfied := ParsifyAll(parsers...)
|
||||||
|
|
||||||
return NewParser("And", 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 {
|
||||||
@ -56,7 +51,7 @@ func Any(parsers ...Parserish) Parser {
|
|||||||
|
|
||||||
parserfied := ParsifyAll(parsers...)
|
parserfied := ParsifyAll(parsers...)
|
||||||
|
|
||||||
return NewParser("Any", 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 {
|
||||||
@ -78,19 +73,19 @@ func Any(parsers ...Parserish) Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Kleene(opScan Parserish, sepScan ...Parserish) Parser {
|
func Kleene(opScan Parserish, sepScan ...Parserish) Parser {
|
||||||
return NewParser("Kleene", manyImpl(0, opScan, Never, sepScan...))
|
return NewParser("Kleene()", manyImpl(0, opScan, nil, sepScan...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func KleeneUntil(opScan Parserish, untilScan Parserish, sepScan ...Parserish) Parser {
|
func KleeneUntil(opScan Parserish, untilScan Parserish, sepScan ...Parserish) Parser {
|
||||||
return NewParser("KleeneUntil", 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 NewParser("Many", manyImpl(1, opScan, Never, sepScan...))
|
return NewParser("Many()", manyImpl(1, opScan, nil, sepScan...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ManyUntil(opScan Parserish, untilScan Parserish, sepScan ...Parserish) Parser {
|
func ManyUntil(opScan Parserish, untilScan Parserish, sepScan ...Parserish) Parser {
|
||||||
return NewParser("ManyUntil", 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 {
|
||||||
@ -107,6 +102,7 @@ func manyImpl(min int, op Parserish, until Parserish, sep ...Parserish) Parser {
|
|||||||
startpos := ps.Pos
|
startpos := ps.Pos
|
||||||
for {
|
for {
|
||||||
tempPos := ps.Pos
|
tempPos := ps.Pos
|
||||||
|
if untilParser != nil {
|
||||||
node = untilParser(ps)
|
node = untilParser(ps)
|
||||||
if !ps.Errored() {
|
if !ps.Errored() {
|
||||||
ps.Pos = tempPos
|
ps.Pos = tempPos
|
||||||
@ -118,6 +114,7 @@ func manyImpl(min int, op Parserish, until Parserish, sep ...Parserish) Parser {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
ps.ClearError()
|
ps.ClearError()
|
||||||
|
}
|
||||||
|
|
||||||
node = opParser(ps)
|
node = opParser(ps)
|
||||||
if ps.Errored() {
|
if ps.Errored() {
|
||||||
@ -144,7 +141,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 NewParser("Maybe", 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()
|
||||||
@ -158,7 +155,7 @@ func Maybe(parser Parserish) Parser {
|
|||||||
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 NewParser("Map", 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
|
||||||
@ -184,7 +181,7 @@ func flatten(n *Node) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Merge(parser Parserish) Parser {
|
func Merge(parser Parserish) Parser {
|
||||||
return NewParser("Merge", 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)}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,6 @@ func TestNil(t *testing.T) {
|
|||||||
require.False(t, p2.Errored())
|
require.False(t, p2.Errored())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNever(t *testing.T) {
|
|
||||||
node, p2 := runParser("hello world", Never)
|
|
||||||
|
|
||||||
require.Nil(t, node)
|
|
||||||
require.Equal(t, 0, p2.Pos)
|
|
||||||
require.True(t, p2.Errored())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAnd(t *testing.T) {
|
func TestAnd(t *testing.T) {
|
||||||
parser := And("hello", "world")
|
parser := And("hello", "world")
|
||||||
|
|
||||||
|
@ -33,6 +33,8 @@ type Parserish interface{}
|
|||||||
|
|
||||||
func Parsify(p Parserish) Parser {
|
func Parsify(p Parserish) Parser {
|
||||||
switch p := p.(type) {
|
switch p := p.(type) {
|
||||||
|
case nil:
|
||||||
|
return nil
|
||||||
case func(*State) *Node:
|
case func(*State) *Node:
|
||||||
return NewParser("anonymous func", p)
|
return NewParser("anonymous func", p)
|
||||||
case Parser:
|
case Parser:
|
||||||
|
18
state.go
18
state.go
@ -2,8 +2,6 @@ package goparsify
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Error struct {
|
type Error struct {
|
||||||
@ -18,7 +16,7 @@ type State struct {
|
|||||||
Input string
|
Input string
|
||||||
Pos int
|
Pos int
|
||||||
Error Error
|
Error Error
|
||||||
WSChars string
|
WSChars []byte
|
||||||
NoAutoWS bool
|
NoAutoWS bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,13 +33,17 @@ func (s *State) AutoWS() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) WS() {
|
func (s *State) WS() {
|
||||||
|
loop:
|
||||||
for s.Pos < len(s.Input) {
|
for s.Pos < len(s.Input) {
|
||||||
r, w := utf8.DecodeRuneInString(s.Input[s.Pos:])
|
// Pretty sure this is unicode safe as long as WSChars is only in the ascii range...
|
||||||
if !strings.ContainsRune(s.WSChars, r) {
|
for _, ws := range s.WSChars {
|
||||||
return
|
if s.Input[s.Pos] == ws {
|
||||||
|
s.Pos++
|
||||||
|
continue loop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s.Pos += w
|
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,5 +68,5 @@ func (s *State) Errored() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func InputString(input string) *State {
|
func InputString(input string) *State {
|
||||||
return &State{Input: input, WSChars: "\t\n\v\f\r \x85\xA0"}
|
return &State{Input: input, WSChars: []byte("\t\n\v\f\r ")}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user