Rename some things
This commit is contained in:
parent
b62ae2f567
commit
8b2f10f238
@ -13,7 +13,7 @@ var (
|
|||||||
sumOp = Chars("+-", 1, 1)
|
sumOp = Chars("+-", 1, 1)
|
||||||
prodOp = Chars("/*", 1, 1)
|
prodOp = Chars("/*", 1, 1)
|
||||||
|
|
||||||
groupExpr = Map(And("(", sum, ")"), func(n Node) Node {
|
groupExpr = Map(Seq("(", sum, ")"), func(n Node) Node {
|
||||||
return Node{Result: n.Child[1].Result}
|
return Node{Result: n.Child[1].Result}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ var (
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
sum = Map(And(prod, Kleene(And(sumOp, prod))), func(n Node) Node {
|
sum = Map(Seq(prod, Some(Seq(sumOp, prod))), func(n Node) Node {
|
||||||
i := n.Child[0].Result.(float64)
|
i := n.Child[0].Result.(float64)
|
||||||
|
|
||||||
for _, op := range n.Child[1].Child {
|
for _, op := range n.Child[1].Child {
|
||||||
@ -43,7 +43,7 @@ var (
|
|||||||
return Node{Result: i}
|
return Node{Result: i}
|
||||||
})
|
})
|
||||||
|
|
||||||
prod = Map(And(&value, Kleene(And(prodOp, &value))), func(n Node) Node {
|
prod = Map(Seq(&value, Some(Seq(prodOp, &value))), func(n Node) Node {
|
||||||
i := n.Child[0].Result.(float64)
|
i := n.Child[0].Result.(float64)
|
||||||
|
|
||||||
for _, op := range n.Child[1].Child {
|
for _, op := range n.Child[1].Child {
|
||||||
|
@ -4,18 +4,10 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Nil = NewParser("Nil", func(ps *State) Node {
|
func Seq(parsers ...Parserish) Parser {
|
||||||
return Node{}
|
|
||||||
})
|
|
||||||
|
|
||||||
func And(parsers ...Parserish) Parser {
|
|
||||||
if len(parsers) == 0 {
|
|
||||||
return Nil
|
|
||||||
}
|
|
||||||
|
|
||||||
parserfied := ParsifyAll(parsers...)
|
parserfied := ParsifyAll(parsers...)
|
||||||
|
|
||||||
return NewParser("And()", func(ps *State) Node {
|
return NewParser("Seq()", func(ps *State) Node {
|
||||||
result := Node{Child: make([]Node, len(parserfied))}
|
result := Node{Child: make([]Node, len(parserfied))}
|
||||||
startpos := ps.Pos
|
startpos := ps.Pos
|
||||||
for i, parser := range parserfied {
|
for i, parser := range parserfied {
|
||||||
@ -42,10 +34,6 @@ func NoAutoWS(parser Parserish) Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Any(parsers ...Parserish) Parser {
|
func Any(parsers ...Parserish) Parser {
|
||||||
if len(parsers) == 0 {
|
|
||||||
return Nil
|
|
||||||
}
|
|
||||||
|
|
||||||
parserfied := ParsifyAll(parsers...)
|
parserfied := ParsifyAll(parsers...)
|
||||||
|
|
||||||
return NewParser("Any()", func(ps *State) Node {
|
return NewParser("Any()", func(ps *State) Node {
|
||||||
@ -69,8 +57,8 @@ func Any(parsers ...Parserish) Parser {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Kleene(opScan Parserish, sepScan ...Parserish) Parser {
|
func Some(opScan Parserish, sepScan ...Parserish) Parser {
|
||||||
return NewParser("Kleene()", manyImpl(0, opScan, sepScan...))
|
return NewParser("Some()", manyImpl(0, opScan, sepScan...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Many(opScan Parserish, sepScan ...Parserish) Parser {
|
func Many(opScan Parserish, sepScan ...Parserish) Parser {
|
||||||
|
@ -6,16 +6,8 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNil(t *testing.T) {
|
func TestSeq(t *testing.T) {
|
||||||
node, p2 := runParser("hello world", Nil)
|
parser := Seq("hello", "world")
|
||||||
|
|
||||||
require.Equal(t, Node{}, node)
|
|
||||||
require.Equal(t, 0, p2.Pos)
|
|
||||||
require.False(t, p2.Errored())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAnd(t *testing.T) {
|
|
||||||
parser := And("hello", "world")
|
|
||||||
|
|
||||||
t.Run("matches sequence", func(t *testing.T) {
|
t.Run("matches sequence", func(t *testing.T) {
|
||||||
node, p2 := runParser("hello world", parser)
|
node, p2 := runParser("hello world", parser)
|
||||||
@ -29,10 +21,6 @@ func TestAnd(t *testing.T) {
|
|||||||
require.Equal(t, 6, p2.Error.pos)
|
require.Equal(t, 6, p2.Error.pos)
|
||||||
require.Equal(t, 0, p2.Pos)
|
require.Equal(t, 0, p2.Pos)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("No parsers", func(t *testing.T) {
|
|
||||||
assertNilParser(t, And())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMaybe(t *testing.T) {
|
func TestMaybe(t *testing.T) {
|
||||||
@ -60,8 +48,8 @@ func TestAny(t *testing.T) {
|
|||||||
t.Run("Returns longest error", func(t *testing.T) {
|
t.Run("Returns longest error", func(t *testing.T) {
|
||||||
_, p2 := runParser("hello world!", Any(
|
_, p2 := runParser("hello world!", Any(
|
||||||
"nope",
|
"nope",
|
||||||
And("hello", "world", "."),
|
Seq("hello", "world", "."),
|
||||||
And("hello", "brother"),
|
Seq("hello", "brother"),
|
||||||
))
|
))
|
||||||
require.Equal(t, "offset 11: Expected .", p2.Error.Error())
|
require.Equal(t, "offset 11: Expected .", p2.Error.Error())
|
||||||
require.Equal(t, 11, p2.Error.Pos())
|
require.Equal(t, 11, p2.Error.Pos())
|
||||||
@ -73,34 +61,30 @@ func TestAny(t *testing.T) {
|
|||||||
require.Equal(t, Node{}, node)
|
require.Equal(t, Node{}, node)
|
||||||
require.Equal(t, 0, p2.Pos)
|
require.Equal(t, 0, p2.Pos)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("No parsers", func(t *testing.T) {
|
|
||||||
assertNilParser(t, Any())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKleene(t *testing.T) {
|
func TestSome(t *testing.T) {
|
||||||
t.Run("Matches sequence with sep", func(t *testing.T) {
|
t.Run("Matches sequence with sep", func(t *testing.T) {
|
||||||
node, p2 := runParser("a,b,c,d,e,", Kleene(Chars("a-g"), ","))
|
node, p2 := runParser("a,b,c,d,e,", Some(Chars("a-g"), ","))
|
||||||
require.False(t, p2.Errored())
|
require.False(t, p2.Errored())
|
||||||
assertSequence(t, node, "a", "b", "c", "d", "e")
|
assertSequence(t, node, "a", "b", "c", "d", "e")
|
||||||
require.Equal(t, 10, p2.Pos)
|
require.Equal(t, 10, p2.Pos)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Matches sequence without sep", func(t *testing.T) {
|
t.Run("Matches sequence without sep", func(t *testing.T) {
|
||||||
node, p2 := runParser("a,b,c,d,e,", Kleene(Any(Chars("a-g"), ",")))
|
node, p2 := runParser("a,b,c,d,e,", Some(Any(Chars("a-g"), ",")))
|
||||||
assertSequence(t, node, "a", ",", "b", ",", "c", ",", "d", ",", "e", ",")
|
assertSequence(t, node, "a", ",", "b", ",", "c", ",", "d", ",", "e", ",")
|
||||||
require.Equal(t, 10, p2.Pos)
|
require.Equal(t, 10, p2.Pos)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("splits words automatically on space", func(t *testing.T) {
|
t.Run("splits words automatically on space", func(t *testing.T) {
|
||||||
node, p2 := runParser("hello world", Kleene(Chars("a-z")))
|
node, p2 := runParser("hello world", Some(Chars("a-z")))
|
||||||
assertSequence(t, node, "hello", "world")
|
assertSequence(t, node, "hello", "world")
|
||||||
require.Equal(t, "", p2.Get())
|
require.Equal(t, "", p2.Get())
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Stops on error", func(t *testing.T) {
|
t.Run("Stops on error", func(t *testing.T) {
|
||||||
node, p2 := runParser("a,b,c,d,e,", Kleene(Chars("a-c"), ","))
|
node, p2 := runParser("a,b,c,d,e,", Some(Chars("a-c"), ","))
|
||||||
assertSequence(t, node, "a", "b", "c")
|
assertSequence(t, node, "a", "b", "c")
|
||||||
require.Equal(t, 6, p2.Pos)
|
require.Equal(t, 6, p2.Pos)
|
||||||
require.Equal(t, "d,e,", p2.Get())
|
require.Equal(t, "d,e,", p2.Get())
|
||||||
@ -139,7 +123,7 @@ type htmlTag struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMap(t *testing.T) {
|
func TestMap(t *testing.T) {
|
||||||
parser := Map(And("<", Chars("a-zA-Z0-9"), ">"), func(n Node) Node {
|
parser := Map(Seq("<", Chars("a-zA-Z0-9"), ">"), func(n Node) Node {
|
||||||
return Node{Result: htmlTag{n.Child[1].Token}}
|
return Node{Result: htmlTag{n.Child[1].Token}}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -157,7 +141,7 @@ func TestMap(t *testing.T) {
|
|||||||
|
|
||||||
func TestMerge(t *testing.T) {
|
func TestMerge(t *testing.T) {
|
||||||
var bracer Parser
|
var bracer Parser
|
||||||
bracer = And("(", Maybe(&bracer), ")")
|
bracer = Seq("(", Maybe(&bracer), ")")
|
||||||
parser := Merge(bracer)
|
parser := Merge(bracer)
|
||||||
|
|
||||||
t.Run("sucess", func(t *testing.T) {
|
t.Run("sucess", func(t *testing.T) {
|
||||||
@ -172,12 +156,6 @@ func TestMerge(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertNilParser(t *testing.T, parser Parser) {
|
|
||||||
node, p2 := runParser("fff", parser)
|
|
||||||
require.Equal(t, Node{}, node)
|
|
||||||
require.Equal(t, 0, p2.Pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertSequence(t *testing.T, node Node, expected ...string) {
|
func assertSequence(t *testing.T, node Node, expected ...string) {
|
||||||
require.NotNil(t, node)
|
require.NotNil(t, node)
|
||||||
actual := []string{}
|
actual := []string{}
|
||||||
|
14
html/html.go
14
html/html.go
@ -17,13 +17,13 @@ type Tag struct {
|
|||||||
var (
|
var (
|
||||||
tag Parser
|
tag Parser
|
||||||
|
|
||||||
identifier = NoAutoWS(Merge(And(WS(), Chars("a-zA-Z", 1), Chars("a-zA-Z0-9", 0))))
|
identifier = NoAutoWS(Merge(Seq(WS(), Chars("a-zA-Z", 1), Chars("a-zA-Z0-9", 0))))
|
||||||
text = Map(NotChars("<>"), func(n Node) Node {
|
text = Map(NotChars("<>"), func(n Node) Node {
|
||||||
return Node{Result: n.Token}
|
return Node{Result: n.Token}
|
||||||
})
|
})
|
||||||
|
|
||||||
element = Any(text, &tag)
|
element = Any(text, &tag)
|
||||||
elements = Map(Kleene(element), func(n Node) Node {
|
elements = Map(Some(element), func(n Node) Node {
|
||||||
ret := []interface{}{}
|
ret := []interface{}{}
|
||||||
for _, child := range n.Child {
|
for _, child := range n.Child {
|
||||||
ret = append(ret, child.Result)
|
ret = append(ret, child.Result)
|
||||||
@ -31,8 +31,8 @@ var (
|
|||||||
return Node{Result: ret}
|
return Node{Result: ret}
|
||||||
})
|
})
|
||||||
|
|
||||||
attr = And(identifier, "=", StringLit(`"'`))
|
attr = Seq(identifier, "=", StringLit(`"'`))
|
||||||
attrs = Map(Kleene(attr), func(node Node) Node {
|
attrs = Map(Some(attr), func(node Node) Node {
|
||||||
attr := map[string]string{}
|
attr := map[string]string{}
|
||||||
|
|
||||||
for _, attrNode := range node.Child {
|
for _, attrNode := range node.Child {
|
||||||
@ -42,12 +42,12 @@ var (
|
|||||||
return Node{Result: attr}
|
return Node{Result: attr}
|
||||||
})
|
})
|
||||||
|
|
||||||
tstart = And("<", identifier, attrs, ">")
|
tstart = Seq("<", identifier, attrs, ">")
|
||||||
tend = And("</", identifier, ">")
|
tend = Seq("</", identifier, ">")
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
tag = Map(And(tstart, elements, tend), func(node Node) Node {
|
tag = Map(Seq(tstart, elements, tend), func(node Node) Node {
|
||||||
openTag := node.Child[0]
|
openTag := node.Child[0]
|
||||||
return Node{Result: Tag{
|
return Node{Result: Tag{
|
||||||
Name: openTag.Child[1].Token,
|
Name: openTag.Child[1].Token,
|
||||||
|
@ -10,9 +10,9 @@ var (
|
|||||||
_false = Bind("false", false)
|
_false = Bind("false", false)
|
||||||
_string = StringLit(`"`)
|
_string = StringLit(`"`)
|
||||||
_number = NumberLit()
|
_number = NumberLit()
|
||||||
_properties = Kleene(And(StringLit(`"`), ":", &_value), ",")
|
_properties = Some(Seq(StringLit(`"`), ":", &_value), ",")
|
||||||
|
|
||||||
_array = Map(And("[", Kleene(&_value, ","), "]"), func(n Node) Node {
|
_array = Map(Seq("[", Some(&_value, ","), "]"), func(n Node) Node {
|
||||||
ret := []interface{}{}
|
ret := []interface{}{}
|
||||||
for _, child := range n.Child[1].Child {
|
for _, child := range n.Child[1].Child {
|
||||||
ret = append(ret, child.Result)
|
ret = append(ret, child.Result)
|
||||||
@ -20,7 +20,7 @@ var (
|
|||||||
return Node{Result: ret}
|
return Node{Result: ret}
|
||||||
})
|
})
|
||||||
|
|
||||||
_object = Map(And("{", _properties, "}"), func(n Node) Node {
|
_object = Map(Seq("{", _properties, "}"), func(n Node) Node {
|
||||||
ret := map[string]interface{}{}
|
ret := map[string]interface{}{}
|
||||||
|
|
||||||
for _, prop := range n.Child[1].Child {
|
for _, prop := range n.Child[1].Child {
|
||||||
|
@ -21,12 +21,12 @@ type Parser func(*State) Node
|
|||||||
// eg, matching balanced paren:
|
// eg, matching balanced paren:
|
||||||
// ```go
|
// ```go
|
||||||
// var group Parser
|
// var group Parser
|
||||||
// group = And("(", Maybe(&group), ")")
|
// group = Seq("(", Maybe(&group), ")")
|
||||||
// ```
|
// ```
|
||||||
// vs
|
// vs
|
||||||
// ```go
|
// ```go
|
||||||
// var group ParserPtr{}
|
// var group ParserPtr{}
|
||||||
// group.P = And(Exact("("), Maybe(group.Parse), Exact(")"))
|
// group.P = Seq(Exact("("), Maybe(group.Parse), Exact(")"))
|
||||||
// ```
|
// ```
|
||||||
type Parserish interface{}
|
type Parserish interface{}
|
||||||
|
|
||||||
|
18
readme.md
18
readme.md
@ -25,12 +25,12 @@ If you build the parser with -tags debug it will instrument each parser and a ca
|
|||||||
```
|
```
|
||||||
Any() 415.7136ms 87000 calls json.go:35
|
Any() 415.7136ms 87000 calls json.go:35
|
||||||
Map() 309.6569ms 12000 calls json.go:31
|
Map() 309.6569ms 12000 calls json.go:31
|
||||||
And() 298.6519ms 12000 calls json.go:23
|
Seq() 298.6519ms 12000 calls json.go:23
|
||||||
Kleene() 290.6462ms 12000 calls json.go:13
|
Some() 290.6462ms 12000 calls json.go:13
|
||||||
And() 272.6392ms 81000 calls json.go:13
|
Seq() 272.6392ms 81000 calls json.go:13
|
||||||
And() 78.0404ms 13000 calls json.go:15
|
Seq() 78.0404ms 13000 calls json.go:15
|
||||||
Map() 78.0404ms 13000 calls json.go:21
|
Map() 78.0404ms 13000 calls json.go:21
|
||||||
Kleene() 77.0401ms 1000 calls json.go:15
|
Some() 77.0401ms 1000 calls json.go:15
|
||||||
string literal 7.5053ms 81000 calls json.go:13
|
string literal 7.5053ms 81000 calls json.go:13
|
||||||
string literal 4.5031ms 84000 calls json.go:11
|
string literal 4.5031ms 84000 calls json.go:11
|
||||||
, 4.0008ms 81000 calls json.go:13
|
, 4.0008ms 81000 calls json.go:13
|
||||||
@ -106,7 +106,7 @@ func TestAddition(t *testing.T) {
|
|||||||
|
|
||||||
var sumOp = Chars("+-", 1, 1)
|
var sumOp = Chars("+-", 1, 1)
|
||||||
|
|
||||||
sum = Map(And(number, Kleene(And(sumOp, number))), func(n Node) Node {
|
sum = Map(Seq(number, Some(And(sumOp, number))), func(n Node) Node {
|
||||||
i := n.Child[0].Result.(float64)
|
i := n.Child[0].Result.(float64)
|
||||||
|
|
||||||
for _, op := range n.Child[1].Child {
|
for _, op := range n.Child[1].Child {
|
||||||
@ -124,7 +124,7 @@ sum = Map(And(number, Kleene(And(sumOp, number))), func(n Node) Node {
|
|||||||
// and update Calc to point to the new root parser -> `result, remaining, err := ParseString(sum, input)`
|
// and update Calc to point to the new root parser -> `result, remaining, err := ParseString(sum, input)`
|
||||||
```
|
```
|
||||||
|
|
||||||
This parser will match number ([+-] number)+, then map its to be the sum. See how the Child map directly to the positions in the parsers? n is the result of the and, n.Child[0] is its first argument, n.Child[1] is the result of the Kleene parser, n.Child[1].Child[0] is the result of the first And and so fourth. Given how closely tied the parser and the Map are it is good to keep the two together.
|
This parser will match number ([+-] number)+, then map its to be the sum. See how the Child map directly to the positions in the parsers? n is the result of the and, `n.Child[0]` is its first argument, `n.Child[1]` is the result of the Some parser, `n.Child[1].Child[0]` is the result of the first And and so fourth. Given how closely tied the parser and the Map are it is good to keep the two together.
|
||||||
|
|
||||||
You can continue like this and add multiplication and parenthesis fairly easily. Eventually if you keep adding parsers you will end up with a loop, and go will give you a handy error message like:
|
You can continue like this and add multiplication and parenthesis fairly easily. Eventually if you keep adding parsers you will end up with a loop, and go will give you a handy error message like:
|
||||||
```
|
```
|
||||||
@ -132,10 +132,10 @@ typechecking loop involving value = goparsify.Any(number, groupExpr)
|
|||||||
```
|
```
|
||||||
|
|
||||||
we need to break the loop using a pointer, then set its value in init
|
we need to break the loop using a pointer, then set its value in init
|
||||||
```
|
```go
|
||||||
var (
|
var (
|
||||||
value Parser
|
value Parser
|
||||||
prod = And(&value, Kleene(And(prodOp, &value)))
|
prod = Seq(&value, Some(And(prodOp, &value)))
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
Loading…
Reference in New Issue
Block a user