summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--combinator.go43
-rw-r--r--combinator_test.go8
-rw-r--r--parser.go2
-rw-r--r--state.go18
4 files changed, 32 insertions, 39 deletions
diff --git a/combinator.go b/combinator.go
index 12991a3..15e6cea 100644
--- a/combinator.go
+++ b/combinator.go
@@ -8,11 +8,6 @@ var Nil = NewParser("Nil", func(ps *State) *Node {
return nil
})
-var Never = NewParser("Never", func(ps *State) *Node {
- ps.ErrorHere("not anything")
- return nil
-})
-
func And(parsers ...Parserish) Parser {
if len(parsers) == 0 {
return Nil
@@ -20,7 +15,7 @@ func And(parsers ...Parserish) Parser {
parserfied := ParsifyAll(parsers...)
- return NewParser("And", 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 {
@@ -56,7 +51,7 @@ func Any(parsers ...Parserish) Parser {
parserfied := ParsifyAll(parsers...)
- return NewParser("Any", func(ps *State) *Node {
+ return NewParser("Any()", func(ps *State) *Node {
longestError := Error{}
startpos := ps.Pos
for _, parser := range parserfied {
@@ -78,19 +73,19 @@ func Any(parsers ...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 {
- return NewParser("KleeneUntil", manyImpl(0, opScan, untilScan, sepScan...))
+ return NewParser("KleeneUntil()", manyImpl(0, opScan, untilScan, sepScan...))
}
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 {
- 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 {
@@ -107,17 +102,19 @@ func manyImpl(min int, op Parserish, until Parserish, sep ...Parserish) Parser {
startpos := ps.Pos
for {
tempPos := ps.Pos
- node = untilParser(ps)
- if !ps.Errored() {
- ps.Pos = tempPos
- if len(nodes) < min {
- ps.Pos = startpos
- ps.ErrorHere("something else")
- return nil
+ if untilParser != nil {
+ node = untilParser(ps)
+ if !ps.Errored() {
+ ps.Pos = tempPos
+ if len(nodes) < min {
+ ps.Pos = startpos
+ ps.ErrorHere("something else")
+ return nil
+ }
+ break
}
- break
+ ps.ClearError()
}
- ps.ClearError()
node = opParser(ps)
if ps.Errored() {
@@ -144,7 +141,7 @@ func manyImpl(min int, op Parserish, until Parserish, sep ...Parserish) Parser {
func Maybe(parser Parserish) Parser {
parserfied := Parsify(parser)
- return NewParser("Maybe", func(ps *State) *Node {
+ return NewParser("Maybe()", func(ps *State) *Node {
node := parserfied(ps)
if ps.Errored() {
ps.ClearError()
@@ -158,7 +155,7 @@ func Maybe(parser Parserish) Parser {
func Map(parser Parserish, f func(n *Node) *Node) Parser {
p := Parsify(parser)
- return NewParser("Map", func(ps *State) *Node {
+ return NewParser("Map()", func(ps *State) *Node {
node := p(ps)
if ps.Errored() {
return nil
@@ -184,7 +181,7 @@ func flatten(n *Node) string {
}
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)}
}))
}
diff --git a/combinator_test.go b/combinator_test.go
index dbf2b50..5fd23eb 100644
--- a/combinator_test.go
+++ b/combinator_test.go
@@ -14,14 +14,6 @@ func TestNil(t *testing.T) {
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) {
parser := And("hello", "world")
diff --git a/parser.go b/parser.go
index 25a907e..2da450f 100644
--- a/parser.go
+++ b/parser.go
@@ -33,6 +33,8 @@ type Parserish interface{}
func Parsify(p Parserish) Parser {
switch p := p.(type) {
+ case nil:
+ return nil
case func(*State) *Node:
return NewParser("anonymous func", p)
case Parser:
diff --git a/state.go b/state.go
index 99e6021..e624082 100644
--- a/state.go
+++ b/state.go
@@ -2,8 +2,6 @@ package goparsify
import (
"fmt"
- "strings"
- "unicode/utf8"
)
type Error struct {
@@ -18,7 +16,7 @@ type State struct {
Input string
Pos int
Error Error
- WSChars string
+ WSChars []byte
NoAutoWS bool
}
@@ -35,13 +33,17 @@ func (s *State) AutoWS() {
}
func (s *State) WS() {
+loop:
for s.Pos < len(s.Input) {
- r, w := utf8.DecodeRuneInString(s.Input[s.Pos:])
- if !strings.ContainsRune(s.WSChars, r) {
- return
+ // Pretty sure this is unicode safe as long as WSChars is only in the ascii range...
+ for _, ws := range s.WSChars {
+ 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 {
- return &State{Input: input, WSChars: "\t\n\v\f\r \x85\xA0"}
+ return &State{Input: input, WSChars: []byte("\t\n\v\f\r ")}
}