Add String parser
This commit is contained in:
parent
a65a9325aa
commit
2c0c5b628f
@ -21,7 +21,7 @@ var (
|
|||||||
element = Any(text, &tag)
|
element = Any(text, &tag)
|
||||||
elements = Kleene(element)
|
elements = Kleene(element)
|
||||||
//attr := And(identifier, equal, String())
|
//attr := And(identifier, equal, String())
|
||||||
attr = And(identifier, WS, "=", WS, `"test"`)
|
attr = And(WS, identifier, WS, "=", WS, Any(String('"'), String('\'')))
|
||||||
attrs = Map(Kleene(attr, WS), func(node Node) Node {
|
attrs = Map(Kleene(attr, WS), func(node Node) Node {
|
||||||
nodes := node.([]Node)
|
nodes := node.([]Node)
|
||||||
attr := map[string]string{}
|
attr := map[string]string{}
|
||||||
|
@ -8,10 +8,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestParse(t *testing.T) {
|
func TestParse(t *testing.T) {
|
||||||
result, _, err := Parse("<body>hello <b>world</b></body>")
|
result, _, err := Parse(`<body>hello <p color="blue">world</p></body>`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, Tag{Name: "body", Attributes: map[string]string{}, Body: []Node{
|
require.Equal(t, Tag{Name: "body", Attributes: map[string]string{}, Body: []Node{
|
||||||
"hello ",
|
"hello ",
|
||||||
Tag{Name: "b", Attributes: map[string]string{}, Body: []Node{"world"}},
|
Tag{Name: "p", Attributes: map[string]string{"color": "blue"}, Body: []Node{"world"}},
|
||||||
}}, result)
|
}}, result)
|
||||||
}
|
}
|
||||||
|
34
parser.go
34
parser.go
@ -1,6 +1,7 @@
|
|||||||
package parsec
|
package parsec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
@ -185,3 +186,36 @@ func WS(p Pointer) (Node, Pointer) {
|
|||||||
_, p2 := CharRun("\t\n\v\f\r \x85\xA0")(p)
|
_, p2 := CharRun("\t\n\v\f\r \x85\xA0")(p)
|
||||||
return nil, p2
|
return nil, p2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func String(quote rune) Parser {
|
||||||
|
return func(p Pointer) (Node, Pointer) {
|
||||||
|
var r rune
|
||||||
|
var w int
|
||||||
|
r, w = utf8.DecodeRuneInString(p.input[p.pos:])
|
||||||
|
if r != quote {
|
||||||
|
return NewError(p.pos, `Expected "`), p
|
||||||
|
}
|
||||||
|
|
||||||
|
matched := w
|
||||||
|
result := &bytes.Buffer{}
|
||||||
|
|
||||||
|
for p.pos+matched < len(p.input) {
|
||||||
|
r, w = utf8.DecodeRuneInString(p.input[p.pos+matched:])
|
||||||
|
matched += w
|
||||||
|
|
||||||
|
if r == '\\' {
|
||||||
|
r, w = utf8.DecodeRuneInString(p.input[p.pos+matched:])
|
||||||
|
result.WriteRune(r)
|
||||||
|
matched += w
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if r == quote {
|
||||||
|
return result.String(), p.Advance(matched)
|
||||||
|
}
|
||||||
|
result.WriteRune(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewError(p.pos, "Unterminated string"), p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -178,3 +178,29 @@ func TestParseString(t *testing.T) {
|
|||||||
require.Equal(t, "offset 0: Expected world", err.Error())
|
require.Equal(t, "offset 0: Expected world", err.Error())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestString(t *testing.T) {
|
||||||
|
t.Run("test basic match", func(t *testing.T) {
|
||||||
|
result, p := String('"')(Pointer{`"hello"`, 0})
|
||||||
|
require.Equal(t, `hello`, result)
|
||||||
|
require.Equal(t, "", p.Get())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test non match", func(t *testing.T) {
|
||||||
|
result, p := String('"')(Pointer{`1`, 0})
|
||||||
|
require.Equal(t, NewError(0, `Expected "`), result)
|
||||||
|
require.Equal(t, `1`, p.Get())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test unterminated string", func(t *testing.T) {
|
||||||
|
result, p := String('"')(Pointer{`"hello `, 0})
|
||||||
|
require.Equal(t, NewError(0, `Unterminated string`), result)
|
||||||
|
require.Equal(t, `"hello `, p.Get())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test escaping", func(t *testing.T) {
|
||||||
|
result, p := String('"')(Pointer{`"hello \"world\""`, 0})
|
||||||
|
require.Equal(t, `hello "world"`, result)
|
||||||
|
require.Equal(t, ``, p.Get())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user