2019-10-16 18:21:20 +09:00
|
|
|
package parser_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2019-12-22 11:50:07 +09:00
|
|
|
"path/filepath"
|
2019-10-16 18:21:20 +09:00
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/goccy/go-yaml/ast"
|
|
|
|
"github.com/goccy/go-yaml/lexer"
|
|
|
|
"github.com/goccy/go-yaml/parser"
|
|
|
|
"github.com/goccy/go-yaml/printer"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestParser(t *testing.T) {
|
|
|
|
sources := []string{
|
|
|
|
"null\n",
|
|
|
|
"{}\n",
|
|
|
|
"v: hi\n",
|
|
|
|
"v: \"true\"\n",
|
|
|
|
"v: \"false\"\n",
|
|
|
|
"v: true\n",
|
|
|
|
"v: false\n",
|
|
|
|
"v: 10\n",
|
|
|
|
"v: -10\n",
|
|
|
|
"v: 42\n",
|
|
|
|
"v: 4294967296\n",
|
|
|
|
"v: \"10\"\n",
|
|
|
|
"v: 0.1\n",
|
|
|
|
"v: 0.99\n",
|
|
|
|
"v: -0.1\n",
|
|
|
|
"v: .inf\n",
|
|
|
|
"v: -.inf\n",
|
|
|
|
"v: .nan\n",
|
|
|
|
"v: null\n",
|
|
|
|
"v: \"\"\n",
|
|
|
|
"v:\n- A\n- B\n",
|
|
|
|
"a: '-'\n",
|
|
|
|
"123\n",
|
|
|
|
"hello: world\n",
|
|
|
|
"a: null\n",
|
|
|
|
"v:\n- A\n- 1\n- B:\n - 2\n - 3\n",
|
|
|
|
"a:\n b: c\n",
|
|
|
|
"a: {x: 1}\n",
|
|
|
|
"t2: 2018-01-09T10:40:47Z\nt4: 2098-01-09T10:40:47Z\n",
|
|
|
|
"a: [1, 2]\n",
|
|
|
|
"a: {b: c, d: e}\n",
|
|
|
|
"a: 3s\n",
|
|
|
|
"a: <foo>\n",
|
|
|
|
"a: \"1:1\"\n",
|
|
|
|
"a: 1.2.3.4\n",
|
|
|
|
"a: \"2015-02-24T18:19:39Z\"\n",
|
|
|
|
"a: 'b: c'\n",
|
|
|
|
"a: 'Hello #comment'\n",
|
|
|
|
"a: 100.5\n",
|
|
|
|
"a: bogus\n",
|
|
|
|
"a: \"\\0\"\n",
|
|
|
|
"b: 2\na: 1\nd: 4\nc: 3\nsub:\n e: 5\n",
|
|
|
|
" a : b \n",
|
|
|
|
"a: b # comment\nb: c\n",
|
|
|
|
"---\na: b\n",
|
|
|
|
"a: b\n...\n",
|
|
|
|
"%YAML 1.2\n---\n",
|
|
|
|
"a: !!binary gIGC\n",
|
|
|
|
"a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
|
|
|
|
"- !tag\n a: b\n c: d\n",
|
|
|
|
"v:\n- A\n- |-\n B\n C\n",
|
|
|
|
"v:\n- A\n- >-\n B\n C\n",
|
|
|
|
}
|
|
|
|
for _, src := range sources {
|
|
|
|
fmt.Printf(src)
|
2019-10-21 12:53:30 +09:00
|
|
|
tokens := lexer.Tokenize(src)
|
2019-10-16 18:21:20 +09:00
|
|
|
var printer printer.Printer
|
|
|
|
fmt.Println(printer.PrintTokens(tokens))
|
2019-11-05 17:02:55 +09:00
|
|
|
ast, err := parser.Parse(tokens, 0)
|
2019-10-16 18:21:20 +09:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("%+v", err)
|
|
|
|
}
|
|
|
|
fmt.Printf("%+v\n", ast)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestParseComplicatedDocument(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
source string
|
|
|
|
expect string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
`
|
|
|
|
american:
|
|
|
|
- Boston Red Sox
|
|
|
|
- Detroit Tigers
|
|
|
|
- New York Yankees
|
|
|
|
national:
|
|
|
|
- New York Mets
|
|
|
|
- Chicago Cubs
|
|
|
|
- Atlanta Braves
|
|
|
|
`, `
|
|
|
|
american:
|
|
|
|
- Boston Red Sox
|
|
|
|
- Detroit Tigers
|
|
|
|
- New York Yankees
|
|
|
|
national:
|
|
|
|
- New York Mets
|
|
|
|
- Chicago Cubs
|
|
|
|
- Atlanta Braves
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
b: c
|
|
|
|
d: e
|
|
|
|
f: g
|
|
|
|
h:
|
|
|
|
i: j
|
|
|
|
k:
|
|
|
|
l: m
|
|
|
|
n: o
|
|
|
|
p: q
|
|
|
|
r: s
|
|
|
|
`, `
|
|
|
|
a:
|
|
|
|
b: c
|
|
|
|
d: e
|
|
|
|
f: g
|
|
|
|
h:
|
|
|
|
i: j
|
|
|
|
k:
|
|
|
|
l: m
|
|
|
|
n: o
|
|
|
|
p: q
|
|
|
|
r: s
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
- a:
|
|
|
|
- b
|
|
|
|
- c
|
|
|
|
- d
|
|
|
|
`, `
|
|
|
|
- a:
|
|
|
|
- b
|
|
|
|
- c
|
|
|
|
- d
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
- a
|
|
|
|
- b
|
|
|
|
- c
|
|
|
|
- d
|
|
|
|
- e
|
|
|
|
- f
|
|
|
|
`, `
|
|
|
|
- a
|
|
|
|
- b
|
|
|
|
- c - d - e
|
|
|
|
- f
|
2019-12-04 23:58:06 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a: 0 - 1
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
a: 0 - 1
|
2019-10-16 18:21:20 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{`
|
|
|
|
- a:
|
|
|
|
b: c
|
|
|
|
d: e
|
|
|
|
- f:
|
|
|
|
g: h
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
- a:
|
|
|
|
b: c
|
|
|
|
d: e
|
|
|
|
- f:
|
|
|
|
g: h
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
b
|
|
|
|
c
|
|
|
|
d: e
|
|
|
|
`, `
|
|
|
|
a: b c
|
|
|
|
d: e
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a
|
|
|
|
b
|
|
|
|
c
|
|
|
|
`, `
|
|
|
|
a b c
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
- b
|
|
|
|
- c
|
|
|
|
`, `
|
|
|
|
a:
|
|
|
|
- b
|
|
|
|
- c
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
- a :
|
|
|
|
b: c
|
|
|
|
`, `
|
|
|
|
- a:
|
|
|
|
b: c
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
- a:
|
|
|
|
b
|
|
|
|
c
|
|
|
|
d
|
|
|
|
hoge: fuga
|
|
|
|
`, `
|
|
|
|
- a: b c d
|
|
|
|
hoge: fuga
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
- a # ' " # - : %
|
|
|
|
- b # " # - : % '
|
|
|
|
- c # # - : % ' "
|
|
|
|
- d # - : % ' " #
|
|
|
|
- e # : % ' " # -
|
|
|
|
- f # % ' : # - :
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
- a
|
|
|
|
- b
|
|
|
|
- c
|
|
|
|
- d
|
|
|
|
- e
|
|
|
|
- f
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
# comment
|
|
|
|
a: # comment
|
|
|
|
# comment
|
|
|
|
b: c # comment
|
|
|
|
# comment
|
|
|
|
d: e # comment
|
|
|
|
# comment
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
b: c
|
|
|
|
d: e
|
2019-11-12 19:50:58 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a: b#notcomment
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
a: b#notcomment
|
2019-10-16 18:21:20 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
anchored: &anchor foo
|
|
|
|
aliased: *anchor
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
anchored: &anchor foo
|
|
|
|
aliased: *anchor
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
---
|
|
|
|
- &CENTER { x: 1, y: 2 }
|
|
|
|
- &LEFT { x: 0, y: 2 }
|
|
|
|
- &BIG { r: 10 }
|
|
|
|
- &SMALL { r: 1 }
|
|
|
|
|
|
|
|
# All the following maps are equal:
|
|
|
|
|
|
|
|
- # Explicit keys
|
|
|
|
x: 1
|
|
|
|
y: 2
|
|
|
|
r: 10
|
|
|
|
label: center/big
|
|
|
|
|
|
|
|
- # Merge one map
|
|
|
|
<< : *CENTER
|
|
|
|
r: 10
|
|
|
|
label: center/big
|
|
|
|
|
|
|
|
- # Merge multiple maps
|
|
|
|
<< : [ *CENTER, *BIG ]
|
|
|
|
label: center/big
|
|
|
|
|
|
|
|
- # Override
|
|
|
|
<< : [ *BIG, *LEFT, *SMALL ]
|
|
|
|
x: 1
|
|
|
|
label: center/big
|
|
|
|
`,
|
|
|
|
`
|
2019-11-05 17:02:55 +09:00
|
|
|
---
|
2019-10-16 18:21:20 +09:00
|
|
|
- &CENTER {x: 1, y: 2}
|
|
|
|
- &LEFT {x: 0, y: 2}
|
|
|
|
- &BIG {r: 10}
|
|
|
|
- &SMALL {r: 1}
|
|
|
|
- x: 1
|
|
|
|
y: 2
|
|
|
|
r: 10
|
|
|
|
label: center/big
|
|
|
|
- <<: *CENTER
|
|
|
|
r: 10
|
|
|
|
label: center/big
|
|
|
|
- <<: [*CENTER, *BIG]
|
|
|
|
label: center/big
|
|
|
|
- <<: [*BIG, *LEFT, *SMALL]
|
|
|
|
x: 1
|
|
|
|
label: center/big
|
2019-10-23 20:22:14 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
- - b
|
|
|
|
- - c
|
|
|
|
- d
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
- - b
|
|
|
|
- - c
|
|
|
|
- d
|
2019-10-24 13:52:12 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
b:
|
|
|
|
c: d
|
|
|
|
e:
|
|
|
|
f: g
|
|
|
|
h: i
|
|
|
|
j: k
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
b:
|
|
|
|
c: d
|
|
|
|
e:
|
|
|
|
f: g
|
|
|
|
h: i
|
|
|
|
j: k
|
2019-11-05 17:02:55 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
---
|
|
|
|
a: 1
|
|
|
|
b: 2
|
|
|
|
...
|
|
|
|
---
|
|
|
|
c: 3
|
|
|
|
d: 4
|
|
|
|
...
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
---
|
|
|
|
a: 1
|
|
|
|
b: 2
|
|
|
|
...
|
|
|
|
---
|
|
|
|
c: 3
|
|
|
|
d: 4
|
|
|
|
...
|
2019-11-07 23:45:39 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
b: |
|
|
|
|
{
|
|
|
|
[ 1, 2 ]
|
|
|
|
}
|
|
|
|
c: d
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
b: |
|
|
|
|
{
|
|
|
|
[ 1, 2 ]
|
|
|
|
}
|
|
|
|
c: d
|
2019-11-08 16:48:54 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
|
|
|
|
|
hoge
|
|
|
|
fuga
|
|
|
|
piyo`,
|
|
|
|
`
|
|
|
|
|
|
|
|
|
hoge
|
|
|
|
fuga
|
|
|
|
piyo
|
2019-11-19 18:03:24 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a: |
|
|
|
|
bbbbbbb
|
|
|
|
|
|
|
|
|
|
|
|
ccccccc
|
|
|
|
d: eeeeeeeeeeeeeeeee
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
a: |
|
|
|
|
bbbbbbb
|
|
|
|
|
|
|
|
|
|
|
|
ccccccc
|
|
|
|
d: eeeeeeeeeeeeeeeee
|
2019-12-11 17:17:05 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a: b
|
|
|
|
c
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
a: b c
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
b: c
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
b: c
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a: b
|
|
|
|
c: d
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
a: b
|
|
|
|
c: d
|
2020-03-07 12:03:06 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
- ab - cd
|
|
|
|
- ef - gh
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
- ab - cd
|
|
|
|
- ef - gh
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
- 0 - 1
|
|
|
|
- 2 - 3
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
- 0 - 1 - 2 - 3
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a - b - c: value
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
a - b - c: value
|
2020-03-07 20:17:54 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
-
|
|
|
|
b: c
|
|
|
|
d: e
|
|
|
|
-
|
|
|
|
f: g
|
|
|
|
h: i
|
|
|
|
`,
|
|
|
|
`
|
|
|
|
a:
|
|
|
|
- b: c
|
|
|
|
d: e
|
|
|
|
- f: g
|
|
|
|
h: i
|
2019-10-16 18:21:20 +09:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
2019-10-21 12:53:30 +09:00
|
|
|
tokens := lexer.Tokenize(test.source)
|
2019-10-16 18:21:20 +09:00
|
|
|
tokens.Dump()
|
2019-11-05 17:02:55 +09:00
|
|
|
f, err := parser.Parse(tokens, 0)
|
2019-10-16 18:21:20 +09:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("%+v", err)
|
|
|
|
}
|
|
|
|
var v Visitor
|
2019-11-05 17:02:55 +09:00
|
|
|
for _, doc := range f.Docs {
|
|
|
|
ast.Walk(&v, doc.Body)
|
2019-10-16 18:21:20 +09:00
|
|
|
}
|
2019-11-05 17:02:55 +09:00
|
|
|
expect := fmt.Sprintf("\n%+v\n", f)
|
2019-10-16 18:21:20 +09:00
|
|
|
if test.expect != expect {
|
|
|
|
t.Fatalf("unexpected output: [%s] != [%s]", test.expect, expect)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-22 11:50:07 +09:00
|
|
|
func TestNewLineChar(t *testing.T) {
|
|
|
|
for _, f := range []string{
|
|
|
|
"lf.yml",
|
|
|
|
"cr.yml",
|
|
|
|
"crlf.yml",
|
|
|
|
} {
|
2019-12-22 12:08:45 +09:00
|
|
|
ast, err := parser.ParseFile(filepath.Join("testdata", f), 0)
|
2019-12-22 11:59:24 +09:00
|
|
|
if err != nil {
|
2019-12-22 11:50:07 +09:00
|
|
|
t.Fatalf("%+v", err)
|
|
|
|
}
|
2019-12-22 11:59:24 +09:00
|
|
|
actual := fmt.Sprintf("%v\n", ast)
|
|
|
|
expect := `a: "a"
|
|
|
|
b: 1
|
|
|
|
`
|
|
|
|
if expect != actual {
|
|
|
|
t.Fatal("unexpected result")
|
|
|
|
}
|
2019-12-22 11:50:07 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-23 03:21:42 +09:00
|
|
|
func TestSyntaxError(t *testing.T) {
|
|
|
|
sources := []string{
|
|
|
|
"a:\n- b\n c: d\n e: f\n g: h",
|
|
|
|
}
|
|
|
|
for _, source := range sources {
|
2019-11-05 17:02:55 +09:00
|
|
|
_, err := parser.ParseBytes([]byte(source), 0)
|
2019-10-23 03:21:42 +09:00
|
|
|
if err == nil {
|
|
|
|
t.Fatal("cannot catch syntax error")
|
|
|
|
}
|
2019-10-23 13:30:22 +09:00
|
|
|
fmt.Printf("%v\n", err)
|
2019-10-23 03:21:42 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-28 21:39:06 +09:00
|
|
|
func TestComment(t *testing.T) {
|
|
|
|
yml := `
|
|
|
|
# commentA
|
|
|
|
a: #commentB
|
|
|
|
# commentC
|
|
|
|
b: c # commentD
|
|
|
|
# commentE
|
|
|
|
d: e # commentF
|
|
|
|
# commentG
|
|
|
|
f: g # commentH
|
|
|
|
# commentI
|
|
|
|
f: g # commentJ
|
|
|
|
# commentK
|
|
|
|
`
|
|
|
|
f, err := parser.ParseBytes([]byte(yml), parser.ParseComments)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("%+v", err)
|
|
|
|
}
|
|
|
|
var v Visitor
|
|
|
|
for _, doc := range f.Docs {
|
|
|
|
ast.Walk(&v, doc.Body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-16 18:21:20 +09:00
|
|
|
type Visitor struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *Visitor) Visit(node ast.Node) ast.Visitor {
|
2019-10-31 13:06:35 +09:00
|
|
|
tk := node.GetToken()
|
|
|
|
tk.Prev = nil
|
|
|
|
tk.Next = nil
|
2020-05-28 21:39:06 +09:00
|
|
|
if comment := node.GetComment(); comment != nil {
|
|
|
|
comment.Prev = nil
|
|
|
|
comment.Next = nil
|
|
|
|
}
|
2019-10-16 18:21:20 +09:00
|
|
|
return v
|
|
|
|
}
|