diff options
author | Adam Scarr <adam@vektah.net> | 2017-08-06 17:28:34 +1000 |
---|---|---|
committer | Adam Scarr <adam@vektah.net> | 2017-08-06 17:28:34 +1000 |
commit | 2c0c5b628fd0b8e7499574d379b4138630f886d7 (patch) | |
tree | 20be82a411649f8f80281c6f73977e0d797858eb | |
parent | a65a9325aaebd1499a8e523463cc023124f8536a (diff) |
Add String parser
-rw-r--r-- | html/html.go | 2 | ||||
-rw-r--r-- | html/html_test.go | 4 | ||||
-rw-r--r-- | parser.go | 34 | ||||
-rw-r--r-- | parser_test.go | 26 |
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) } @@ -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()) + }) +} |