Best Atoum code snippet using parser.parseString
parser_test.go
Source:parser_test.go
1package participle_test2import (3 "errors"4 "fmt"5 "math"6 "net"7 "reflect"8 "strconv"9 "strings"10 "testing"11 "text/scanner"12 require "github.com/alecthomas/assert/v2"13 "github.com/alecthomas/participle/v2"14 "github.com/alecthomas/participle/v2/lexer"15)16func TestProductionCapture(t *testing.T) {17 type testCapture struct {18 A string `@Test`19 }20 _, err := participle.Build[testCapture]()21 require.Error(t, err)22}23func TestTermCapture(t *testing.T) {24 type grammar struct {25 A string `@"."*`26 }27 parser := mustTestParser[grammar](t)28 expected := &grammar{"..."}29 actual, err := parser.ParseString("", "...")30 require.NoError(t, err)31 require.Equal(t, expected, actual)32}33func TestParseScalar(t *testing.T) {34 type grammar struct {35 A string `@"one"`36 }37 parser := mustTestParser[grammar](t)38 actual, err := parser.ParseString("", "one")39 require.NoError(t, err)40 require.Equal(t, &grammar{"one"}, actual)41}42func TestParseGroup(t *testing.T) {43 type grammar struct {44 A string `@("one" | "two")`45 }46 parser := mustTestParser[grammar](t)47 actual, err := parser.ParseString("", "one")48 require.NoError(t, err)49 require.Equal(t, &grammar{"one"}, actual)50 actual, err = parser.ParseString("", "two")51 require.NoError(t, err)52 require.Equal(t, &grammar{"two"}, actual)53}54func TestParseAlternative(t *testing.T) {55 type grammar struct {56 A string `@"one" |`57 B string `@"two"`58 }59 parser := mustTestParser[grammar](t)60 actual, err := parser.ParseString("", "one")61 require.NoError(t, err)62 require.Equal(t, &grammar{A: "one"}, actual)63 actual, err = parser.ParseString("", "two")64 require.NoError(t, err)65 require.Equal(t, &grammar{B: "two"}, actual)66}67func TestParseSequence(t *testing.T) {68 type grammar struct {69 A string `@"one"`70 B string `@"two"`71 C string `@"three"`72 }73 parser := mustTestParser[grammar](t)74 expected := &grammar{"one", "two", "three"}75 actual, err := parser.ParseString("", "one two three")76 require.NoError(t, err)77 require.Equal(t, expected, actual)78 expected = &grammar{}79 actual, err = parser.ParseString("", "moo")80 require.Error(t, err)81 require.Equal(t, expected, actual)82}83func TestNested(t *testing.T) {84 type nestedInner struct {85 B string `@"one"`86 C string `@"two"`87 }88 type testNested struct {89 A *nestedInner `@@`90 }91 parser := mustTestParser[testNested](t)92 expected := &testNested{A: &nestedInner{B: "one", C: "two"}}93 actual, err := parser.ParseString("", "one two")94 require.NoError(t, err)95 require.Equal(t, expected, actual)96}97func TestAccumulateNested(t *testing.T) {98 type nestedInner struct {99 B string `@"one"`100 C string `@"two"`101 }102 type testAccumulateNested struct {103 A []*nestedInner `@@+`104 }105 parser := mustTestParser[testAccumulateNested](t)106 expected := &testAccumulateNested{A: []*nestedInner{{B: "one", C: "two"}, {B: "one", C: "two"}}}107 actual, err := parser.ParseString("", "one two one two")108 require.NoError(t, err)109 require.Equal(t, expected, actual)110}111func TestRepetitionNoMatch(t *testing.T) {112 type grammar struct {113 A []string `@"."*`114 }115 parser := mustTestParser[grammar](t)116 expected := &grammar{}117 actual, err := parser.ParseString("", ``)118 require.NoError(t, err)119 require.Equal(t, expected, actual)120}121func TestRepetition(t *testing.T) {122 type grammar struct {123 A []string `@"."*`124 }125 parser := mustTestParser[grammar](t)126 expected := &grammar{A: []string{".", ".", "."}}127 actual, err := parser.ParseString("", `...`)128 require.NoError(t, err)129 require.Equal(t, expected, actual)130}131func TestRepetitionAcrossFields(t *testing.T) {132 type testRepetition struct {133 A []string `@"."*`134 B *string `(@"b" |`135 C *string ` @"c")`136 }137 parser := mustTestParser[testRepetition](t)138 b := "b"139 c := "c"140 expected := &testRepetition{141 A: []string{".", ".", "."},142 B: &b,143 }144 actual, err := parser.ParseString("", "...b")145 require.NoError(t, err)146 require.Equal(t, expected, actual)147 expected = &testRepetition{148 A: []string{".", ".", "."},149 C: &c,150 }151 actual, err = parser.ParseString("", "...c")152 require.NoError(t, err)153 require.Equal(t, expected, actual)154 expected = &testRepetition{155 B: &b,156 }157 actual, err = parser.ParseString("", "b")158 require.NoError(t, err)159 require.Equal(t, expected, actual)160}161func TestAccumulateString(t *testing.T) {162 type testAccumulateString struct {163 A string `@"."+`164 }165 parser := mustTestParser[testAccumulateString](t)166 expected := &testAccumulateString{167 A: "...",168 }169 actual, err := parser.ParseString("", "...")170 require.NoError(t, err)171 require.Equal(t, expected, actual)172}173type Group struct {174 Expression *Expression `"(" @@ ")"`175}176type LookaheadGroup struct {177 Expression *Expression `"(" "?" ("=" | "!") @@ ")"`178}179type EBNFOption struct {180 Expression *Expression `"[" @@ "]"`181}182type Repetition struct {183 Expression *Expression `"{" @@ "}"`184}185type Negation struct {186 Expression *Expression `"!" @@`187}188type Literal struct {189 Start string `@String`190}191type Range struct {192 Start string `@String`193 End string `"â¦" @String`194}195type Term struct {196 Name string `@Ident |`197 Literal *Literal `@@ |`198 Range *Range `@@ |`199 Group *Group `@@ |`200 LookaheadGroup *LookaheadGroup `@@ |`201 Option *EBNFOption `@@ |`202 Repetition *Repetition `@@ |`203 Negation *Negation `@@`204}205type Sequence struct {206 Terms []*Term `@@+`207}208type Expression struct {209 Alternatives []*Sequence `@@ ( "|" @@ )*`210}211type Production struct {212 Name string `@Ident "="`213 Expression []*Expression `@@+ "."`214}215type EBNF struct {216 Productions []*Production `@@*`217}218func TestEBNFParser(t *testing.T) {219 parser := mustTestParser[EBNF](t, participle.Unquote())220 expected := &EBNF{221 Productions: []*Production{222 {223 Name: "Production",224 Expression: []*Expression{225 {226 Alternatives: []*Sequence{227 {228 Terms: []*Term{229 {Name: "name"},230 {Literal: &Literal{Start: "="}},231 {232 Option: &EBNFOption{233 Expression: &Expression{234 Alternatives: []*Sequence{235 {236 Terms: []*Term{237 {Name: "Expression"},238 },239 },240 },241 },242 },243 },244 {Literal: &Literal{Start: "."}},245 },246 },247 },248 },249 },250 },251 {252 Name: "Expression",253 Expression: []*Expression{254 {255 Alternatives: []*Sequence{256 {257 Terms: []*Term{258 {Name: "Alternative"},259 {260 Repetition: &Repetition{261 Expression: &Expression{262 Alternatives: []*Sequence{263 {264 Terms: []*Term{265 {Literal: &Literal{Start: "|"}},266 {Name: "Alternative"},267 },268 },269 },270 },271 },272 },273 },274 },275 },276 },277 },278 },279 {280 Name: "Alternative",281 Expression: []*Expression{282 {283 Alternatives: []*Sequence{284 {285 Terms: []*Term{286 {Name: "Term"},287 {288 Repetition: &Repetition{289 Expression: &Expression{290 Alternatives: []*Sequence{291 {292 Terms: []*Term{293 {Name: "Term"},294 },295 },296 },297 },298 },299 },300 },301 },302 },303 },304 },305 },306 {307 Name: "Term",308 Expression: []*Expression{309 {310 Alternatives: []*Sequence{311 {Terms: []*Term{{Name: "name"}}},312 {313 Terms: []*Term{314 {Name: "token"},315 {316 Option: &EBNFOption{317 Expression: &Expression{318 Alternatives: []*Sequence{319 {320 Terms: []*Term{321 {Literal: &Literal{Start: "â¦"}},322 {Name: "token"},323 },324 },325 },326 },327 },328 },329 },330 },331 {Terms: []*Term{{Literal: &Literal{Start: "@@"}}}},332 {Terms: []*Term{{Name: "Group"}}},333 {Terms: []*Term{{Name: "EBNFOption"}}},334 {Terms: []*Term{{Name: "Repetition"}}},335 },336 },337 },338 },339 {340 Name: "Group",341 Expression: []*Expression{342 {343 Alternatives: []*Sequence{344 {345 Terms: []*Term{346 {Literal: &Literal{Start: "("}},347 {Name: "Expression"},348 {Literal: &Literal{Start: ")"}},349 },350 },351 },352 },353 },354 },355 {356 Name: "EBNFOption",357 Expression: []*Expression{358 {359 Alternatives: []*Sequence{360 {361 Terms: []*Term{362 {Literal: &Literal{Start: "["}},363 {Name: "Expression"},364 {Literal: &Literal{Start: "]"}},365 },366 },367 },368 },369 },370 },371 {372 Name: "Repetition",373 Expression: []*Expression{374 {375 Alternatives: []*Sequence{376 {377 Terms: []*Term{378 {Literal: &Literal{Start: "{"}},379 {Name: "Expression"},380 {Literal: &Literal{Start: "}"}},381 },382 },383 },384 },385 },386 },387 },388 }389 actual, err := parser.ParseString("", strings.TrimSpace(`390Production = name "=" [ Expression ] "." .391Expression = Alternative { "|" Alternative } .392Alternative = Term { Term } .393Term = name | token [ "â¦" token ] | "@@" | Group | EBNFOption | Repetition .394Group = "(" Expression ")" .395EBNFOption = "[" Expression "]" .396Repetition = "{" Expression "}" .397`))398 require.NoError(t, err)399 require.Equal(t, expected, actual)400}401func TestParseExpression(t *testing.T) {402 type testNestA struct {403 A string `":" @"a"*`404 }405 type testNestB struct {406 B string `";" @"b"*`407 }408 type testExpression struct {409 A *testNestA `@@ |`410 B *testNestB `@@`411 }412 parser := mustTestParser[testExpression](t)413 expected := &testExpression{414 B: &testNestB{415 B: "b",416 },417 }418 actual, err := parser.ParseString("", ";b")419 require.NoError(t, err)420 require.Equal(t, expected, actual)421}422func TestParseOptional(t *testing.T) {423 type testOptional struct {424 A string `( @"a" @"b" )?`425 B string `@"c"`426 }427 parser := mustTestParser[testOptional](t)428 expected := &testOptional{B: "c"}429 actual, err := parser.ParseString("", `c`)430 require.NoError(t, err)431 require.Equal(t, expected, actual)432}433func TestHello(t *testing.T) {434 type testHello struct {435 Hello string `@"hello"`436 To string `@String`437 }438 parser := mustTestParser[testHello](t, participle.Unquote())439 expected := &testHello{"hello", `Bobby Brown`}440 actual, err := parser.ParseString("", `hello "Bobby Brown"`)441 require.NoError(t, err)442 require.Equal(t, expected, actual)443}444func mustTestParser[G any](t *testing.T, options ...participle.Option) *participle.Parser[G] {445 t.Helper()446 parser, err := participle.Build[G](options...)447 require.NoError(t, err)448 return parser449}450func BenchmarkEBNFParser(b *testing.B) {451 parser, err := participle.Build[EBNF]()452 require.NoError(b, err)453 b.ResetTimer()454 source := strings.TrimSpace(`455Production = name "=" [ Expression ] "." .456Expression = Alternative { "|" Alternative } .457Alternative = Term { Term } .458Term = name | token [ "â¦" token ] | "@@" | Group | EBNFOption | Repetition .459Group = "(" Expression ")" .460EBNFOption = "[" Expression "]" .461Repetition = "{" Expression "}" .462`)463 for i := 0; i < b.N; i++ {464 _, _ = parser.ParseString("", source)465 }466}467func TestRepeatAcrossFields(t *testing.T) {468 type grammar struct {469 A string `( @("." ">") |`470 B string ` @("," "<") )*`471 }472 parser := mustTestParser[grammar](t)473 expected := &grammar{A: ".>.>.>.>", B: ",<,<,<"}474 actual, err := parser.ParseString("", ".>,<.>.>,<.>,<")475 require.NoError(t, err)476 require.Equal(t, expected, actual)477}478func TestPosInjection(t *testing.T) {479 type subgrammar struct {480 Pos lexer.Position481 B string `@","*`482 EndPos lexer.Position483 }484 type grammar struct {485 Pos lexer.Position486 A string `@"."*`487 B *subgrammar `@@`488 C string `@"."`489 EndPos lexer.Position490 }491 parser := mustTestParser[grammar](t)492 expected := &grammar{493 Pos: lexer.Position{494 Offset: 3,495 Line: 1,496 Column: 4,497 },498 A: "...",499 B: &subgrammar{500 B: ",,,",501 Pos: lexer.Position{502 Offset: 6,503 Line: 1,504 Column: 7,505 },506 EndPos: lexer.Position{507 Offset: 9,508 Line: 1,509 Column: 10,510 },511 },512 C: ".",513 EndPos: lexer.Position{514 Offset: 10,515 Line: 1,516 Column: 11,517 },518 }519 actual, err := parser.ParseString("", " ...,,,.")520 require.NoError(t, err)521 require.Equal(t, expected, actual)522}523type parseableCount int524func (c *parseableCount) Capture(values []string) error {525 *c += parseableCount(len(values))526 return nil527}528func TestCaptureInterface(t *testing.T) {529 type grammar struct {530 Count parseableCount `@"a"*`531 }532 parser := mustTestParser[grammar](t)533 expected := &grammar{Count: 3}534 actual, err := parser.ParseString("", "a a a")535 require.NoError(t, err)536 require.Equal(t, expected, actual)537}538type unmarshallableCount int539func (u *unmarshallableCount) UnmarshalText(text []byte) error {540 *u += unmarshallableCount(len(text))541 return nil542}543func TestTextUnmarshalerInterface(t *testing.T) {544 type grammar struct {545 Count unmarshallableCount `{ @"a" }`546 }547 parser := mustTestParser[grammar](t)548 expected := &grammar{Count: 3}549 actual, err := parser.ParseString("", "a a a")550 require.NoError(t, err)551 require.Equal(t, expected, actual)552}553func TestLiteralTypeConstraint(t *testing.T) {554 type grammar struct {555 Literal string `@"123456":String`556 }557 parser := mustTestParser[grammar](t, participle.Unquote())558 expected := &grammar{Literal: "123456"}559 actual, err := parser.ParseString("", `"123456"`)560 require.NoError(t, err)561 require.Equal(t, expected, actual)562 _, err = parser.ParseString("", `123456`)563 require.Error(t, err)564}565type nestedCapture struct {566 Tokens []string567}568func (n *nestedCapture) Capture(tokens []string) error {569 n.Tokens = tokens570 return nil571}572func TestStructCaptureInterface(t *testing.T) {573 type grammar struct {574 Capture *nestedCapture `@String`575 }576 parser, err := participle.Build[grammar](participle.Unquote())577 require.NoError(t, err)578 expected := &grammar{Capture: &nestedCapture{Tokens: []string{"hello"}}}579 actual, err := parser.ParseString("", `"hello"`)580 require.NoError(t, err)581 require.Equal(t, expected, actual)582}583type parseableStruct struct {584 Tokens []string585}586func (p *parseableStruct) Parse(lex *lexer.PeekingLexer) error {587 for {588 tok := lex.Next()589 if tok.EOF() {590 break591 }592 p.Tokens = append(p.Tokens, tok.Value)593 }594 return nil595}596func TestParseable(t *testing.T) {597 type grammar struct {598 Inner *parseableStruct `@@`599 }600 parser, err := participle.Build[grammar](participle.Unquote())601 require.NoError(t, err)602 expected := &grammar{Inner: &parseableStruct{Tokens: []string{"hello", "123", "world"}}}603 actual, err := parser.ParseString("", `hello 123 "world"`)604 require.NoError(t, err)605 require.Equal(t, expected, actual)606}607func TestStringConcat(t *testing.T) {608 type grammar struct {609 Field string `@"."+`610 }611 parser, err := participle.Build[grammar]()612 require.NoError(t, err)613 expected := &grammar{"...."}614 actual, err := parser.ParseString("", `. . . .`)615 require.NoError(t, err)616 require.Equal(t, expected, actual)617}618func TestParseIntSlice(t *testing.T) {619 type grammar struct {620 Field []int `@Int+`621 }622 parser := mustTestParser[grammar](t)623 expected := &grammar{[]int{1, 2, 3, 4}}624 actual, err := parser.ParseString("", `1 2 3 4`)625 require.NoError(t, err)626 require.Equal(t, expected, actual)627}628func TestEmptyStructErrorsNotPanicsIssue21(t *testing.T) {629 type grammar struct {630 Foo struct{} `@@`631 }632 _, err := participle.Build[grammar]()633 require.Error(t, err)634}635func TestMultipleTokensIntoScalar(t *testing.T) {636 type grammar struct {637 Field int `@("-" Int)`638 }639 p, err := participle.Build[grammar]()640 require.NoError(t, err)641 actual, err := p.ParseString("", `- 10`)642 require.NoError(t, err)643 require.Equal(t, -10, actual.Field)644}645type posMixin struct {646 Pos lexer.Position647}648func TestMixinPosIsPopulated(t *testing.T) {649 type grammar struct {650 posMixin651 Int int `@Int`652 }653 p := mustTestParser[grammar](t)654 actual, err := p.ParseString("", "10")655 require.NoError(t, err)656 require.Equal(t, 10, actual.Int)657 require.Equal(t, 1, actual.Pos.Column)658 require.Equal(t, 1, actual.Pos.Line)659}660type testParserMixin struct {661 A string `@Ident`662 B string `@Ident`663}664func TestMixinFieldsAreParsed(t *testing.T) {665 type grammar struct {666 testParserMixin667 C string `@Ident`668 }669 p := mustTestParser[grammar](t)670 actual, err := p.ParseString("", "one two three")671 require.NoError(t, err)672 require.Equal(t, "one", actual.A)673 require.Equal(t, "two", actual.B)674 require.Equal(t, "three", actual.C)675}676func TestNestedOptional(t *testing.T) {677 type grammar struct {678 Args []string `"(" [ @Ident ( "," @Ident )* ] ")"`679 }680 p := mustTestParser[grammar](t)681 _, err := p.ParseString("", `()`)682 require.NoError(t, err)683 _, err = p.ParseString("", `(a)`)684 require.NoError(t, err)685 _, err = p.ParseString("", `(a, b, c)`)686 require.NoError(t, err)687 _, err = p.ParseString("", `(1)`)688 require.Error(t, err)689}690func TestInvalidNumbers(t *testing.T) {691 type grammar struct {692 Int8 int8 ` "int8" @Int`693 Int16 int16 `| "int16" @Int`694 Int32 int32 `| "int32" @Int`695 Int64 int64 `| "int64" @Int`696 Uint8 uint8 `| "uint8" @Int`697 Uint16 uint16 `| "uint16" @Int`698 Uint32 uint32 `| "uint32" @Int`699 Uint64 uint64 `| "uint64" @Int`700 Float32 float32 `| "float32" @Float`701 Float64 float64 `| "float64" @Float`702 }703 p := mustTestParser[grammar](t)704 tests := []struct {705 name string706 input string707 expected *grammar708 err bool709 }{710 {name: "ValidInt8", input: "int8 127", expected: &grammar{Int8: 127}},711 {name: "InvalidInt8", input: "int8 129", err: true},712 {name: "ValidInt16", input: "int16 32767", expected: &grammar{Int16: 32767}},713 {name: "InvalidInt16", input: "int16 32768", err: true},714 {name: "ValidInt32", input: fmt.Sprintf("int32 %d", math.MaxInt32), expected: &grammar{Int32: math.MaxInt32}},715 {name: "InvalidInt32", input: fmt.Sprintf("int32 %d", int64(math.MaxInt32+1)), err: true},716 {name: "ValidInt64", input: fmt.Sprintf("int64 %d", int64(math.MaxInt64)), expected: &grammar{Int64: math.MaxInt64}},717 {name: "InvalidInt64", input: "int64 9223372036854775808", err: true},718 {name: "ValidFloat64", input: "float64 1234.5", expected: &grammar{Float64: 1234.5}},719 {name: "InvalidFloat64", input: "float64 asdf", err: true},720 }721 for _, test := range tests {722 // nolint: scopelint723 t.Run(test.name, func(t *testing.T) {724 actual, err := p.ParseString("", test.input)725 if test.err {726 require.Error(t, err, fmt.Sprintf("%#v", actual))727 } else {728 require.NoError(t, err)729 require.Equal(t, test.expected, actual)730 }731 })732 }733}734// We'd like this to work, but it can wait.735func TestPartialAST(t *testing.T) {736 type grammar struct {737 Succeed string `@Ident`738 Fail string `@"foo"`739 }740 p := mustTestParser[grammar](t)741 actual, err := p.ParseString("", `foo bar`)742 require.Error(t, err)743 expected := &grammar{Succeed: "foo"}744 require.Equal(t, expected, actual)745}746func TestCaseInsensitive(t *testing.T) {747 type grammar struct {748 Select string `"select":Keyword @Ident`749 }750 // lex := lexer.MustStateful(lexer.Regexp(751 // `(?i)(?P<Keyword>SELECT)` +752 // `|(?P<Ident>\w+)` +753 // `|(\s+)`,754 // ))755 lex := lexer.MustSimple([]lexer.SimpleRule{756 {"Keyword", `(?i)SELECT`},757 {"Ident", `\w+`},758 {"whitespace", `\s+`},759 })760 p := mustTestParser[grammar](t, participle.Lexer(lex), participle.CaseInsensitive("Keyword"))761 actual, err := p.ParseString("", `SELECT foo`)762 expected := &grammar{"foo"}763 require.NoError(t, err)764 require.Equal(t, expected, actual)765 actual, err = p.ParseString("", `select foo`)766 require.NoError(t, err)767 require.Equal(t, expected, actual)768}769func TestTokenAfterRepeatErrors(t *testing.T) {770 type grammar struct {771 Text string `@Ident* "foo"`772 }773 p := mustTestParser[grammar](t)774 _, err := p.ParseString("", ``)775 require.Error(t, err)776}777func TestEOFAfterRepeat(t *testing.T) {778 type grammar struct {779 Text string `@Ident*`780 }781 p := mustTestParser[grammar](t)782 _, err := p.ParseString("", ``)783 require.NoError(t, err)784}785func TestTrailing(t *testing.T) {786 type grammar struct {787 Text string `@Ident`788 }789 p := mustTestParser[grammar](t)790 _, err := p.ParseString("", `foo bar`)791 require.Error(t, err)792}793type modifierTest[G any] struct {794 name string795 input string796 expected string797 fail bool798}799func (test modifierTest[G]) test(t *testing.T) {800 t.Helper()801 t.Run(test.name, func(t *testing.T) {802 p := mustTestParser[G](t)803 grammar, err := p.ParseString("", test.input)804 if test.fail {805 require.Error(t, err)806 } else {807 require.NoError(t, err)808 actual := reflect.ValueOf(grammar).Elem().FieldByName("A").String()809 require.Equal(t, test.expected, actual)810 }811 })812}813func TestModifiers(t *testing.T) {814 type nonEmptyGrammar struct {815 A string `@( ("x"? "y"? "z"?)! "b" )`816 }817 tests := []interface{ test(t *testing.T) }{818 modifierTest[nonEmptyGrammar]{name: "NonMatchingOptionalNonEmpty",819 input: "b",820 fail: true,821 },822 modifierTest[nonEmptyGrammar]{name: "NonEmptyMatch",823 input: "x b",824 expected: "xb",825 },826 modifierTest[nonEmptyGrammar]{name: "NonEmptyMatchAll",827 input: "x y z b",828 expected: "xyzb",829 },830 modifierTest[nonEmptyGrammar]{name: "NonEmptyMatchSome",831 input: "x z b",832 expected: "xzb",833 },834 modifierTest[struct {835 A string `@( "a"? "b" )`836 }]{name: "MatchingOptional",837 input: "a b",838 expected: "ab",839 },840 modifierTest[struct {841 A string `@( "a"? "b" )`842 }]{name: "NonMatchingOptionalIsSkipped",843 input: "b",844 expected: "b",845 },846 modifierTest[struct {847 A string `@( "a"+ )`848 }]{name: "MatchingOneOrMore",849 input: "a a a a a",850 expected: "aaaaa",851 },852 modifierTest[struct {853 A string `@( "a"+ )`854 }]{name: "NonMatchingOneOrMore",855 input: "",856 fail: true,857 },858 modifierTest[struct {859 A string `@( "a"* )`860 }]{name: "MatchingZeroOrMore",861 input: "aaaaaaa",862 fail: true,863 },864 modifierTest[struct {865 A string `@( "a"* )`866 }]{name: "NonMatchingZeroOrMore",867 input: "",868 },869 }870 for _, test := range tests {871 test.test(t)872 }873}874func TestNonEmptyMatchWithOptionalGroup(t *testing.T) {875 type term struct {876 Minus bool `@'-'?`877 Name string `@Ident`878 }879 type grammar struct {880 Start term `parser:"'[' (@@?"`881 End term `parser:" (':' @@)?)! ']'"`882 }883 p := mustTestParser[grammar](t)884 result, err := p.ParseString("", "[-x]")885 require.NoError(t, err)886 require.Equal(t, &grammar{Start: term{Minus: true, Name: "x"}}, result)887 result, err = p.ParseString("", "[a:-b]")888 require.NoError(t, err)889 require.Equal(t, &grammar{Start: term{Name: "a"}, End: term{Minus: true, Name: "b"}}, result)890 result, err = p.ParseString("", "[:end]")891 require.NoError(t, err)892 require.Equal(t, &grammar{End: term{Name: "end"}}, result)893 _, err = p.ParseString("", "[]")894 require.EqualError(t, err, `1:2: sub-expression (Term? (":" Term)?)! cannot be empty`)895}896func TestIssue60(t *testing.T) {897 type grammar struct {898 A string `@("one" | | "two")`899 }900 _, err := participle.Build[grammar]()901 require.Error(t, err)902}903type Issue62Bar struct {904 A int905}906func (x *Issue62Bar) Parse(lex *lexer.PeekingLexer) error {907 token := lex.Next()908 var err error909 x.A, err = strconv.Atoi(token.Value)910 return err911}912type Issue62Foo struct {913 Bars []Issue62Bar `parser:"@@+"`914}915func TestIssue62(t *testing.T) {916 _, err := participle.Build[Issue62Foo]()917 require.NoError(t, err)918}919// nolint: structcheck, unused920func TestIssue71(t *testing.T) {921 type Sub struct {922 name string `@Ident`923 }924 type grammar struct {925 pattern *Sub `@@`926 }927 _, err := participle.Build[grammar]()928 require.Error(t, err)929}930func TestAllowTrailing(t *testing.T) {931 type G struct {932 Name string `@Ident`933 }934 p, err := participle.Build[G]()935 require.NoError(t, err)936 _, err = p.ParseString("", `hello world`)937 require.Error(t, err)938 g, err := p.ParseString("", `hello world`, participle.AllowTrailing(true))939 require.NoError(t, err)940 require.Equal(t, &G{"hello"}, g)941}942func TestDisjunctionErrorReporting(t *testing.T) {943 type statement struct {944 Add bool ` @"add"`945 Remove bool `| @"remove"`946 }947 type grammar struct {948 Statements []*statement `"{" ( @@ )* "}"`949 }950 p := mustTestParser[grammar](t)951 _, err := p.ParseString("", `{ add foo }`)952 // TODO: This should produce a more useful error. This is returned by sequence.Parse().953 require.EqualError(t, err, `1:7: unexpected token "foo" (expected "}")`)954}955func TestCustomInt(t *testing.T) {956 type MyInt int957 type G struct {958 Value MyInt `@Int`959 }960 p, err := participle.Build[G]()961 require.NoError(t, err)962 g, err := p.ParseString("", `42`)963 require.NoError(t, err)964 require.Equal(t, &G{42}, g)965}966func TestBoolIfSet(t *testing.T) {967 type G struct {968 Value bool `@"true"?`969 }970 p, err := participle.Build[G]()971 require.NoError(t, err)972 g, err := p.ParseString("", `true`)973 require.NoError(t, err)974 require.Equal(t, &G{true}, g)975 g, err = p.ParseString("", ``)976 require.NoError(t, err)977 require.Equal(t, &G{false}, g)978}979func TestCustomBoolIfSet(t *testing.T) {980 type MyBool bool981 type G struct {982 Value MyBool `@"true"?`983 }984 p, err := participle.Build[G]()985 require.NoError(t, err)986 g, err := p.ParseString("", `true`)987 require.NoError(t, err)988 require.Equal(t, &G{true}, g)989 g, err = p.ParseString("", ``)990 require.NoError(t, err)991 require.Equal(t, &G{false}, g)992}993func TestPointerToList(t *testing.T) {994 type grammar struct {995 List *[]string `@Ident*`996 }997 p := mustTestParser[grammar](t)998 ast, err := p.ParseString("", `foo bar`)999 require.NoError(t, err)1000 l := []string{"foo", "bar"}1001 require.Equal(t, &grammar{List: &l}, ast)1002}1003// I'm not sure if this is a problem that should be solved like this.1004// func TestMatchHydratesNullFields(t *testing.T) {1005// type grammar struct {1006// List []string `"{" @Ident* "}"`1007// }1008// p := mustTestParser[grammar](t)1009// ast := &grammar{}1010// err := p.ParseString(`{}`, ast)1011// require.NoError(t, err)1012// require.NotNil(t, ast.List)1013// }1014func TestNegation(t *testing.T) {1015 type grammar struct {1016 EverythingUntilSemicolon *[]string `@!';'* @';'`1017 }1018 p := mustTestParser[grammar](t)1019 ast, err := p.ParseString("", `hello world ;`)1020 require.NoError(t, err)1021 require.Equal(t, &[]string{"hello", "world", ";"}, ast.EverythingUntilSemicolon)1022 _, err = p.ParseString("", `hello world`)1023 require.Error(t, err)1024}1025func TestNegationWithPattern(t *testing.T) {1026 type grammar struct {1027 EverythingMoreComplex *[]string `@!(';' String)* @';' @String`1028 }1029 p := mustTestParser[grammar](t, participle.Unquote())1030 // j, err := json.MarshalIndent(p.root, "", " ")1031 // log.Print(j)1032 // log.Print(ebnf(p.root))1033 ast, err := p.ParseString("", `hello world ; "some-str"`)1034 require.NoError(t, err)1035 require.Equal(t, &[]string{"hello", "world", ";", `some-str`}, ast.EverythingMoreComplex)1036 ast, err = p.ParseString("", `hello ; world ; "hey"`)1037 require.NoError(t, err)1038 require.Equal(t, &[]string{"hello", ";", "world", ";", `hey`}, ast.EverythingMoreComplex)1039 _, err = p.ParseString("", `hello ; world ;`)1040 require.Error(t, err)1041}1042func TestNegationWithDisjunction(t *testing.T) {1043 type grammar struct {1044 EverythingMoreComplex *[]string `@!(';' | ',')* @(';' | ',')`1045 }1046 // Note: we need more lookahead since (';' String) needs some before failing to match1047 p := mustTestParser[grammar](t)1048 ast, err := p.ParseString("", `hello world ;`)1049 require.NoError(t, err)1050 require.Equal(t, &[]string{"hello", "world", ";"}, ast.EverythingMoreComplex)1051 ast, err = p.ParseString("", `hello world , `)1052 require.NoError(t, err)1053 require.Equal(t, &[]string{"hello", "world", ","}, ast.EverythingMoreComplex)1054}1055func TestLookaheadGroup_Positive_SingleToken(t *testing.T) {1056 type val struct {1057 Str string ` @String`1058 Int int `| @Int`1059 }1060 type op struct {1061 Op string `@('+' | '*' (?= @Int))`1062 Operand val `@@`1063 }1064 type sum struct {1065 Left val `@@`1066 Ops []op `@@*`1067 }1068 p := mustTestParser[sum](t)1069 ast, err := p.ParseString("", `"x" + "y" + 4`)1070 require.NoError(t, err)1071 require.Equal(t, &sum{Left: val{Str: `"x"`}, Ops: []op{{"+", val{Str: `"y"`}}, {"+", val{Int: 4}}}}, ast)1072 ast, err = p.ParseString("", `"a" * 4 + "b"`)1073 require.NoError(t, err)1074 require.Equal(t, &sum{Left: val{Str: `"a"`}, Ops: []op{{"*", val{Int: 4}}, {"+", val{Str: `"b"`}}}}, ast)1075 ast, err = p.ParseString("", `1 * 2 * 3`)1076 require.NoError(t, err)1077 require.Equal(t, &sum{Left: val{Int: 1}, Ops: []op{{"*", val{Int: 2}}, {"*", val{Int: 3}}}}, ast)1078 _, err = p.ParseString("", `"a" * "x" + "b"`)1079 require.EqualError(t, err, `1:7: unexpected '"x"'`)1080 _, err = p.ParseString("", `4 * 2 + 0 * "b"`)1081 require.EqualError(t, err, `1:13: unexpected '"b"'`)1082}1083func TestLookaheadGroup_Negative_SingleToken(t *testing.T) {1084 type variable struct {1085 Name string `@Ident`1086 }1087 type grammar struct {1088 Identifiers []variable `((?! 'except'|'end') @@)*`1089 Except *variable `('except' @@)? 'end'`1090 }1091 p := mustTestParser[grammar](t)1092 ast, err := p.ParseString("", `one two three exception end`)1093 require.NoError(t, err)1094 require.Equal(t, []variable{{"one"}, {"two"}, {"three"}, {"exception"}}, ast.Identifiers)1095 require.Zero(t, ast.Except)1096 ast, err = p.ParseString("", `anything except this end`)1097 require.NoError(t, err)1098 require.Equal(t, []variable{{"anything"}}, ast.Identifiers)1099 require.Equal(t, &variable{"this"}, ast.Except)1100 ast, err = p.ParseString("", `except the end`)1101 require.NoError(t, err)1102 require.Zero(t, ast.Identifiers)1103 require.Equal(t, &variable{"the"}, ast.Except)1104 _, err = p.ParseString("", `no ending`)1105 require.EqualError(t, err, `1:10: unexpected token "<EOF>" (expected "end")`)1106 _, err = p.ParseString("", `no end in sight`)1107 require.EqualError(t, err, `1:8: unexpected token "in"`)1108}1109func TestLookaheadGroup_Negative_MultipleTokens(t *testing.T) {1110 type grammar struct {1111 Parts []string `((?! '.' '.' '.') @(Ident | '.'))*`1112 }1113 p := mustTestParser[grammar](t)1114 ast, err := p.ParseString("", `x.y.z.`)1115 require.NoError(t, err)1116 require.Equal(t, []string{"x", ".", "y", ".", "z", "."}, ast.Parts)1117 ast, err = p.ParseString("", `..x..`)1118 require.NoError(t, err)1119 require.Equal(t, []string{".", ".", "x", ".", "."}, ast.Parts)1120 ast, err = p.ParseString("", `two.. are fine`)1121 require.NoError(t, err)1122 require.Equal(t, []string{"two", ".", ".", "are", "fine"}, ast.Parts)1123 _, err = p.ParseString("", `but this... is just wrong`)1124 require.EqualError(t, err, `1:9: unexpected token "."`)1125}1126func TestASTTokens(t *testing.T) {1127 type subject struct {1128 Tokens []lexer.Token1129 Word string `@Ident`1130 }1131 type hello struct {1132 Tokens []lexer.Token1133 Subject subject `"hello" @@`1134 }1135 p := mustTestParser[hello](t,1136 participle.Elide("Whitespace"),1137 participle.Lexer(lexer.MustSimple([]lexer.SimpleRule{1138 {"Ident", `\w+`},1139 {"Whitespace", `\s+`},1140 })))1141 actual, err := p.ParseString("", "hello world")1142 require.NoError(t, err)1143 tokens := []lexer.Token{1144 {-2, "hello", lexer.Position{Line: 1, Column: 1}},1145 {-3, " ", lexer.Position{Offset: 5, Line: 1, Column: 6}},1146 {-2, "world", lexer.Position{Offset: 6, Line: 1, Column: 7}},1147 }1148 expected := &hello{1149 Tokens: tokens,1150 Subject: subject{1151 Tokens: tokens[1:],1152 Word: "world",1153 },1154 }1155 require.Equal(t, expected, actual)1156}1157func TestCaptureIntoToken(t *testing.T) {1158 type ast struct {1159 Head lexer.Token `@Ident`1160 Tail []lexer.Token `@(Ident*)`1161 }1162 p := mustTestParser[ast](t)1163 actual, err := p.ParseString("", "hello waz baz")1164 require.NoError(t, err)1165 expected := &ast{1166 Head: lexer.Token{-2, "hello", lexer.Position{Line: 1, Column: 1}},1167 Tail: []lexer.Token{1168 {-2, "waz", lexer.Position{Offset: 6, Line: 1, Column: 7}},1169 {-2, "baz", lexer.Position{Offset: 10, Line: 1, Column: 11}},1170 },1171 }1172 require.Equal(t, expected, actual)1173}1174func TestEndPos(t *testing.T) {1175 type Ident struct {1176 Pos lexer.Position1177 EndPos lexer.Position1178 Text string `parser:"@Ident"`1179 }1180 type AST struct {1181 First *Ident `parser:"@@"`1182 Second *Ident `parser:"@@"`1183 }1184 var (1185 Lexer = lexer.Must(lexer.New(lexer.Rules{1186 "Root": {1187 {"Ident", `[\w:]+`, nil},1188 {"Whitespace", `[\r\t ]+`, nil},1189 },1190 }))1191 Parser = participle.MustBuild[AST](1192 participle.Lexer(Lexer),1193 participle.Elide("Whitespace"),1194 )1195 )1196 mod, err := Parser.Parse("", strings.NewReader("foo bar"))1197 require.NoError(t, err)1198 require.Equal(t, 0, mod.First.Pos.Offset)1199 require.Equal(t, 3, mod.First.EndPos.Offset)1200}1201func TestBug(t *testing.T) {1202 type A struct {1203 Shared string `parser:"@'1'"`1204 Diff string `parser:"@A"`1205 }1206 type B struct {1207 Shared string `parser:"@'1'"`1208 Diff string `parser:"@B"`1209 }1210 type AST struct {1211 Branch string `parser:"@'branch'"`1212 A *A `parser:"( @@"`1213 B *B `parser:"| @@ )"`1214 }1215 var (1216 lexer = lexer.Must(lexer.New(lexer.Rules{1217 "Root": {1218 {"A", `@`, nil},1219 {"B", `!`, nil},1220 {"Ident", `[\w:]+`, nil},1221 {"Whitespace", `[\r\t ]+`, nil},1222 },1223 }))1224 parser = participle.MustBuild[AST](1225 participle.Lexer(lexer),1226 participle.Elide("Whitespace"),1227 )1228 )1229 expected := &AST{1230 Branch: "branch",1231 B: &B{1232 Shared: "1",1233 Diff: "!",1234 },1235 }1236 actual, err := parser.Parse("name", strings.NewReader(`branch 1!`))1237 require.NoError(t, err)1238 require.Equal(t, expected, actual)1239}1240type sliceCapture string1241func (c *sliceCapture) Capture(values []string) error {1242 *c = sliceCapture(strings.ToUpper(values[0]))1243 return nil1244}1245func TestCaptureOnSliceElements(t *testing.T) { // nolint:dupl1246 type capture struct {1247 Single *sliceCapture `@Capture`1248 Slice []sliceCapture `@Capture @Capture`1249 SlicePtr []*sliceCapture `@Capture @Capture`1250 }1251 parser := participle.MustBuild[capture]([]participle.Option{1252 participle.Lexer(lexer.MustSimple([]lexer.SimpleRule{1253 {Name: "Capture", Pattern: `[a-z]{3}`},1254 {Name: "Whitespace", Pattern: `[\s|\n]+`},1255 })),1256 participle.Elide("Whitespace"),1257 }...)1258 captured, err := parser.ParseString("capture_slice", `abc def ijk lmn opq`)1259 require.NoError(t, err)1260 expectedSingle := sliceCapture("ABC")1261 expectedSlicePtr1 := sliceCapture("LMN")1262 expectedSlicePtr2 := sliceCapture("OPQ")1263 expected := &capture{1264 Single: &expectedSingle,1265 Slice: []sliceCapture{"DEF", "IJK"},1266 SlicePtr: []*sliceCapture{&expectedSlicePtr1, &expectedSlicePtr2},1267 }1268 require.Equal(t, expected, captured)1269}1270type sliceParse string1271func (s *sliceParse) Parse(lex *lexer.PeekingLexer) error {1272 token := lex.Peek()1273 if len(token.Value) != 3 {1274 return participle.NextMatch1275 }1276 lex.Next()1277 *s = sliceParse(strings.Repeat(token.Value, 2))1278 return nil1279}1280func TestParseOnSliceElements(t *testing.T) { // nolint:dupl1281 type parse struct {1282 Single *sliceParse `@@`1283 Slice []sliceParse `@@+`1284 }1285 parser := participle.MustBuild[parse]([]participle.Option{1286 participle.Lexer(lexer.MustSimple([]lexer.SimpleRule{1287 {Name: "Element", Pattern: `[a-z]{3}`},1288 {Name: "Whitespace", Pattern: `[\s|\n]+`},1289 })),1290 participle.Elide("Whitespace"),1291 }...)1292 parsed, err := parser.ParseString("parse_slice", `abc def ijk`)1293 require.NoError(t, err)1294 expectedSingle := sliceParse("abcabc")1295 expected := &parse{1296 Single: &expectedSingle,1297 Slice: []sliceParse{"defdef", "ijkijk"},1298 }1299 require.Equal(t, expected, parsed)1300}1301func TestUnmarshalNetIP(t *testing.T) {1302 type grammar struct {1303 IP net.IP `@IP`1304 }1305 parser := mustTestParser[grammar](t, participle.Lexer(lexer.MustSimple([]lexer.SimpleRule{1306 {"IP", `[\d.]+`},1307 })))1308 ast, err := parser.ParseString("", "10.2.3.4")1309 require.NoError(t, err)1310 require.Equal(t, "10.2.3.4", ast.IP.String())1311}1312type Address net.IP1313func (a *Address) Capture(values []string) error {1314 fmt.Println("does not run at all")1315 *a = Address(net.ParseIP(values[0]))1316 return nil1317}1318func TestCaptureIP(t *testing.T) {1319 type grammar struct {1320 IP Address `@IP`1321 }1322 parser := mustTestParser[grammar](t, participle.Lexer(lexer.MustSimple([]lexer.SimpleRule{1323 {"IP", `[\d.]+`},1324 })))1325 ast, err := parser.ParseString("", "10.2.3.4")1326 require.NoError(t, err)1327 require.Equal(t, "10.2.3.4", (net.IP)(ast.IP).String())1328}1329func BenchmarkIssue143(b *testing.B) {1330 type Disjunction struct {1331 Long1 bool `parser:" '<' '1' ' ' 'l' 'o' 'n' 'g' ' ' 'r' 'u' 'l' 'e' ' ' 't' 'o' ' ' 'f' 'o' 'r' 'm' 'a' 't' '>'"`1332 Long2 bool `parser:"| '<' '2' ' ' 'l' 'o' 'n' 'g' ' ' 'r' 'u' 'l' 'e' ' ' 't' 'o' ' ' 'f' 'o' 'r' 'm' 'a' 't' '>'"`1333 Long3 bool `parser:"| '<' '3' ' ' 'l' 'o' 'n' 'g' ' ' 'r' 'u' 'l' 'e' ' ' 't' 'o' ' ' 'f' 'o' 'r' 'm' 'a' 't' '>'"`1334 Long4 bool `parser:"| '<' '4' ' ' 'l' 'o' 'n' 'g' ' ' 'r' 'u' 'l' 'e' ' ' 't' 'o' ' ' 'f' 'o' 'r' 'm' 'a' 't' '>'"`1335 Real bool `parser:"| '<' 'x' '>'"`1336 }1337 type Disjunctions struct {1338 List []Disjunction `parser:"@@*"`1339 }1340 var disjunctionParser = participle.MustBuild[Disjunctions]()1341 input := "<x> <x> <x> <x> <x> <x> <x> <x> <x> <x> <x> <x> <x> <x> <x> <x> <x> <x> <x> <x>"1342 b.ResetTimer()1343 b.ReportAllocs()1344 for i := 0; i < b.N; i++ {1345 if _, err := disjunctionParser.ParseString("", input); err != nil {1346 panic(err)1347 }1348 }1349}1350type Boxes struct {1351 Pos lexer.Position1352 Boxes Box `@Ident`1353}1354type Box struct {1355 Pos lexer.Position1356 Val string `@Ident`1357}1358func (b *Box) Capture(values []string) error {1359 b.Val = values[0]1360 return nil1361}1362func TestBoxedCapture(t *testing.T) {1363 lex := lexer.MustSimple([]lexer.SimpleRule{1364 {"Ident", `[a-zA-Z](\w|\.|/|:|-)*`},1365 {"whitespace", `\s+`},1366 })1367 parser := participle.MustBuild[Boxes](1368 participle.Lexer(lex),1369 participle.UseLookahead(2),1370 )1371 if _, err := parser.ParseString("test", "abc::cdef.abc"); err != nil {1372 t.Fatal(err)1373 }1374}1375func TestMatchEOF(t *testing.T) {1376 type testMatchNewlineOrEOF struct {1377 Text []string `@Ident+ ("\n" | EOF)`1378 }1379 p := mustTestParser[testMatchNewlineOrEOF](t)1380 _, err := p.ParseString("", "hell world")1381 require.NoError(t, err)1382 _, err = p.ParseString("", "hell world\n")1383 require.NoError(t, err)1384}1385func TestParseExplicitElidedIdent(t *testing.T) { // nolint1386 lex := lexer.MustSimple([]lexer.SimpleRule{1387 {"Ident", `[a-zA-Z](\w|\.|/|:|-)*`},1388 {"Comment", `/\*[^*]*\*/`},1389 {"whitespace", `\s+`},1390 })1391 type grammar struct {1392 Comment string `@Comment?`1393 Ident string `@Ident`1394 }1395 p := mustTestParser[grammar](t, participle.Lexer(lex), participle.Elide("Comment"))1396 actual, err := p.ParseString("", `hello`)1397 require.NoError(t, err)1398 require.Equal(t, &grammar{Ident: "hello"}, actual)1399 actual, err = p.ParseString("", `/* Comment */ hello`)1400 require.NoError(t, err)1401 require.Equal(t, &grammar{Comment: `/* Comment */`, Ident: "hello"}, actual)1402}1403func TestParseExplicitElidedTypedLiteral(t *testing.T) { // nolint1404 lex := lexer.MustSimple([]lexer.SimpleRule{1405 {"Ident", `[a-zA-Z](\w|\.|/|:|-)*`},1406 {"Comment", `/\*[^*]*\*/`},1407 {"whitespace", `\s+`},1408 })1409 type grammar struct {1410 Comment string `@"/* Comment */":Comment?`1411 Ident string `@Ident`1412 }1413 p := mustTestParser[grammar](t, participle.Lexer(lex), participle.Elide("Comment"))1414 actual, err := p.ParseString("", `hello`)1415 require.NoError(t, err)1416 require.Equal(t, &grammar{Ident: "hello"}, actual)1417 actual, err = p.ParseString("", `/* Comment */ hello`)1418 require.NoError(t, err)1419 require.Equal(t, &grammar{Comment: `/* Comment */`, Ident: "hello"}, actual)1420}1421func TestEmptySequenceMatches(t *testing.T) {1422 lex := lexer.MustSimple([]lexer.SimpleRule{1423 {"Ident", `[a-zA-Z](\w|\.|/|:|-)*`},1424 {"Comment", `/\*[^*]*\*/`},1425 {"Whitespace", `\s+`},1426 })1427 type grammar struct {1428 Ident []string `@Ident*`1429 Comments []string `@Comment*`1430 }1431 p := mustTestParser[grammar](t, participle.Lexer(lex), participle.Elide("Whitespace"))1432 expected := &grammar{}1433 actual, err := p.ParseString("", "")1434 require.NoError(t, err)1435 require.Equal(t, expected, actual)1436}1437type RootParseableFail struct{}1438func (*RootParseableFail) String() string { return "" }1439func (*RootParseableFail) GoString() string { return "" }1440func (*RootParseableFail) Parse(lex *lexer.PeekingLexer) error {1441 return errors.New("always fail immediately")1442}1443func TestRootParseableFail(t *testing.T) {1444 p := mustTestParser[RootParseableFail](t)1445 _, err := p.ParseString("<test>", "blah")1446 require.EqualError(t, err, "<test>:1:1: always fail immediately")1447}1448type (1449 TestCustom interface{ isTestCustom() }1450 CustomIdent string1451 CustomNumber float641452 CustomBoolean bool1453)1454func (CustomIdent) isTestCustom() {}1455func (CustomNumber) isTestCustom() {}1456func (CustomBoolean) isTestCustom() {}1457func TestParserWithCustomProduction(t *testing.T) {1458 type grammar struct {1459 Custom TestCustom `@@`1460 }1461 p := mustTestParser[grammar](t, participle.ParseTypeWith(func(lex *lexer.PeekingLexer) (TestCustom, error) {1462 switch peek := lex.Peek(); {1463 case peek.Type == scanner.Int || peek.Type == scanner.Float:1464 v, err := strconv.ParseFloat(lex.Next().Value, 64)1465 if err != nil {1466 return nil, err1467 }1468 return CustomNumber(v), nil1469 case peek.Type == scanner.Ident:1470 name := lex.Next().Value1471 if name == "true" || name == "false" {1472 return CustomBoolean(name == "true"), nil1473 }1474 return CustomIdent(name), nil1475 default:1476 return nil, participle.NextMatch1477 }1478 }))1479 type testCase struct {1480 src string1481 expected TestCustom1482 }1483 for _, c := range []testCase{1484 {"a", CustomIdent("a")},1485 {"12.5", CustomNumber(12.5)},1486 {"true", CustomBoolean(true)},1487 {"false", CustomBoolean(false)},1488 } {1489 actual, err := p.ParseString("", c.src)1490 require.NoError(t, err)1491 require.Equal(t, c.expected, actual.Custom)1492 }1493 require.Equal(t, `Grammar = TestCustom .`, p.String())1494}1495type (1496 TestUnionA interface{ isTestUnionA() }1497 TestUnionB interface{ isTestUnionB() }1498 AMember1 struct {1499 V string `@Ident`1500 }1501 AMember2 struct {1502 V TestUnionB `"[" @@ "]"`1503 }1504 BMember1 struct {1505 V float64 `@Int | @Float`1506 }1507 BMember2 struct {1508 V TestUnionA `"{" @@ "}"`1509 }1510)1511func (AMember1) isTestUnionA() {}1512func (AMember2) isTestUnionA() {}1513func (BMember1) isTestUnionB() {}1514func (BMember2) isTestUnionB() {}1515func TestParserWithUnion(t *testing.T) {1516 type grammar struct {1517 A TestUnionA `@@`1518 B TestUnionB `| @@`1519 }1520 parser := mustTestParser[grammar](t, participle.UseLookahead(10),1521 participle.Union[TestUnionA](AMember1{}, AMember2{}),1522 participle.Union[TestUnionB](BMember1{}, BMember2{}))1523 type testCase struct {1524 src string1525 expected grammar1526 }1527 for _, c := range []testCase{1528 {`a`, grammar{A: AMember1{"a"}}},1529 {`1.5`, grammar{B: BMember1{1.5}}},1530 {`[2.5]`, grammar{A: AMember2{BMember1{2.5}}}},1531 {`{x}`, grammar{B: BMember2{AMember1{"x"}}}},1532 {`{ [ { [12] } ] }`, grammar{B: BMember2{AMember2{BMember2{AMember2{BMember1{12}}}}}}},1533 } {1534 var trace strings.Builder1535 actual, err := parser.ParseString("", c.src, participle.Trace(&trace))1536 require.NoError(t, err)1537 require.Equal(t, &c.expected, actual)1538 require.NotEqual(t, "", trace.String())1539 }1540 require.Equal(t, strings.TrimSpace(`1541Grammar = TestUnionA | TestUnionB .1542TestUnionA = AMember1 | AMember2 .1543AMember1 = <ident> .1544AMember2 = "[" TestUnionB "]" .1545TestUnionB = BMember1 | BMember2 .1546BMember1 = <int> | <float> .1547BMember2 = "{" TestUnionA "}" .1548 `), parser.String())1549}1550func TestParseSubProduction(t *testing.T) {1551 type (1552 ListItem struct {1553 Number *float64 `(@Int | @Float)`1554 String *string `| @String`1555 }1556 Grammar struct {1557 List []ListItem `"[" @@ ("," @@)* "]"`1558 }1559 )1560 numberItem := func(n float64) ListItem { return ListItem{Number: &n} }1561 stringItem := func(s string) ListItem { return ListItem{String: &s} }1562 p := mustTestParser[Grammar](t, participle.Unquote())1563 expected := &Grammar{List: []ListItem{numberItem(1), stringItem("test")}}1564 actual, err := p.ParseString("", `[ 1, "test" ]`)1565 require.NoError(t, err)1566 require.Equal(t, expected, actual)1567 expectedItem := numberItem(1.234e5)1568 ip, err := participle.ParserForProduction[ListItem](p)1569 require.NoError(t, err)1570 actualItem, err := ip.ParseString("", `1.234e5`)1571 require.NoError(t, err)1572 require.Equal(t, &expectedItem, actualItem)1573 expectedItem2 := stringItem("\t\ttest\t\t")1574 actualItem2, err := ip.ParseString("", `"\t\ttest\t\t"`)1575 require.NoError(t, err)1576 require.Equal(t, &expectedItem2, actualItem2)1577}1578type I255Grammar struct {1579 Union I255Union `@@`1580}1581type I255Union interface{ union() }1582type I255String struct {1583 Value string `@String`1584}1585func (*I255String) union() {}1586func TestIssue255(t *testing.T) {1587 parser, err := participle.Build[I255Grammar](1588 participle.Union[I255Union](&I255String{}),1589 )1590 require.NoError(t, err)1591 g, err := parser.ParseString("", `"Hello, World!"`)1592 require.NoError(t, err)1593 require.Equal(t, &I255Grammar{Union: &I255String{Value: `"Hello, World!"`}}, g)1594}...
grammar_test.go
Source:grammar_test.go
1package parser2import (3 "testing"4 "github.com/alecthomas/participle/v2"5 "github.com/k0kubun/pp"6 "github.com/stretchr/testify/assert"7)8func parserTypeWithDefaultOptions(t interface{}) (*participle.Parser, error) {9 return participle.Build(t, participle.Lexer(fileLexer), participle.Elide("Comment", "Whitespace", "CommentLine"))10}11func TestNumberRanges(t *testing.T) {12 print := false13 // t.Parallel()14 assert := assert.New(t)15 parser, err := parserTypeWithDefaultOptions(&NumberRange{})16 assert.NoError(err)17 val := &NumberRange{}18 err = parser.ParseString("", `7`, val)19 assert.NoError(err)20 assert.Equal(7, val.Single)21 if print {22 pp.Println(val)23 }24 val2 := &NumberRange{}25 err = parser.ParseString("", `1-7`, val2)26 assert.NoError(err)27 assert.Equal(1, *val2.First)28 assert.Equal(7, val2.Last)29 if print {30 pp.Println(val2)31 }32 p2, err := parserTypeWithDefaultOptions(&RangeList{})33 assert.NoError(err)34 val3 := &RangeList{}35 err = p2.ParseString("", `1-7,4,5,9`, val3)36 assert.NoError(err)37 assert.NotNil(val3.Ranges)38 assert.Len(val3.Ranges, 4)39 if print {40 pp.Println(val3)41 }42}43func TestLabelString(t *testing.T) {44 print := false45 // t.Parallel()46 assert := assert.New(t)47 parser, err := parserTypeWithDefaultOptions(&LabelString{})48 assert.NoError(err)49 val := &LabelString{}50 expect := `"Twas brillig and the slithy toves."`51 err = parser.ParseString("", expect, val)52 assert.NoError(err)53 assert.NotNil(val.Escaped)54 assert.Equal(expect, *val.Escaped)55 if print {56 pp.Println(val)57 }58 val = &LabelString{}59 expect = `S0mething_cool-ish`60 err = parser.ParseString("", expect, val)61 assert.NoError(err)62 assert.NotNil(val.Single)63 assert.Equal(expect, *val.Single)64 if print {65 pp.Println(val)66 }67}68func TestTableRow(t *testing.T) {69 print := false70 // t.Parallel()71 assert := assert.New(t)72 parser, err := parserTypeWithDefaultOptions(&TableRow{})73 assert.NoError(err)74 // Expression value75 val := &TableRow{}76 err = parser.ParseString("", `{4}`, val)77 assert.NoError(err)78 assert.Len(val.Values, 1)79 if print {80 pp.Println(val)81 }82 // Lbael and expression value.83 val = &TableRow{}84 expect := `"qux zed"`85 err = parser.ParseString("", `zombie: {4} `+expect, val)86 assert.NoError(err)87 assert.False(val.Default)88 assert.NotNil(val.Label)89 assert.Len(val.Values, 2)90 assert.Equal(expect, *val.Values[1].StringVal)91 if print {92 pp.Println(val)93 }94 // Range selector and string value95 val = &TableRow{}96 expect = `"grok"`97 err = parser.ParseString("", `1-3,4,8: `+expect, val)98 assert.NoError(err)99 assert.False(val.Default)100 assert.NotNil(val.Numbers)101 assert.Len(val.Values, 1)102 assert.Equal(expect, *val.Values[0].StringVal)103 if print {104 pp.Println(val)105 }106 // Two string values with numeeric and label selectors.107 val = &TableRow{}108 expects := []string{`"gleebrox"`, `"molduk"`}109 err = parser.ParseString("", `6 zombie: `+expects[0]+` `+expects[1], val)110 assert.NoError(err)111 assert.False(val.Default)112 assert.NotNil(val.Label)113 assert.NotNil(val.Numbers)114 assert.Len(val.Values, 2)115 assert.Equal(expects[0], *val.Values[0].StringVal)116 assert.Equal(expects[1], *val.Values[1].StringVal)117 if print {118 pp.Println(val)119 }120 // Shortest default.121 val = &TableRow{}122 err = parser.ParseString("", `Default: "zzz"`, val)123 assert.NoError(err)124 assert.True(val.Default)125 if print {126 pp.Println(val)127 }128 // Default as def and numric value.129 val = &TableRow{}130 err = parser.ParseString("", `Default 6: "zzz"`, val)131 assert.NoError(err)132 assert.True(val.Default)133 if print {134 pp.Println(val)135 }136 // Default and label.137 val = &TableRow{}138 err = parser.ParseString("", `Default axes: "xyz"`, val)139 assert.NoError(err)140 assert.True(val.Default)141 if print {142 pp.Println(val)143 }144 // Weighted rows145 val = &TableRow{}146 err = parser.ParseString("", `w=36: "xyz"`, val)147 assert.NoError(err)148 assert.Equal(36, val.Weight)149 if print {150 pp.Println(val)151 }152 // Count rows153 val = &TableRow{}154 err = parser.ParseString("", `c=36: "xyz"`, val)155 assert.NoError(err)156 assert.Equal(36, val.Count)157 if print {158 pp.Println(val)159 }160 // Multiple line lists.161 val = &TableRow{}162 err = parser.ParseString("", "\"xyz\" ->\n \"asdf\" \"qwer\" ->\r\n \t\"ffff\"", val)163 assert.NoError(err)164 assert.Len(val.Values, 4)165 if print {166 pp.Println(val)167 }168}169func TestTableHeader(t *testing.T) {170 print := false171 // t.Parallel()172 assert := assert.New(t)173 parser, err := parserTypeWithDefaultOptions(&TableHeader{})174 assert.NoError(err)175 val := &TableHeader{}176 err = parser.ParseString("", `TableDef: table1`, val)177 assert.NoError(err)178 assert.Equal("table1", val.Name)179 assert.Len(val.Tags, 0)180 if print {181 pp.Println(val)182 }183 val = &TableHeader{}184 err = parser.ParseString("", "TableDef: table1 \n ~ author: franz", val)185 assert.NoError(err)186 assert.Equal("table1", val.Name)187 assert.Len(val.Tags, 1)188 if print {189 pp.Println(val)190 }191 val = &TableHeader{}192 err = parser.ParseString("", "TableDef: table1 \n ~ author: franz \n ~ \"create date\": \"10/01/2001\"", val)193 assert.NoError(err)194 assert.Equal("table1", val.Name)195 assert.Len(val.Tags, 2)196 if print {197 pp.Println(val)198 }199}200func TestTable(t *testing.T) {201 print := false202 // t.Parallel()203 assert := assert.New(t)204 parser, err := parserTypeWithDefaultOptions(&Table{})205 assert.NoError(err)206 val := &Table{}207 table := `TableDef: footable208 ~ license: free209 1: "asdf"210 "green"211 w=3: {4}212 foo: "once"213 Default: "red"`214 err = parser.ParseString("", table, val)215 assert.NoError(err)216 assert.Equal("footable", val.Header.Name)217 assert.Len(val.Header.Tags, 1)218 assert.Len(val.Rows, 5)219 assert.True(val.Rows[4].Default)220 if print {221 pp.Println(val)222 }223}224func TestFileHeader(t *testing.T) {225 print := false226 // t.Parallel()227 assert := assert.New(t)228 parser, err := parserTypeWithDefaultOptions(&FileHeader{})229 assert.NoError(err)230 val := &FileHeader{}231 err = parser.ParseString("", `TablePack: Main`, val)232 assert.NoError(err)233 assert.Equal("Main", val.Name.Names[0])234 if print {235 pp.Println(val)236 }237 val = &FileHeader{}238 err = parser.ParseString("", `TablePack: Foo.Bar.Baz.quz.z3d`, val)239 assert.NoError(err)240 assert.Equal("Foo", val.Name.Names[0])241 assert.Len(val.Name.Names, 5)242 assert.Equal("z3d", val.Name.Names[4])243 if print {244 pp.Println(val)245 }246 val = &FileHeader{}247 header := `TablePack: garbo248 Import: f"~/tables/1.tab"249 Import: f"c:/blah/blerf"`250 err = parser.ParseString("", header, val)251 assert.NoError(err)252 assert.Equal("garbo", val.Name.Names[0])253 assert.Len(val.Name.Names, 1)254 assert.Len(val.Imports, 2)255 if print {256 pp.Println(val)257 }258 val = &FileHeader{}259 header = `TablePack: flux-capacitor.car260 Import: f"/marty/Mcfly" As: marty261 Import: f"../doc/file.file" As: doc.Fu7ur3_space`262 err = parser.ParseString("", header, val)263 assert.NoError(err)264 assert.Equal("flux-capacitor", val.Name.Names[0])265 assert.Len(val.Name.Names, 2)266 assert.Len(val.Imports, 2)267 assert.Equal("marty", val.Imports[0].Alias.Names[0])268 assert.Len(val.Imports[1].Alias.Names, 2)269 if print {270 pp.Println(val)271 }272}273func TestTableFile(t *testing.T) {274 print := false275 // t.Parallel()276 assert := assert.New(t)277 parser, err := parserTypeWithDefaultOptions(&TableFile{})278 assert.NoError(err)279 val := &TableFile{}280 err = parser.ParseString("", `TablePack: Main`, val)281 assert.NoError(err)282 assert.Equal("Main", val.Header.Name.Names[0])283 if print {284 pp.Println(val)285 }286 val = &TableFile{}287 file := `TablePack: Main288 TableDef: colors289 "red"290 "green"291 # some note292 "blue"293 ---294 TableDef: numbers295 ~ size: "7"296 ~ "weight max": forty-eight297 a: "One"298 5: "two"299 Default: {3}300 `301 err = parser.ParseString("", file, val)302 assert.NoError(err)303 assert.Equal("Main", val.Header.Name.Names[0])304 assert.Len(val.Tables, 2)305 if print {306 pp.Println(val)307 }308 val = &TableFile{}309 file = `TablePack: quacko310 Import: f"~/jeremy" As: something.new311 TableDef: colors312 Default w=4 1-5,8 red: "red"313 "blue"314 #----------315 TableDef: numbers316 ~ size: "7"317 ~ "weight max": forty-eight318 a: "One"319 5: "two"320 Default: {3}`321 err = parser.ParseString("", file, val)322 assert.NoError(err)323 assert.Equal("quacko", val.Header.Name.Names[0])324 assert.Len(val.Tables, 2)325 assert.Len(val.Tables[0].Rows, 2)326 if print {327 pp.Println(val)328 }329}330func TestRoll(t *testing.T) {331 print := false332 // t.Parallel()333 assert := assert.New(t)334 parser, err := parserTypeWithDefaultOptions(&Roll{})335 assert.NoError(err)336 val := &Roll{}337 err = parser.ParseString("", `3d8?`, val)338 assert.NoError(err)339 assert.Equal("3d8", val.RollDice)340 if print {341 pp.Println(val)342 }343 val = &Roll{}344 err = parser.ParseString("", `10d20h5.mode?`, val)345 assert.NoError(err)346 assert.Equal("10d20", val.RollDice)347 assert.Equal("h", val.RollSubset)348 assert.Equal(5, val.SubsetCount)349 assert.Equal(".mode", val.RollFuncAggr)350 assert.False(val.Print)351 if print {352 pp.Println(val)353 }354 val = &Roll{}355 err = parser.ParseString("", `10d20.+1x2.-20x1.str?`, val)356 assert.NoError(err)357 assert.Equal("10d20", val.RollDice)358 assert.Len(val.RollCountAggrs, 2)359 assert.Equal(".+", val.RollCountAggrs[0].Sign)360 assert.Equal(1, val.RollCountAggrs[0].Number)361 assert.Equal(2, val.RollCountAggrs[0].Multiplier)362 assert.True(val.Print)363 if print {364 pp.Println(val)365 }366}367func TestExpr(t *testing.T) {368 print := false369 t.Parallel()370 assert := assert.New(t)371 parser, err := parserTypeWithDefaultOptions(&Expression{})372 assert.NoError(err)373 val := &Expression{}374 err = parser.ParseString("", `{ 4}`, val)375 assert.NoError(err)376 assert.Equal(4, *val.Value.Num)377 if print {378 pp.Println(val)379 }380 val = &Expression{}381 err = parser.ParseString("", `{-8 }`, val)382 assert.NoError(err)383 assert.Equal(-8, *val.Value.Num)384 if print {385 pp.Println(val)386 }387 val = &Expression{}388 err = parser.ParseString("", `{ foo }`, val)389 assert.NoError(err)390 assert.NotNil(val.Value.Label)391 assert.Equal("foo", *val.Value.Label.Single)392 if print {393 pp.Println(val)394 }395 val = &Expression{}396 err = parser.ParseString("", `{ "hello World!" }`, val)397 assert.NoError(err)398 assert.NotNil(val.Value.Label)399 assert.Equal(`"hello World!"`, *val.Value.Label.Escaped)400 if print {401 pp.Println(val)402 }403 val = &Expression{}404 strVal := "{ add( \n\t3,\r\n \t6) }"405 err = parser.ParseString("", strVal, val)406 assert.NoError(err)407 assert.NotNil(val.Value.Call)408 assert.False(val.Value.Call.IsTable)409 assert.Equal("add", val.Value.Call.Name.Names[0])410 assert.Len(val.Value.Call.Params, 2)411 if print {412 pp.Println(val)413 }414 val = &Expression{}415 err = parser.ParseString("", `{ !color() }`, val)416 assert.NoError(err)417 assert.NotNil(val.Value.Call)418 assert.True(val.Value.Call.IsTable)419 assert.Equal("color", val.Value.Call.Name.Names[0])420 assert.Len(val.Value.Call.Params, 0)421 if print {422 pp.Println(val)423 }424 val = &Expression{}425 err = parser.ParseString("", `{ 1d3? }`, val)426 assert.NoError(err)427 assert.NotNil(val.Value.Roll)428 assert.Equal("1d3", val.Value.Roll.RollDice)429 if print {430 pp.Println(val)431 }432 val = &Expression{}433 err = parser.ParseString("", `{ add( !primes(), 3, !test(weight, 3d12.+12x1?), oops) }`, val)434 assert.NoError(err)435 assert.NotNil(val.Value.Call)436 assert.False(val.Value.Call.IsTable)437 assert.Len(val.Value.Call.Params, 4)438 if print {439 pp.Println(val)440 }441}442func TestExprVars(t *testing.T) {443 print := false444 t.Parallel()445 assert := assert.New(t)446 parser, err := parserTypeWithDefaultOptions(&Expression{})447 assert.NoError(err)448 val := &Expression{}449 strVal := `{ @foo=6; 4}`450 err = parser.ParseString("", strVal, val)451 assert.NoError(err)452 assert.Len(val.Vars, 1)453 assert.Equal("foo", val.Vars[0].VarName.Name)454 assert.Equal(6, *val.Vars[0].AssignedValue.Num)455 assert.Equal(4, *val.Value.Num)456 if print {457 pp.Println(val)458 }459 val = &Expression{}460 strVal = `{ @one="One", @Second-Thing="two"; @Second-Thing }`461 err = parser.ParseString("", strVal, val)462 assert.NoError(err)463 assert.Len(val.Vars, 2)464 assert.Equal("\"One\"", *val.Vars[0].AssignedValue.Label.Escaped)465 assert.Equal("Second-Thing", val.Value.Variable.Name)466 if print {467 pp.Println(val)468 }469 val = &Expression{}470 strVal = "{\n\t @one=\"On\ne\",\r\n @Second-Thing=\"two\";\t\n @Second-Thing }"471 err = parser.ParseString("", strVal, val)472 assert.NoError(err)473 assert.Len(val.Vars, 2)474 assert.Equal("\"On\ne\"", *val.Vars[0].AssignedValue.Label.Escaped)475 assert.Equal("Second-Thing", val.Value.Variable.Name)476 if print {477 pp.Println(val)478 }479}480func TestGeneratorRows(t *testing.T) {481 print := false482 t.Parallel()483 assert := assert.New(t)484 parser, err := parserTypeWithDefaultOptions(&Table{})485 assert.NoError(err)486 val := &Table{}487 strVal := `TableDef: foo488 ["a"]`489 err = parser.ParseString("", strVal, val)490 assert.NoError(err)491 assert.Nil(val.Rows)492 assert.Len(val.Generator.Steps, 1)493 assert.Len(val.Generator.Steps[0].Values, 1)494 if print {495 pp.Println(val)496 }497 val = &Table{}498 strVal = `TableDef: foo499 ["A","2","3","4", "5", "6", "7", "8", "9", "10" , "J" ,"Q",500 "K"][" of "]["Clubs", "Spades", "Diamonds", "Hearts"]`501 err = parser.ParseString("", strVal, val)502 assert.NoError(err)503 assert.Nil(val.Rows)504 assert.Len(val.Generator.Steps, 3)505 assert.Len(val.Generator.Steps[0].Values, 13)506 assert.Len(val.Generator.Steps[1].Values, 1)507 assert.Len(val.Generator.Steps[2].Values, 4)508 assert.Equal(`"Diamonds"`, val.Generator.Steps[2].Values[2])509 if print {510 pp.Println(val)511 }512}...
Parser.php
Source:Parser.php
...169 $bankAccount = new BankAccount();170 $BANKACCTFROM = $content->xpath('//BANKACCTFROM');171 if (count($BANKACCTFROM) == 1) {172 $BANKACCTFROM = $BANKACCTFROM[0];173 $bankAccount->bankId = isset($BANKACCTFROM->BANKID) ? OfxParser::parseString($BANKACCTFROM->BANKID) : null;174 $bankAccount->branchId = isset($BANKACCTFROM->BRANCHID) ? OfxParser::parseString($BANKACCTFROM->BRANCHID) : null;175 $bankAccount->accountId = isset($BANKACCTFROM->ACCTID) ? OfxParser::parseString($BANKACCTFROM->ACCTID) : null;176 $bankAccount->accountType = isset($BANKACCTFROM->ACCTTYPE) ? OfxParser::parseString($BANKACCTFROM->ACCTTYPE) : null;177 $bankAccount->accountKey = isset($BANKACCTFROM->ACCTKEY) ? OfxParser::parseString($BANKACCTFROM->ACCTKEY) : null;178 } // end if (count($BANKACCTFROM) == 1)179 return $bankAccount;180 }181 /**182 *183 * @param string|SimpleXMLElement $content184 *185 * @return \Realejo\Ofx\Banking\CreditcardAccount186 */187 public static function parseCreditcardAccount($content)188 {189 // Verifica se é um string190 if (is_string($content)) {191 $content = \Realejo\Ofx\Parser::makeXML($content);192 }193 $creditcardAccount = new CreditcardAccount();194 $CCACCTFROM = $content->xpath('//CCACCTFROM');195 if (count($CCACCTFROM) == 1) {196 $CCACCTFROM = $CCACCTFROM[0];197 $creditcardAccount->accountId = isset($CCACCTFROM->ACCTID) ? OfxParser::parseString($CCACCTFROM->ACCTID) : null;198 $creditcardAccount->accountKey = isset($CCACCTFROM->ACCTKEY) ? OfxParser::parseString($CCACCTFROM->ACCTKEY) : null;199 } // end if (count($BANKACCTFROM) == 1)200 return $creditcardAccount;201 }202 /**203 *204 * @param string|SimpleXMLElement $content205 *206 * @return \Realejo\Ofx\Banking\TransactionList207 */208 public static function parseTransactions($content)209 {210 // Verifica se é um string211 if (is_string($content)) {212 $content = \Realejo\Ofx\Parser::makeXML($content);213 }214 // Verifica as transações215 $BANKTRANLIST = $content->xpath('//BANKTRANLIST');216 if (count($BANKTRANLIST) == 1) {217 $BANKTRANLIST = $BANKTRANLIST[0];218 $transactionList = new TransactionList();219 $transactionList->dateStart = OfxParser::parseDate($BANKTRANLIST->DTSTART);220 $transactionList->dateEnd = OfxParser::parseDate($BANKTRANLIST->DTEND);221 $STMTTRN = $BANKTRANLIST->xpath('//STMTTRN');222 if (count($STMTTRN) > 0) {223 foreach ($STMTTRN as $S) {224 $transaction = new Transaction();225 $transaction->type = OfxParser::parseString($S->TRNTYPE);226 $transaction->datePosted = OfxParser::parseDate($S->DTPOSTED);227 $transaction->dateUser = OfxParser::parseDate($S->DTUSER);228 $transaction->dateAvalilable = OfxParser::parseDate($S->DTAVAIL);229 $transaction->amount = (float) $S->TRNAMT;230 $transaction->fitId = OfxParser::parseString($S->FITID);231 $transaction->correctFitId = OfxParser::parseString($S->CORRECTFITID);232 $transaction->correctAction = OfxParser::parseString($S->CORRECTACTION);233 $transaction->serverTransactionId = OfxParser::parseString($S->SRVRTID);234 $transaction->checkNumber = OfxParser::parseString($S->CHECKNUM);235 $transaction->referenceNumber = OfxParser::parseString($S->REFNUM);236 $transaction->standardIndustrialCode = OfxParser::parseString($S->SIC);237 $transaction->payeeId = OfxParser::parseString($S->PAYEEID);238 $transaction->name = OfxParser::parseString($S->NAME);239 $transaction->payee = OfxParser::parseString($S->PAYEE);240 $transaction->bankAccountTo = OfxParser::parseString($S->BANKACCTTO);241 $transaction->creditCardAccountTo = OfxParser::parseString($S->CCACCTTO);242 $transaction->memo = OfxParser::parseString($S->MEMO);243 $transaction->currency = OfxParser::parseString($S->CURRENCY);244 $transaction->originalCurrency = OfxParser::parseString($S->ORIGCURRENCY);245 $transactionList[] = $transaction;246 }247 } // end if (count($STMTTRN) > 0)248 // Grava o transactionList249 return $transactionList;250 } //end if (count($BANKTRANLIST) == 1)251 return null;252 }253 /**254 *255 * @param string $content256 * @return \Realejo\Ofx\Banking\Balance257 */258 public static function parseLedgerBalance($content)...
TransformationProcessorPcreCompilerTest.php
Source:TransformationProcessorPcreCompilerTest.php
...37 {38 $parser = new Persistence\TransformationProcessor\DefinitionBased\Parser( self::getInstallationDir() );39 $compiler = new Persistence\TransformationProcessor\PcreCompiler( new Persistence\Utf8Converter() );40 $rules = $compiler->compile(41 $parser->parseString(42 "map_test:\n" .43 "U+00e4 = \"ae\""44 )45 );46 $this->assertSame(47 'aeöü',48 $this->applyTransformations( $rules, 'äöü' )49 );50 }51 public function testCompileMapRemove()52 {53 $parser = new Persistence\TransformationProcessor\DefinitionBased\Parser( self::getInstallationDir() );54 $compiler = new Persistence\TransformationProcessor\PcreCompiler( new Persistence\Utf8Converter() );55 $rules = $compiler->compile(56 $parser->parseString(57 "map_test:\n" .58 "U+00e4 = remove"59 )60 );61 $this->assertSame(62 'öü',63 $this->applyTransformations( $rules, 'äöü' )64 );65 }66 public function testCompileMapKeep()67 {68 $parser = new Persistence\TransformationProcessor\DefinitionBased\Parser( self::getInstallationDir() );69 $compiler = new Persistence\TransformationProcessor\PcreCompiler( new Persistence\Utf8Converter() );70 $rules = $compiler->compile(71 $parser->parseString(72 "map_test:\n" .73 "U+00e4 = keep"74 )75 );76 $this->assertSame(77 'äöü',78 $this->applyTransformations( $rules, 'äöü' )79 );80 }81 public function testCompileMapAscii()82 {83 $parser = new Persistence\TransformationProcessor\DefinitionBased\Parser( self::getInstallationDir() );84 $compiler = new Persistence\TransformationProcessor\PcreCompiler( new Persistence\Utf8Converter() );85 $rules = $compiler->compile(86 $parser->parseString(87 "map_test:\n" .88 "U+00e4 = 41"89 )90 );91 $this->assertSame(92 'Aöü',93 $this->applyTransformations( $rules, 'äöü' )94 );95 }96 public function testCompileMapUnicode()97 {98 $parser = new Persistence\TransformationProcessor\DefinitionBased\Parser( self::getInstallationDir() );99 $compiler = new Persistence\TransformationProcessor\PcreCompiler( new Persistence\Utf8Converter() );100 $rules = $compiler->compile(101 $parser->parseString(102 "map_test:\n" .103 "U+00e4 = U+00e5"104 )105 );106 $this->assertSame(107 'åöü',108 $this->applyTransformations( $rules, 'äöü' )109 );110 }111 public function testCompileReplace()112 {113 $parser = new Persistence\TransformationProcessor\DefinitionBased\Parser( self::getInstallationDir() );114 $compiler = new Persistence\TransformationProcessor\PcreCompiler( new Persistence\Utf8Converter() );115 $rules = $compiler->compile(116 $parser->parseString(117 "replace_test:\n" .118 "U+00e0 - U+00e6 = \"a\""119 )120 );121 $this->assertSame(122 'aaaaaaaçè',123 $this->applyTransformations( $rules, 'à áâãäåæçè' )124 );125 }126 public function testCompileTranspose()127 {128 $parser = new Persistence\TransformationProcessor\DefinitionBased\Parser( self::getInstallationDir() );129 $compiler = new Persistence\TransformationProcessor\PcreCompiler( new Persistence\Utf8Converter() );130 $rules = $compiler->compile(131 $parser->parseString(132 "transpose_test:\n" .133 "U+00e0 - U+00e6 - 02"134 )135 );136 $this->assertSame(137 'ÃÃà áâãäçè',138 $this->applyTransformations( $rules, 'à áâãäåæçè' )139 );140 }141 public function testCompileTransposeAsciiLowercase()142 {143 $parser = new Persistence\TransformationProcessor\DefinitionBased\Parser( self::getInstallationDir() );144 $compiler = new Persistence\TransformationProcessor\PcreCompiler( new Persistence\Utf8Converter() );145 $rules = $compiler->compile(146 $parser->parseString(147 "ascii_lowercase:\n" .148 "U+0041 - U+005A + 20"149 )150 );151 $this->assertSame(152 'hello world',153 $this->applyTransformations( $rules, 'Hello World' )154 );155 }156 public function testCompileTransposePlus()157 {158 $parser = new Persistence\TransformationProcessor\DefinitionBased\Parser( self::getInstallationDir() );159 $compiler = new Persistence\TransformationProcessor\PcreCompiler( new Persistence\Utf8Converter() );160 $rules = $compiler->compile(161 $parser->parseString(162 "transpose_test:\n" .163 "U+00e0 - U+00e6 + 02"164 )165 );166 $this->assertSame(167 'âãäåæçèçè',168 $this->applyTransformations( $rules, 'à áâãäåæçè' )169 );170 }171 public function testCompileModuloTranspose()172 {173 $parser = new Persistence\TransformationProcessor\DefinitionBased\Parser( self::getInstallationDir() );174 $compiler = new Persistence\TransformationProcessor\PcreCompiler( new Persistence\Utf8Converter() );175 $rules = $compiler->compile(176 $parser->parseString(177 "transpose_modulo_test:\n" .178 "U+00e0 - U+00e6 % 02 - 01"179 )180 );181 $this->assertSame(182 'Ãááããååçè',183 $this->applyTransformations( $rules, 'à áâãäåæçè' )184 );185 }186}...
parseString
Using AI Code Generation
1require_once 'Parser.php';2$parser = new Parser();3$parser->parseString($string);4require_once 'Parser.php';5$parser = new Parser();6$parser->parseString($string);7require_once 'Parser.php';8$parser = new Parser();9$parser->parseString($string);10require_once 'Parser.php';11$parser = new Parser();12$parser->parseString($string);13require_once 'Parser.php';14$parser = new Parser();15$parser->parseString($string);16require_once 'Parser.php';17$parser = new Parser();18$parser->parseString($string);19require_once 'Parser.php';20$parser = new Parser();21$parser->parseString($string);22require_once 'Parser.php';23$parser = new Parser();24$parser->parseString($string);25require_once 'Parser.php';26$parser = new Parser();27$parser->parseString($string);28require_once 'Parser.php';29$parser = new Parser();30$parser->parseString($string);31require_once 'Parser.php';32$parser = new Parser();33$parser->parseString($string);34require_once 'Parser.php';35$parser = new Parser();36$parser->parseString($string);37require_once 'Parser.php';38$parser = new Parser();39$parser->parseString($string);
parseString
Using AI Code Generation
1require_once 'Parser.php';2$parser = new Parser;3$parser->parseString($string);4require_once 'Parser.php';5$parser = new Parser;6$parser->parseFile($file);7require_once 'Parser.php';8$parser = new Parser;9$parser->parseString($string);10require_once 'Parser.php';11$parser = new Parser;12$parser->parseFile($file);13require_once 'Parser.php';14$parser = new Parser;15$parser->parseString($string);16require_once 'Parser.php';17$parser = new Parser;18$parser->parseFile($file);19require_once 'Parser.php';20$parser = new Parser;21$parser->parseString($string);22require_once 'Parser.php';23$parser = new Parser;24$parser->parseFile($file);25require_once 'Parser.php';26$parser = new Parser;27$parser->parseString($string);28require_once 'Parser.php';29$parser = new Parser;30$parser->parseFile($file);31require_once 'Parser.php';32$parser = new Parser;33$parser->parseString($string);34require_once 'Parser.php';35$parser = new Parser;36$parser->parseFile($file);37require_once 'Parser.php';38$parser = new Parser;39$parser->parseString($string);40require_once 'Parser.php';41$parser = new Parser;42$parser->parseFile($file);43require_once 'Parser.php';44$parser = new Parser;
parseString
Using AI Code Generation
1require_once('Parser.php');2$parser = new Parser();3$parser->parseString("1.php");4require_once('Parser.php');5$parser = new Parser();6$parser->parseFile("1.php");7require_once('Parser.php');8$parser = new Parser();9$parser->parseDirectory("C:\\xampp\\htdocs\\php\\src\\");
parseString
Using AI Code Generation
1$parser = new Parser();2$parser->parseString($xml);3$parser->getResults();4$parser = new Parser();5$parser->parseFile($xml_file);6$parser->getResults();7 (8 (9 (10 (
parseString
Using AI Code Generation
1$parser = new Parser();2$parser->parseString($string);3$parser->parseString($string, $options, $context);4$parser->parseString($string, $options, $context, $offset);5$parser->parseString($string, $options, $context, $offset, $limit);6$parser->parseString($string, $options, $context, $offset, $limit, $flags);7$parser->parseString($string, $options, $context, $offset, $limit, $flags, $encoding);8$parser->parseString($string, $options, $context, $offset, $limit, $flags, $encoding, $error);9$parser->parseString($string, $options, $context, $offset, $limit, $flags, $encoding, $error, $error_offset);10$parser = new Parser();11$parser->parseFile($file);12$parser->parseFile($file, $options, $context);13$parser->parseFile($file, $options, $context, $offset);14$parser->parseFile($file, $options, $context, $offset, $limit);15$parser->parseFile($file, $options, $context, $offset, $limit, $flags);16$parser->parseFile($file, $options, $context, $offset, $limit, $flags, $encoding);17$parser->parseFile($file, $options, $context, $offset, $limit, $flags, $encoding, $error);18$parser->parseFile($file, $options, $context, $offset, $limit, $flags, $encoding, $error, $error_offset);19$parser = new Parser();20$parser->parseUrl($url);21$parser->parseUrl($url, $options, $context);22$parser->parseUrl($url, $options, $context, $offset);23$parser->parseUrl($url, $options, $context, $offset, $limit);24$parser->parseUrl($url, $options, $context, $offset, $limit, $flags);25$parser->parseUrl($url, $options, $context, $offset, $limit, $flags
parseString
Using AI Code Generation
1require_once 'Parser.php';2$parser = new Parser();3$parser->parseString('{"name":"John"}');4print_r($parser->getParsed());5require_once 'Parser.php';6$parser = new Parser();7$parser->parseFile('data.json');8print_r($parser->getParsed());9require_once 'Parser.php';10$parser = new Parser();11$parser->parseFile('data.json');12print_r($parser->getParsed());13require_once 'Parser.php';14$parser = new Parser();15$parser->parseFile('data.json');16print_r($parser->getParsed());17require_once 'Parser.php';18$parser = new Parser();19$parser->parseFile('data.json');20print_r($parser->getParsed());21require_once 'Parser.php';22$parser = new Parser();23$parser->parseFile('data.json');24print_r($parser->getParsed());25require_once 'Parser.php';26$parser = new Parser();27$parser->parseFile('data.json');28print_r($parser->getParsed());29require_once 'Parser.php';30$parser = new Parser();31$parser->parseFile('data.json');32print_r($parser->getParsed());33require_once 'Parser.php';34$parser = new Parser();35$parser->parseFile('data.json');36print_r($parser->getParsed());37require_once 'Parser.php';38$parser = new Parser();39$parser->parseFile('data.json');40print_r($parser->getParsed());
parseString
Using AI Code Generation
1require_once 'Parser.php';2$parser = new Parser();3$tree = $parser->parseString("1 + 2 * 3");4print_r($tree);5require_once 'Parser.php';6$parser = new Parser();7$tree = $parser->parseFile("test.txt");8print_r($tree);9require_once 'Parser.php';10$parser = new Parser();11$tree = $parser->parseFile("test.txt");12print_r($tree);13require_once 'Parser.php';14$parser = new Parser();15$tree = $parser->parseFile("test.txt");16print_r($tree);17require_once 'Parser.php';18$parser = new Parser();19$tree = $parser->parseFile("test.txt");20print_r($tree);21require_once 'Parser.php';22$parser = new Parser();23$tree = $parser->parseFile("test.txt");24print_r($tree);25require_once 'Parser.php';26$parser = new Parser();27$tree = $parser->parseFile("test.txt");28print_r($tree);
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Execute automation tests with parseString on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.
Test now for FreeGet 100 minutes of automation test minutes FREE!!