summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--html/html.go2
-rw-r--r--html/html_test.go4
-rw-r--r--parser.go34
-rw-r--r--parser_test.go26
4 files changed, 63 insertions, 3 deletions
diff --git a/html/html.go b/html/html.go
index 5ceb5e9..adee935 100644
--- a/html/html.go
+++ b/html/html.go
@@ -21,7 +21,7 @@ var (
element = Any(text, &tag)
elements = Kleene(element)
//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 {
nodes := node.([]Node)
attr := map[string]string{}
diff --git a/html/html_test.go b/html/html_test.go
index 6dca6d4..defdc10 100644
--- a/html/html_test.go
+++ b/html/html_test.go
@@ -8,10 +8,10 @@ import (
)
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.Equal(t, Tag{Name: "body", Attributes: map[string]string{}, Body: []Node{
"hello ",
- Tag{Name: "b", Attributes: map[string]string{}, Body: []Node{"world"}},
+ Tag{Name: "p", Attributes: map[string]string{"color": "blue"}, Body: []Node{"world"}},
}}, result)
}
diff --git a/parser.go b/parser.go
index 3c5d752..7599bf1 100644
--- a/parser.go
+++ b/parser.go
@@ -1,6 +1,7 @@
package parsec
import (
+ "bytes"
"fmt"
"strings"
"unicode/utf8"
@@ -185,3 +186,36 @@ func WS(p Pointer) (Node, Pointer) {
_, p2 := CharRun("\t\n\v\f\r \x85\xA0")(p)
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
+ }
+}
diff --git a/parser_test.go b/parser_test.go
index a560c8c..4d60781 100644
--- a/parser_test.go
+++ b/parser_test.go
@@ -178,3 +178,29 @@ func TestParseString(t *testing.T) {
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())
+ })
+}