Best Syzkaller code snippet using ast.Info
parse_test.go
Source:parse_test.go
...51 }52}53func TestParseSimple(t *testing.T) {54 expected := ast.NewTree("parser simple")55 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))56 cmd := ast.NewCommandNode(token.NewFileInfo(1, 0), "echo", false)57 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 6), "hello world", true))58 ln.Push(cmd)59 expected.Root = ln60 parserTest("parser simple", `echo "hello world"`, expected, t, true)61 cmd1 := ast.NewCommandNode(token.NewFileInfo(1, 0), "cat", false)62 arg1 := ast.NewStringExpr(token.NewFileInfo(1, 4), "/etc/resolv.conf", false)63 arg2 := ast.NewStringExpr(token.NewFileInfo(1, 21), "/etc/hosts", false)64 cmd1.AddArg(arg1)65 cmd1.AddArg(arg2)66 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))67 ln.Push(cmd1)68 expected.Root = ln69 parserTest("parser simple", `cat /etc/resolv.conf /etc/hosts`, expected, t, true)70}71func TestParseReverseGetSame(t *testing.T) {72 parser := NewParser("reverse simple", "echo \"hello world\"")73 tr, err := parser.Parse()74 if err != nil {75 t.Error(err)76 return77 }78 if tr.String() != "echo \"hello world\"" {79 t.Errorf("Failed to reverse tree: %s", tr.String())80 return81 }82}83func TestParsePipe(t *testing.T) {84 expected := ast.NewTree("parser pipe")85 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))86 first := ast.NewCommandNode(token.NewFileInfo(1, 0), "echo", false)87 first.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 6), "hello world", true))88 second := ast.NewCommandNode(token.NewFileInfo(1, 21), "awk", false)89 second.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 26), "{print $1}", true))90 pipe := ast.NewPipeNode(token.NewFileInfo(1, 19), false)91 pipe.AddCmd(first)92 pipe.AddCmd(second)93 ln.Push(pipe)94 expected.Root = ln95 parserTest("parser pipe", `echo "hello world" | awk "{print $1}"`, expected, t, true)96}97func TestBasicSetEnvAssignment(t *testing.T) {98 expected := ast.NewTree("simple set assignment")99 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))100 set, err := ast.NewSetenvNode(token.NewFileInfo(1, 0), "test", nil)101 if err != nil {102 t.Fatal(err)103 }104 ln.Push(set)105 expected.Root = ln106 parserTest("simple set assignment", `setenv test`, expected, t, true)107 // setenv with assignment108 expected = ast.NewTree("setenv with simple assignment")109 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))110 assign := ast.NewSingleAssignNode(token.NewFileInfo(1, 7),111 ast.NewNameNode(token.NewFileInfo(1, 7), "test", nil),112 ast.NewStringExpr(token.NewFileInfo(1, 15), "hello", true))113 set, err = ast.NewSetenvNode(token.NewFileInfo(1, 0), "test", assign)114 if err != nil {115 t.Fatal(err)116 }117 ln.Push(set)118 expected.Root = ln119 parserTest("setenv with simple assignment", `setenv test = "hello"`, expected, t, true)120 expected = ast.NewTree("setenv with simple cmd assignment")121 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))122 cmd := ast.NewCommandNode(token.NewFileInfo(1, 15), "ls", false)123 cmdAssign, err := ast.NewExecAssignNode(124 token.NewFileInfo(1, 7),125 []*ast.NameNode{ast.NewNameNode(token.NewFileInfo(1, 7), "test", nil)},126 cmd,127 )128 if err != nil {129 t.Fatal(err)130 }131 set, err = ast.NewSetenvNode(token.NewFileInfo(1, 0), "test", cmdAssign)132 if err != nil {133 t.Fatal(err)134 }135 ln.Push(set)136 expected.Root = ln137 parserTest("simple assignment", `setenv test <= ls`, expected, t, true)138}139func TestBasicAssignment(t *testing.T) {140 expected := ast.NewTree("simple assignment")141 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))142 assign := ast.NewSingleAssignNode(token.NewFileInfo(1, 0),143 ast.NewNameNode(token.NewFileInfo(1, 0), "test", nil),144 ast.NewStringExpr(token.NewFileInfo(1, 8), "hello", true))145 ln.Push(assign)146 expected.Root = ln147 parserTest("simple assignment", `test = "hello"`, expected, t, true)148 // test concatenation of strings and variables149 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))150 concats := make([]ast.Expr, 2, 2)151 concats[0] = ast.NewStringExpr(token.NewFileInfo(1, 8), "hello", true)152 concats[1] = ast.NewVarExpr(token.NewFileInfo(1, 15), "$var")153 arg1 := ast.NewConcatExpr(token.NewFileInfo(1, 8), concats)154 assign = ast.NewSingleAssignNode(token.NewFileInfo(1, 0),155 ast.NewNameNode(token.NewFileInfo(1, 0), "test", nil),156 arg1,157 )158 ln.Push(assign)159 expected.Root = ln160 parserTest("test", `test = "hello"+$var`, expected, t, true)161 for _, test := range []string{162 "test=hello",163 "test = hello",164 "test = 1",165 "test = false",166 "test = -1",167 `test = "1", "2"`,168 } {169 parserTestFail(t, test)170 }171}172func TestVarAssignment(t *testing.T) {173 expected := ast.NewTree("var assignment")174 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))175 varAssign := ast.NewVarAssignDecl(token.NewFileInfo(1, 0),176 ast.NewSingleAssignNode(token.NewFileInfo(1, 4),177 ast.NewNameNode(token.NewFileInfo(1, 4), "test", nil),178 ast.NewStringExpr(token.NewFileInfo(1, 12), "hello", true)),179 )180 ln.Push(varAssign)181 expected.Root = ln182 parserTest("var assignment", `var test = "hello"`, expected, t, true)183 for _, test := range []string{184 "var test=hello",185 "var",186 "var test",187 "var test = false",188 "var test = -1",189 `var test = "1", "2"`,190 } {191 parserTestFail(t, test)192 }193}194func TestParseMultipleAssign(t *testing.T) {195 one := ast.NewNameNode(token.NewFileInfo(1, 0), "one", nil)196 two := ast.NewNameNode(token.NewFileInfo(1, 5), "two", nil)197 value1 := ast.NewStringExpr(token.NewFileInfo(1, 12), "1", true)198 value2 := ast.NewStringExpr(token.NewFileInfo(1, 17), "2", true)199 assign := ast.NewAssignNode(token.NewFileInfo(1, 0),200 []*ast.NameNode{one, two},201 []ast.Expr{value1, value2},202 )203 expected := ast.NewTree("tuple assignment")204 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))205 ln.Push(assign)206 expected.Root = ln207 parserTest("tuple assignment", `one, two = "1", "2"`, expected, t, true)208 lvalue1 := ast.NewListExpr(token.NewFileInfo(1, 11), []ast.Expr{})209 value2 = ast.NewStringExpr(token.NewFileInfo(1, 16), "2", true)210 assign = ast.NewAssignNode(token.NewFileInfo(1, 0),211 []*ast.NameNode{one, two},212 []ast.Expr{lvalue1, value2},213 )214 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))215 ln.Push(assign)216 expected.Root = ln217 parserTest("tuple assignment", `one, two = (), "2"`, expected, t, true)218}219func TestParseMultipleExecAssignment(t *testing.T) {220 expected := ast.NewTree("multiple cmd assignment")221 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))222 cmd := ast.NewCommandNode(token.NewFileInfo(1, 16), "ls", false)223 assign, err := ast.NewExecAssignNode(token.NewFileInfo(1, 0),224 []*ast.NameNode{225 ast.NewNameNode(token.NewFileInfo(1, 0), "test", nil),226 ast.NewNameNode(token.NewFileInfo(1, 6), "status", nil),227 },228 cmd,229 )230 if err != nil {231 t.Error(err)232 return233 }234 ln.Push(assign)235 expected.Root = ln236 parserTest("multiple cmd assignment", `test, status <= ls`, expected, t, true)237 expected = ast.NewTree("multiple cmd assignment")238 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))239 cmd = ast.NewCommandNode(token.NewFileInfo(1, 19), "ls", false)240 assign, err = ast.NewExecAssignNode(token.NewFileInfo(1, 0),241 []*ast.NameNode{242 ast.NewNameNode(token.NewFileInfo(1, 0), "test", ast.NewIntExpr(token.NewFileInfo(1, 5), 0)),243 ast.NewNameNode(token.NewFileInfo(1, 9), "status", nil),244 },245 cmd,246 )247 if err != nil {248 t.Error(err)249 return250 }251 ln.Push(assign)252 expected.Root = ln253 parserTest("multiple cmd assignment", `test[0], status <= ls`, expected, t, true)254}255func TestParseInvalidIndexing(t *testing.T) {256 // test indexed assignment257 parser := NewParser("invalid", `test[a] = "a"`)258 _, err := parser.Parse()259 if err == nil {260 t.Error("Parse must fail")261 return262 } else if err.Error() != "invalid:1:5: Expected number or variable in index. Found ARG" {263 t.Error("Invalid err msg")264 return265 }266 parser = NewParser("invalid", `test[] = "a"`)267 _, err = parser.Parse()268 if err == nil {269 t.Error("Parse must fail")270 return271 } else if err.Error() != "invalid:1:5: Expected number or variable in index. Found ]" {272 t.Error("Invalid err msg")273 return274 }275 parser = NewParser("invalid", `test[10.0] = "a"`)276 _, err = parser.Parse()277 if err == nil {278 t.Error("Parse must fail")279 return280 } else if err.Error() != "invalid:1:5: Expected number or variable in index. Found ARG" {281 t.Error("Invalid err msg")282 return283 }284}285func TestParseListAssignment(t *testing.T) {286 expected := ast.NewTree("list assignment")287 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))288 values := make([]ast.Expr, 0, 4)289 values = append(values,290 ast.NewStringExpr(token.NewFileInfo(2, 1), "plan9", false),291 ast.NewStringExpr(token.NewFileInfo(3, 1), "from", false),292 ast.NewStringExpr(token.NewFileInfo(4, 1), "bell", false),293 ast.NewStringExpr(token.NewFileInfo(5, 1), "labs", false),294 )295 elem := ast.NewListExpr(token.NewFileInfo(1, 7), values)296 assign := ast.NewSingleAssignNode(token.NewFileInfo(1, 0),297 ast.NewNameNode(token.NewFileInfo(1, 0), "test", nil),298 elem,299 )300 ln.Push(assign)301 expected.Root = ln302 parserTest("list assignment", `test = (303 plan9304 from305 bell306 labs307)`, expected, t, false)308}309func TestParseListOfListsAssignment(t *testing.T) {310 expected := ast.NewTree("list assignment")311 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))312 plan9 := make([]ast.Expr, 0, 4)313 plan9 = append(plan9,314 ast.NewStringExpr(token.NewFileInfo(2, 2), "plan9", false),315 ast.NewStringExpr(token.NewFileInfo(2, 8), "from", false),316 ast.NewStringExpr(token.NewFileInfo(2, 13), "bell", false),317 ast.NewStringExpr(token.NewFileInfo(2, 18), "labs", false),318 )319 elem1 := ast.NewListExpr(token.NewFileInfo(2, 1), plan9)320 linux := make([]ast.Expr, 0, 2)321 linux = append(linux, ast.NewStringExpr(token.NewFileInfo(3, 2), "linux", false))322 linux = append(linux, ast.NewStringExpr(token.NewFileInfo(3, 8), "kernel", false))323 elem2 := ast.NewListExpr(token.NewFileInfo(3, 1), linux)324 values := make([]ast.Expr, 2)325 values[0] = elem1326 values[1] = elem2327 elem := ast.NewListExpr(token.NewFileInfo(1, 7), values)328 assign := ast.NewSingleAssignNode(token.NewFileInfo(1, 0),329 ast.NewNameNode(token.NewFileInfo(1, 0), "test", nil),330 elem,331 )332 ln.Push(assign)333 expected.Root = ln334 parserTest("list assignment", `test = (335 (plan9 from bell labs)336 (linux kernel)337 )`, expected, t, false)338}339func TestParseCmdAssignment(t *testing.T) {340 expected := ast.NewTree("simple cmd assignment")341 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))342 cmd := ast.NewCommandNode(token.NewFileInfo(1, 8), "ls", false)343 assign, err := ast.NewExecAssignNode(token.NewFileInfo(1, 0),344 []*ast.NameNode{ast.NewNameNode(token.NewFileInfo(1, 0), "test", nil)},345 cmd,346 )347 if err != nil {348 t.Error(err)349 return350 }351 ln.Push(assign)352 expected.Root = ln353 parserTest("simple assignment", `test <= ls`, expected, t, true)354}355func TestParseInvalidEmpty(t *testing.T) {356 parser := NewParser("invalid", ";")357 _, err := parser.Parse()358 if err == nil {359 t.Error("Parse must fail")360 return361 }362}363func TestParsePathCommand(t *testing.T) {364 expected := ast.NewTree("parser simple")365 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))366 cmd := ast.NewCommandNode(token.NewFileInfo(1, 0), "/bin/echo", false)367 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 11), "hello world", true))368 ln.Push(cmd)369 expected.Root = ln370 parserTest("parser simple", `/bin/echo "hello world"`, expected, t, true)371}372func TestParseWithShebang(t *testing.T) {373 expected := ast.NewTree("parser shebang")374 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))375 cmt := ast.NewCommentNode(token.NewFileInfo(1, 0), "#!/bin/nash")376 cmd := ast.NewCommandNode(token.NewFileInfo(3, 0), "echo", false)377 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(3, 5), "bleh", false))378 ln.Push(cmt)379 ln.Push(cmd)380 expected.Root = ln381 parserTest("parser shebang", `#!/bin/nash382echo bleh383`, expected, t, true)384}385func TestParseEmptyFile(t *testing.T) {386 expected := ast.NewTree("empty file")387 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))388 expected.Root = ln389 parserTest("empty file", "", expected, t, true)390}391func TestParseSingleCommand(t *testing.T) {392 expected := ast.NewTree("single command")393 expected.Root = ast.NewBlockNode(token.NewFileInfo(1, 0))394 expected.Root.Push(ast.NewCommandNode(token.NewFileInfo(1, 0), "bleh", false))395 parserTest("single command", `bleh`, expected, t, true)396}397func TestParseRedirectSimple(t *testing.T) {398 expected := ast.NewTree("redirect")399 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))400 cmd := ast.NewCommandNode(token.NewFileInfo(1, 0), "cmd", false)401 redir := ast.NewRedirectNode(token.NewFileInfo(1, 4))402 redir.SetMap(2, ast.RedirMapSupress)403 cmd.AddRedirect(redir)404 ln.Push(cmd)405 expected.Root = ln406 parserTest("simple redirect", `cmd >[2=]`, expected, t, true)407 expected = ast.NewTree("redirect2")408 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))409 cmd = ast.NewCommandNode(token.NewFileInfo(1, 0), "cmd", false)410 redir = ast.NewRedirectNode(token.NewFileInfo(1, 4))411 redir.SetMap(2, 1)412 cmd.AddRedirect(redir)413 ln.Push(cmd)414 expected.Root = ln415 parserTest("simple redirect", `cmd >[2=1]`, expected, t, true)416}417func TestParseRedirectWithLocation(t *testing.T) {418 expected := ast.NewTree("redirect with location")419 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))420 cmd := ast.NewCommandNode(token.NewFileInfo(1, 0), "cmd", false)421 redir := ast.NewRedirectNode(token.NewFileInfo(1, 4))422 redir.SetMap(2, ast.RedirMapNoValue)423 redir.SetLocation(ast.NewStringExpr(token.NewFileInfo(1, 9), "/var/log/service.log", false))424 cmd.AddRedirect(redir)425 ln.Push(cmd)426 expected.Root = ln427 parserTest("simple redirect", `cmd >[2] /var/log/service.log`, expected, t, true)428}429func TestParseRedirectMultiples(t *testing.T) {430 expected := ast.NewTree("redirect multiples")431 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))432 cmd := ast.NewCommandNode(token.NewFileInfo(1, 0), "cmd", false)433 redir1 := ast.NewRedirectNode(token.NewFileInfo(1, 4))434 redir2 := ast.NewRedirectNode(token.NewFileInfo(1, 11))435 redir1.SetMap(1, 2)436 redir2.SetMap(2, ast.RedirMapSupress)437 cmd.AddRedirect(redir1)438 cmd.AddRedirect(redir2)439 ln.Push(cmd)440 expected.Root = ln441 parserTest("multiple redirects", `cmd >[1=2] >[2=]`, expected, t, true)442}443func TestParseCommandWithStringsEqualsNot(t *testing.T) {444 expected := ast.NewTree("strings works as expected")445 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))446 cmd1 := ast.NewCommandNode(token.NewFileInfo(1, 0), "echo", false)447 cmd2 := ast.NewCommandNode(token.NewFileInfo(2, 0), "echo", false)448 cmd1.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 5), "hello", false))449 cmd2.AddArg(ast.NewStringExpr(token.NewFileInfo(2, 6), "hello", true))450 ln.Push(cmd1)451 ln.Push(cmd2)452 expected.Root = ln453 parserTest("strings works as expected", `echo hello454echo "hello"455`, expected, t, true)456}457func TestParseCommandSeparatedBySemicolon(t *testing.T) {458 expected := ast.NewTree("semicolon")459 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))460 cmd1 := ast.NewCommandNode(token.NewFileInfo(1, 0), "echo", false)461 cmd2 := ast.NewCommandNode(token.NewFileInfo(1, 11), "echo", false)462 cmd1.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 5), "hello", false))463 cmd2.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 16), "world", false))464 ln.Push(cmd1)465 ln.Push(cmd2)466 expected.Root = ln467 parserTest("strings works as expected", `echo hello;echo world`, expected, t, false)468}469func TestParseStringNotFinished(t *testing.T) {470 parser := NewParser("string not finished", `echo "hello world`)471 tr, err := parser.Parse()472 if err == nil {473 t.Error("Error: should fail")474 return475 }476 if tr != nil {477 t.Errorf("Failed to parse")478 return479 }480}481func TestParseCd(t *testing.T) {482 expected := ast.NewTree("test cd")483 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))484 cd := ast.NewCommandNode(token.NewFileInfo(1, 0), "cd", false)485 arg := ast.NewStringExpr(token.NewFileInfo(1, 3), "/tmp", false)486 cd.AddArg(arg)487 ln.Push(cd)488 expected.Root = ln489 parserTest("test cd", "cd /tmp", expected, t, true)490 // test cd into home491 expected = ast.NewTree("test cd into home")492 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))493 cd = ast.NewCommandNode(token.NewFileInfo(1, 0), "cd", false)494 ln.Push(cd)495 expected.Root = ln496 parserTest("test cd into home", "cd", expected, t, true)497 // test cd ..498 expected = ast.NewTree("test cd ..")499 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))500 cd = ast.NewCommandNode(token.NewFileInfo(1, 0), "cd", false)501 cd.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 3), "..", false))502 ln.Push(cd)503 expected.Root = ln504 parserTest("test cd ..", "cd ..", expected, t, true)505 expected = ast.NewTree("cd into HOME by setenv")506 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))507 assign := ast.NewSingleAssignNode(token.NewFileInfo(1, 0),508 ast.NewNameNode(token.NewFileInfo(1, 0), "HOME", nil),509 ast.NewStringExpr(token.NewFileInfo(1, 8), "/", true),510 )511 set, err := ast.NewSetenvNode(token.NewFileInfo(3, 0), "HOME", nil)512 if err != nil {513 t.Fatal(err)514 }515 cd = ast.NewCommandNode(token.NewFileInfo(5, 0), "cd", false)516 pwd := ast.NewCommandNode(token.NewFileInfo(6, 0), "pwd", false)517 ln.Push(assign)518 ln.Push(set)519 ln.Push(cd)520 ln.Push(pwd)521 expected.Root = ln522 parserTest("test cd into HOME by setenv", `HOME = "/"523setenv HOME524cd525pwd`, expected, t, true)526 // Test cd into custom variable527 expected = ast.NewTree("cd into variable value")528 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))529 arg = ast.NewStringExpr(token.NewFileInfo(1, 10), "/home/i4k/gopath", true)530 assign = ast.NewSingleAssignNode(token.NewFileInfo(1, 0),531 ast.NewNameNode(token.NewFileInfo(1, 0), "GOPATH", nil),532 arg,533 )534 cd = ast.NewCommandNode(token.NewFileInfo(3, 0), "cd", false)535 arg2 := ast.NewVarExpr(token.NewFileInfo(3, 3), "$GOPATH")536 cd.AddArg(arg2)537 ln.Push(assign)538 ln.Push(cd)539 expected.Root = ln540 parserTest("test cd into variable value", `GOPATH = "/home/i4k/gopath"541cd $GOPATH`, expected, t, true)542 // Test cd into custom variable543 expected = ast.NewTree("cd into variable value with concat")544 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))545 arg = ast.NewStringExpr(token.NewFileInfo(1, 10), "/home/i4k/gopath", true)546 assign = ast.NewSingleAssignNode(token.NewFileInfo(1, 0),547 ast.NewNameNode(token.NewFileInfo(1, 0), "GOPATH", nil),548 arg,549 )550 concat := make([]ast.Expr, 0, 2)551 concat = append(concat, ast.NewVarExpr(token.NewFileInfo(3, 3), "$GOPATH"))552 concat = append(concat, ast.NewStringExpr(token.NewFileInfo(3, 12), "/src/github.com", true))553 cd = ast.NewCommandNode(token.NewFileInfo(3, 0), "cd", false)554 carg := ast.NewConcatExpr(token.NewFileInfo(3, 3), concat)555 cd.AddArg(carg)556 ln.Push(assign)557 ln.Push(cd)558 expected.Root = ln559 parserTest("test cd into variable value", `GOPATH = "/home/i4k/gopath"560cd $GOPATH+"/src/github.com"`, expected, t, true)561}562func TestParseConcatOfIndexedVar(t *testing.T) {563 expected := ast.NewTree("concat indexed var")564 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))565 arg1 := ast.NewStringExpr(token.NewFileInfo(1, 4), "ec2", false)566 arg2 := ast.NewStringExpr(token.NewFileInfo(1, 8), "create-tags", false)567 arg3 := ast.NewStringExpr(token.NewFileInfo(1, 20), "--resources", false)568 arg4 := ast.NewVarExpr(token.NewFileInfo(1, 32), "$resource")569 arg5 := ast.NewStringExpr(token.NewFileInfo(1, 42), "--tags", false)570 c1 := ast.NewStringExpr(token.NewFileInfo(1, 50), "Key=", true)571 c2 := ast.NewIndexExpr(token.NewFileInfo(1, 56),572 ast.NewVarExpr(token.NewFileInfo(1, 56), "$tag"),573 ast.NewIntExpr(token.NewFileInfo(1, 61), 0))574 c3 := ast.NewStringExpr(token.NewFileInfo(1, 65), ",Value=", true)575 c4 := ast.NewIndexExpr(token.NewFileInfo(1, 74),576 ast.NewVarExpr(token.NewFileInfo(1, 74), "$tag"),577 ast.NewIntExpr(token.NewFileInfo(1, 79), 1))578 cvalues := make([]ast.Expr, 4)579 cvalues[0] = c1580 cvalues[1] = c2581 cvalues[2] = c3582 cvalues[3] = c4583 arg6 := ast.NewConcatExpr(token.NewFileInfo(1, 50), cvalues)584 cmd := ast.NewCommandNode(token.NewFileInfo(1, 0), "aws", false)585 cmd.AddArg(arg1)586 cmd.AddArg(arg2)587 cmd.AddArg(arg3)588 cmd.AddArg(arg4)589 cmd.AddArg(arg5)590 cmd.AddArg(arg6)591 ln.Push(cmd)592 expected.Root = ln593 parserTest("concat indexed var",594 `aws ec2 create-tags --resources $resource --tags "Key="+$tag[0]+",Value="+$tag[1]`,595 expected, t, true)596}597func TestParseRfork(t *testing.T) {598 expected := ast.NewTree("test rfork")599 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))600 cmd1 := ast.NewRforkNode(token.NewFileInfo(1, 0))601 f1 := ast.NewStringExpr(token.NewFileInfo(1, 6), "u", false)602 cmd1.SetFlags(f1)603 ln.Push(cmd1)604 expected.Root = ln605 parserTest("test rfork", "rfork u", expected, t, true)606}607func TestParseRforkWithBlock(t *testing.T) {608 expected := ast.NewTree("rfork with block")609 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))610 rfork := ast.NewRforkNode(token.NewFileInfo(1, 0))611 arg := ast.NewStringExpr(token.NewFileInfo(1, 6), "u", false)612 rfork.SetFlags(arg)613 insideFork := ast.NewCommandNode(token.NewFileInfo(2, 1), "mount", false)614 insideFork.AddArg(ast.NewStringExpr(token.NewFileInfo(2, 7), "-t", false))615 insideFork.AddArg(ast.NewStringExpr(token.NewFileInfo(2, 10), "proc", false))616 insideFork.AddArg(ast.NewStringExpr(token.NewFileInfo(2, 15), "proc", false))617 insideFork.AddArg(ast.NewStringExpr(token.NewFileInfo(2, 20), "/proc", false))618 bln := ast.NewBlockNode(token.NewFileInfo(1, 8))619 bln.Push(insideFork)620 subtree := ast.NewTree("rfork")621 subtree.Root = bln622 rfork.SetTree(subtree)623 ln.Push(rfork)624 expected.Root = ln625 parserTest("rfork with block", `rfork u {626 mount -t proc proc /proc627}628`, expected, t, true)629}630func TestUnpairedRforkBlocks(t *testing.T) {631 parser := NewParser("unpaired", "rfork u {")632 _, err := parser.Parse()633 if err == nil {634 t.Errorf("Should fail because of unpaired open/close blocks")635 return636 }637}638func TestParseImport(t *testing.T) {639 expected := ast.NewTree("test import")640 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))641 importStmt := ast.NewImportNode(token.NewFileInfo(1, 0),642 ast.NewStringExpr(token.NewFileInfo(1, 7), "env.sh", false))643 ln.Push(importStmt)644 expected.Root = ln645 parserTest("test import", "import env.sh", expected, t, true)646 expected = ast.NewTree("test import with quotes")647 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))648 importStmt = ast.NewImportNode(token.NewFileInfo(1, 0),649 ast.NewStringExpr(token.NewFileInfo(1, 8), "env.sh", true))650 ln.Push(importStmt)651 expected.Root = ln652 parserTest("test import", `import "env.sh"`, expected, t, true)653}654func TestParseIf(t *testing.T) {655 expected := ast.NewTree("test if")656 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))657 ifDecl := ast.NewIfNode(token.NewFileInfo(1, 0))658 ifDecl.SetLvalue(ast.NewStringExpr(token.NewFileInfo(1, 4), "test", true))659 ifDecl.SetRvalue(ast.NewStringExpr(token.NewFileInfo(1, 14), "other", true))660 ifDecl.SetOp("==")661 subBlock := ast.NewBlockNode(token.NewFileInfo(1, 21))662 cmd := ast.NewCommandNode(token.NewFileInfo(2, 1), "pwd", false)663 subBlock.Push(cmd)664 ifTree := ast.NewTree("if block")665 ifTree.Root = subBlock666 ifDecl.SetIfTree(ifTree)667 ln.Push(ifDecl)668 expected.Root = ln669 parserTest("test if", `if "test" == "other" {670 pwd671}`, expected, t, true)672 expected = ast.NewTree("test if")673 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))674 ifDecl = ast.NewIfNode(token.NewFileInfo(1, 0))675 ifDecl.SetLvalue(ast.NewStringExpr(token.NewFileInfo(1, 4), "", true))676 ifDecl.SetRvalue(ast.NewStringExpr(token.NewFileInfo(1, 10), "other", true))677 ifDecl.SetOp("!=")678 subBlock = ast.NewBlockNode(token.NewFileInfo(1, 17))679 cmd = ast.NewCommandNode(token.NewFileInfo(2, 1), "pwd", false)680 subBlock.Push(cmd)681 ifTree = ast.NewTree("if block")682 ifTree.Root = subBlock683 ifDecl.SetIfTree(ifTree)684 ln.Push(ifDecl)685 expected.Root = ln686 parserTest("test if", `if "" != "other" {687 pwd688}`, expected, t, true)689}690func TestParseFuncall(t *testing.T) {691 expected := ast.NewTree("fn inv")692 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))693 aFn := ast.NewFnInvNode(token.NewFileInfo(1, 0), "a")694 ln.Push(aFn)695 expected.Root = ln696 parserTest("test basic fn inv", `a()`, expected, t, true)697 expected = ast.NewTree("fn inv")698 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))699 aFn = ast.NewFnInvNode(token.NewFileInfo(1, 0), "a")700 bFn := ast.NewFnInvNode(token.NewFileInfo(1, 2), "b")701 aFn.AddArg(bFn)702 ln.Push(aFn)703 expected.Root = ln704 parserTest("test fn composition", `a(b())`, expected, t, true)705 expected = ast.NewTree("fn inv")706 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))707 aFn = ast.NewFnInvNode(token.NewFileInfo(1, 0), "a")708 bFn = ast.NewFnInvNode(token.NewFileInfo(1, 2), "b")709 b2Fn := ast.NewFnInvNode(token.NewFileInfo(1, 7), "b")710 aFn.AddArg(bFn)711 aFn.AddArg(b2Fn)712 ln.Push(aFn)713 expected.Root = ln714 parserTest("test fn composition", `a(b(), b())`, expected, t, true)715 expected = ast.NewTree("fn inv")716 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))717 aFn = ast.NewFnInvNode(token.NewFileInfo(1, 0), "a")718 bFn = ast.NewFnInvNode(token.NewFileInfo(1, 2), "b")719 b2Fn = ast.NewFnInvNode(token.NewFileInfo(1, 4), "b")720 bFn.AddArg(b2Fn)721 aFn.AddArg(bFn)722 ln.Push(aFn)723 expected.Root = ln724 parserTest("test fn composition", `a(b(b()))`, expected, t, true)725 expected = ast.NewTree("fn inv list")726 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))727 aFn = ast.NewFnInvNode(token.NewFileInfo(1, 0), "a")728 lExpr := ast.NewListExpr(token.NewFileInfo(1, 2), []ast.Expr{729 ast.NewStringExpr(token.NewFileInfo(1, 4), "1", true),730 ast.NewStringExpr(token.NewFileInfo(1, 8), "2", true),731 ast.NewStringExpr(token.NewFileInfo(1, 12), "3", true),732 })733 aFn.AddArg(lExpr)734 ln.Push(aFn)735 expected.Root = ln736 parserTest("test fn list arg", `a(("1" "2" "3"))`, expected, t, true)737 // test valid funcall syntaxes (do not verify AST)738 for _, tc := range []string{739 `func()`,740 `func(())`, // empty list741 `func($a)`,742 `_($a, $b)`,743 `func($a())`,744 `func($a(), $b())`,745 `func($a($b($c())))`,746 `func($a("a"))`,747 `__((((()))))`, // perfect fit for a nash obfuscating code contest748 `_(749 ()750 )`,751 `_(752 (), (), (), (), (),753 )`,754 `_((() () () () ()))`,755 `deploy((bomb shell))`, // unquoted list elements are still supported :-(756 `func("a", ())`,757 `_($a+$b)`,758 `_($a+"")`,759 `_(""+$a)`,760 `func((()()))`,761 } {762 parser := NewParser("test", tc)763 _, err := parser.Parse()764 if err != nil {765 t.Fatal(err)766 }767 }768}769func TestParseFuncallInvalid(t *testing.T) {770 for _, tc := range []string{771 `test(()`,772 `_())`,773 `func(a)`,774 `func("a", a)`,775 `func(_(((((()))))`,776 `func(()+())`,777 `func("1"+("2" "3"))`,778 `func(()())`,779 } {780 parser := NewParser("test", tc)781 _, err := parser.Parse()782 if err == nil {783 t.Fatalf("Syntax '%s' must fail...", tc)784 }785 }786}787func TestParseIfFnInv(t *testing.T) {788 expected := ast.NewTree("test if")789 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))790 ifDecl := ast.NewIfNode(token.NewFileInfo(1, 0))791 ifDecl.SetLvalue(ast.NewFnInvNode(token.NewFileInfo(1, 3), "test"))792 ifDecl.SetRvalue(ast.NewStringExpr(token.NewFileInfo(1, 14), "other", true))793 ifDecl.SetOp("==")794 subBlock := ast.NewBlockNode(token.NewFileInfo(1, 21))795 cmd := ast.NewCommandNode(token.NewFileInfo(2, 1), "pwd", false)796 subBlock.Push(cmd)797 ifTree := ast.NewTree("if block")798 ifTree.Root = subBlock799 ifDecl.SetIfTree(ifTree)800 ln.Push(ifDecl)801 expected.Root = ln802 parserTest("test if", `if test() == "other" {803 pwd804}`, expected, t, true)805 expected = ast.NewTree("test if")806 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))807 ifDecl = ast.NewIfNode(token.NewFileInfo(1, 0))808 fnInv := ast.NewFnInvNode(token.NewFileInfo(1, 3), "test")809 fnInv.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 9), "bleh", true))810 ifDecl.SetLvalue(fnInv)811 ifDecl.SetRvalue(ast.NewStringExpr(token.NewFileInfo(1, 20), "other", true))812 ifDecl.SetOp("!=")813 subBlock = ast.NewBlockNode(token.NewFileInfo(1, 27))814 cmd = ast.NewCommandNode(token.NewFileInfo(2, 1), "pwd", false)815 subBlock.Push(cmd)816 ifTree = ast.NewTree("if block")817 ifTree.Root = subBlock818 ifDecl.SetIfTree(ifTree)819 ln.Push(ifDecl)820 expected.Root = ln821 parserTest("test if", `if test("bleh") != "other" {822 pwd823}`, expected, t, true)824}825func TestParseIfLvariable(t *testing.T) {826 expected := ast.NewTree("test if with variable")827 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))828 ifDecl := ast.NewIfNode(token.NewFileInfo(1, 0))829 ifDecl.SetLvalue(ast.NewVarExpr(token.NewFileInfo(1, 3), "$test"))830 ifDecl.SetRvalue(ast.NewStringExpr(token.NewFileInfo(1, 13), "other", true))831 ifDecl.SetOp("==")832 subBlock := ast.NewBlockNode(token.NewFileInfo(1, 20))833 cmd := ast.NewCommandNode(token.NewFileInfo(2, 1), "pwd", false)834 subBlock.Push(cmd)835 ifTree := ast.NewTree("if block")836 ifTree.Root = subBlock837 ifDecl.SetIfTree(ifTree)838 ln.Push(ifDecl)839 expected.Root = ln840 parserTest("test if", `if $test == "other" {841 pwd842}`, expected, t, true)843}844func TestParseIfRvariable(t *testing.T) {845 expected := ast.NewTree("test if with variable")846 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))847 ifDecl := ast.NewIfNode(token.NewFileInfo(1, 0))848 ifDecl.SetLvalue(ast.NewVarExpr(token.NewFileInfo(1, 3), "$test"))849 ifDecl.SetRvalue(ast.NewVarExpr(token.NewFileInfo(1, 12), "$other"))850 ifDecl.SetOp("==")851 subBlock := ast.NewBlockNode(token.NewFileInfo(1, 19))852 cmd := ast.NewCommandNode(token.NewFileInfo(2, 1), "pwd", false)853 subBlock.Push(cmd)854 ifTree := ast.NewTree("if block")855 ifTree.Root = subBlock856 ifDecl.SetIfTree(ifTree)857 ln.Push(ifDecl)858 expected.Root = ln859 parserTest("test if", `if $test == $other {860 pwd861}`, expected, t, true)862}863func TestParseIfElse(t *testing.T) {864 expected := ast.NewTree("test if else with variable")865 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))866 ifDecl := ast.NewIfNode(token.NewFileInfo(1, 0))867 ifDecl.SetLvalue(ast.NewVarExpr(token.NewFileInfo(1, 3), "$test"))868 ifDecl.SetRvalue(ast.NewStringExpr(token.NewFileInfo(1, 13), "other", true))869 ifDecl.SetOp("==")870 subBlock := ast.NewBlockNode(token.NewFileInfo(1, 20))871 cmd := ast.NewCommandNode(token.NewFileInfo(2, 1), "pwd", false)872 subBlock.Push(cmd)873 ifTree := ast.NewTree("if block")874 ifTree.Root = subBlock875 ifDecl.SetIfTree(ifTree)876 elseBlock := ast.NewBlockNode(token.NewFileInfo(3, 7))877 exitCmd := ast.NewCommandNode(token.NewFileInfo(4, 1), "exit", false)878 elseBlock.Push(exitCmd)879 elseTree := ast.NewTree("else block")880 elseTree.Root = elseBlock881 ifDecl.SetElseTree(elseTree)882 ln.Push(ifDecl)883 expected.Root = ln884 parserTest("test if", `if $test == "other" {885 pwd886} else {887 exit888}`, expected, t, true)889}890func TestParseIfElseIf(t *testing.T) {891 expected := ast.NewTree("test if else with variable")892 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))893 ifDecl := ast.NewIfNode(token.NewFileInfo(1, 0))894 ifDecl.SetLvalue(ast.NewVarExpr(token.NewFileInfo(1, 3), "$test"))895 ifDecl.SetRvalue(ast.NewStringExpr(token.NewFileInfo(1, 13), "other", true))896 ifDecl.SetOp("==")897 subBlock := ast.NewBlockNode(token.NewFileInfo(1, 20))898 cmd := ast.NewCommandNode(token.NewFileInfo(2, 1), "pwd", false)899 subBlock.Push(cmd)900 ifTree := ast.NewTree("if block")901 ifTree.Root = subBlock902 ifDecl.SetIfTree(ifTree)903 elseIfDecl := ast.NewIfNode(token.NewFileInfo(3, 7))904 elseIfDecl.SetLvalue(ast.NewVarExpr(token.NewFileInfo(3, 10), "$test"))905 elseIfDecl.SetRvalue(ast.NewStringExpr(token.NewFileInfo(3, 20), "others", true))906 elseIfDecl.SetOp("==")907 elseIfBlock := ast.NewBlockNode(token.NewFileInfo(3, 28))908 elseifCmd := ast.NewCommandNode(token.NewFileInfo(4, 1), "ls", false)909 elseIfBlock.Push(elseifCmd)910 elseIfTree := ast.NewTree("if block")911 elseIfTree.Root = elseIfBlock912 elseIfDecl.SetIfTree(elseIfTree)913 elseBlock := ast.NewBlockNode(token.NewFileInfo(5, 7))914 exitCmd := ast.NewCommandNode(token.NewFileInfo(6, 1), "exit", false)915 elseBlock.Push(exitCmd)916 elseTree := ast.NewTree("else block")917 elseTree.Root = elseBlock918 elseIfDecl.SetElseTree(elseTree)919 elseBlock2 := ast.NewBlockNode(token.NewFileInfo(3, 7))920 elseBlock2.Push(elseIfDecl)921 elseTree2 := ast.NewTree("first else tree")922 elseTree2.Root = elseBlock2923 ifDecl.SetElseTree(elseTree2)924 ln.Push(ifDecl)925 expected.Root = ln926 parserTest("test if", `if $test == "other" {927 pwd928} else if $test == "others" {929 ls930} else {931 exit932}`, expected, t, true)933}934func TestParseFnBasic(t *testing.T) {935 // root936 expected := ast.NewTree("fn")937 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))938 // fn939 fn := ast.NewFnDeclNode(token.NewFileInfo(1, 3), "build")940 tree := ast.NewTree("fn body")941 lnBody := ast.NewBlockNode(token.NewFileInfo(1, 0))942 tree.Root = lnBody943 fn.SetTree(tree)944 // root945 ln.Push(fn)946 expected.Root = ln947 parserTest("fn", `fn build() {948}`, expected, t, true)949 // root950 expected = ast.NewTree("fn")951 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))952 // fn953 fn = ast.NewFnDeclNode(token.NewFileInfo(1, 3), "build")954 tree = ast.NewTree("fn body")955 lnBody = ast.NewBlockNode(token.NewFileInfo(1, 0))956 cmd := ast.NewCommandNode(token.NewFileInfo(1, 0), "ls", false)957 lnBody.Push(cmd)958 tree.Root = lnBody959 fn.SetTree(tree)960 // root961 ln.Push(fn)962 expected.Root = ln963 parserTest("fn", `fn build() {964 ls965}`, expected, t, true)966 // root967 expected = ast.NewTree("fn")968 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))969 // fn970 fn = ast.NewFnDeclNode(token.NewFileInfo(1, 3), "build")971 fn.AddArg(ast.NewFnArgNode(token.NewFileInfo(1, 9), "image", false))972 tree = ast.NewTree("fn body")973 lnBody = ast.NewBlockNode(token.NewFileInfo(1, 0))974 cmd = ast.NewCommandNode(token.NewFileInfo(1, 0), "ls", false)975 lnBody.Push(cmd)976 tree.Root = lnBody977 fn.SetTree(tree)978 // root979 ln.Push(fn)980 expected.Root = ln981 parserTest("fn", `fn build(image) {982 ls983}`, expected, t, true)984 // root985 expected = ast.NewTree("fn")986 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))987 // fn988 fn = ast.NewFnDeclNode(token.NewFileInfo(1, 3), "build")989 fn.AddArg(ast.NewFnArgNode(token.NewFileInfo(1, 9), "image", false))990 fn.AddArg(ast.NewFnArgNode(token.NewFileInfo(1, 16), "debug", false))991 tree = ast.NewTree("fn body")992 lnBody = ast.NewBlockNode(token.NewFileInfo(1, 0))993 cmd = ast.NewCommandNode(token.NewFileInfo(1, 0), "ls", false)994 lnBody.Push(cmd)995 tree.Root = lnBody996 fn.SetTree(tree)997 // root998 ln.Push(fn)999 expected.Root = ln1000 parserTest("fn", `fn build(image, debug) {1001 ls1002}`, expected, t, true)1003}1004func TestParseInlineFnDecl(t *testing.T) {1005 expected := ast.NewTree("fn")1006 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))1007 fn := ast.NewFnDeclNode(token.NewFileInfo(1, 3), "cd")1008 tree := ast.NewTree("fn body")1009 lnBody := ast.NewBlockNode(token.NewFileInfo(1, 0))1010 echo := ast.NewCommandNode(token.NewFileInfo(1, 11), "echo", false)1011 echo.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 16), "hello", true))1012 lnBody.Push(echo)1013 tree.Root = lnBody1014 fn.SetTree(tree)1015 // root1016 ln.Push(fn)1017 expected.Root = ln1018 parserTest("inline fn", `fn cd() { echo "hello" }`,1019 expected, t, false)1020 test := ast.NewCommandNode(token.NewFileInfo(1, 26), "test", false)1021 test.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 32), "-d", false))1022 test.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 35), "/etc", false))1023 pipe := ast.NewPipeNode(token.NewFileInfo(1, 11), false)1024 pipe.AddCmd(echo)1025 pipe.AddCmd(test)1026 lnBody = ast.NewBlockNode(token.NewFileInfo(1, 0))1027 lnBody.Push(pipe)1028 tree.Root = lnBody1029 fn.SetTree(tree)1030 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))1031 ln.Push(fn)1032 expected.Root = ln1033 parserTest("inline fn", `fn cd() { echo "hello" | test -d /etc }`,1034 expected, t, false)1035}1036func TestParseBindFn(t *testing.T) {1037 expected := ast.NewTree("bindfn")1038 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))1039 bindFn := ast.NewBindFnNode(token.NewFileInfo(1, 0), "cd", "cd2")1040 ln.Push(bindFn)1041 expected.Root = ln1042 parserTest("bindfn", `bindfn cd cd2`, expected, t, true)1043}1044func TestParseRedirectionVariable(t *testing.T) {1045 expected := ast.NewTree("redirection var")1046 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))1047 cmd := ast.NewCommandNode(token.NewFileInfo(1, 0), "cmd", false)1048 redir := ast.NewRedirectNode(token.NewFileInfo(1, 4))1049 redirArg := ast.NewVarExpr(token.NewFileInfo(1, 6), "$outFname")1050 redir.SetLocation(redirArg)1051 cmd.AddRedirect(redir)1052 ln.Push(cmd)1053 expected.Root = ln1054 parserTest("redir var", `cmd > $outFname`, expected, t, true)1055}1056func TestParseReturn(t *testing.T) {1057 expected := ast.NewTree("return")1058 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))1059 ret := ast.NewReturnNode(token.NewFileInfo(1, 0))1060 ln.Push(ret)1061 expected.Root = ln1062 parserTest("return", `return`, expected, t, true)1063 expected = ast.NewTree("return list")1064 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))1065 ret = ast.NewReturnNode(token.NewFileInfo(1, 0))1066 listvalues := make([]ast.Expr, 2)1067 listvalues[0] = ast.NewStringExpr(token.NewFileInfo(1, 9), "val1", true)1068 listvalues[1] = ast.NewStringExpr(token.NewFileInfo(1, 16), "val2", true)1069 retReturn := ast.NewListExpr(token.NewFileInfo(1, 7), listvalues)1070 ret.Returns = []ast.Expr{retReturn}1071 ln.Push(ret)1072 expected.Root = ln1073 parserTest("return", `return ("val1" "val2")`, expected, t, true)1074 expected = ast.NewTree("return variable")1075 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))1076 ret = ast.NewReturnNode(token.NewFileInfo(1, 0))1077 ret.Returns = []ast.Expr{ast.NewVarExpr(token.NewFileInfo(1, 7), "$var")}1078 ln.Push(ret)1079 expected.Root = ln1080 parserTest("return", `return $var`, expected, t, true)1081 expected = ast.NewTree("return string")1082 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))1083 ret = ast.NewReturnNode(token.NewFileInfo(1, 0))1084 ret.Returns = []ast.Expr{ast.NewStringExpr(token.NewFileInfo(1, 8), "value", true)}1085 ln.Push(ret)1086 expected.Root = ln1087 parserTest("return", `return "value"`, expected, t, true)1088 expected = ast.NewTree("return funcall")1089 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))1090 ret = ast.NewReturnNode(token.NewFileInfo(1, 0))1091 aFn := ast.NewFnInvNode(token.NewFileInfo(1, 7), "a")1092 ret.Returns = []ast.Expr{aFn}1093 ln.Push(ret)1094 expected.Root = ln1095 parserTest("return", `return a()`, expected, t, true)1096 expected = ast.NewTree("return multiple values")1097 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))1098 ret = ast.NewReturnNode(token.NewFileInfo(1, 0))1099 a1 := ast.NewStringExpr(token.NewFileInfo(1, 8), "1", true)1100 a2 := ast.NewStringExpr(token.NewFileInfo(1, 13), "2", true)1101 a3 := ast.NewStringExpr(token.NewFileInfo(1, 18), "3", true)1102 ret.Returns = []ast.Expr{a1, a2, a3}1103 ln.Push(ret)1104 expected.Root = ln1105 parserTest("return", `return "1", "2", "3"`, expected, t, true)1106}1107func TestParseIfInvalid(t *testing.T) {1108 parser := NewParser("if invalid", `if a == b { pwd }`)1109 _, err := parser.Parse()1110 if err == nil {1111 t.Error("Must fail. Only quoted strings and variables on if clauses.")1112 return1113 }1114}1115func TestParseFor(t *testing.T) {1116 expected := ast.NewTree("for")1117 forStmt := ast.NewForNode(token.NewFileInfo(1, 0))1118 forTree := ast.NewTree("for block")1119 forBlock := ast.NewBlockNode(token.NewFileInfo(1, 0))1120 forTree.Root = forBlock1121 forStmt.SetTree(forTree)1122 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))1123 ln.Push(forStmt)1124 expected.Root = ln1125 parserTest("for", `for {1126}`, expected, t, true)1127 forStmt.SetIdentifier("f")1128 forStmt.SetInExpr(ast.NewVarExpr(token.NewFileInfo(1, 9), "$files"))1129 parserTest("for", `for f in $files {1130}`, expected, t, true)1131 forStmt.SetIdentifier("f")1132 fnInv := ast.NewFnInvNode(token.NewFileInfo(1, 9), "getfiles")1133 fnArg := ast.NewStringExpr(token.NewFileInfo(1, 19), "/", true)1134 fnInv.AddArg(fnArg)1135 forStmt.SetInExpr(fnInv)1136 parserTest("for", `for f in getfiles("/") {1137}`, expected, t, true)1138 forStmt.SetIdentifier("f")1139 value1 := ast.NewStringExpr(token.NewFileInfo(1, 10), "1", false)1140 value2 := ast.NewStringExpr(token.NewFileInfo(1, 12), "2", false)1141 value3 := ast.NewStringExpr(token.NewFileInfo(1, 14), "3", false)1142 value4 := ast.NewStringExpr(token.NewFileInfo(1, 16), "4", false)1143 value5 := ast.NewStringExpr(token.NewFileInfo(1, 18), "5", false)1144 list := ast.NewListExpr(token.NewFileInfo(1, 9), []ast.Expr{1145 value1, value2, value3, value4, value5,1146 })1147 forStmt.SetInExpr(list)1148 parserTest("for", `for f in (1 2 3 4 5) {1149}`, expected, t, true)1150}1151func TestParseVariableIndexing(t *testing.T) {1152 expected := ast.NewTree("variable indexing")1153 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))1154 indexedVar := ast.NewIndexExpr(1155 token.NewFileInfo(1, 7),1156 ast.NewVarExpr(token.NewFileInfo(1, 7), "$values"),1157 ast.NewIntExpr(token.NewFileInfo(1, 15), 0),1158 )1159 assignment := ast.NewSingleAssignNode(token.NewFileInfo(1, 0),1160 ast.NewNameNode(token.NewFileInfo(1, 0), "test", nil),1161 indexedVar,1162 )1163 ln.Push(assignment)1164 expected.Root = ln1165 parserTest("variable indexing", `test = $values[0]`, expected, t, true)1166 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))1167 ifDecl := ast.NewIfNode(token.NewFileInfo(1, 0))1168 lvalue := ast.NewVarExpr(token.NewFileInfo(1, 3), "$values")1169 indexedVar = ast.NewIndexExpr(token.NewFileInfo(1, 3), lvalue,1170 ast.NewIntExpr(token.NewFileInfo(1, 11), 0))1171 ifDecl.SetLvalue(indexedVar)1172 ifDecl.SetOp("==")1173 ifDecl.SetRvalue(ast.NewStringExpr(token.NewFileInfo(1, 18), "1", true))1174 ifBlock := ast.NewTree("if")1175 lnBody := ast.NewBlockNode(token.NewFileInfo(1, 21))1176 ifBlock.Root = lnBody1177 ifDecl.SetIfTree(ifBlock)1178 ln.Push(ifDecl)1179 expected.Root = ln1180 parserTest("variable indexing", `if $values[0] == "1" {1181}`, expected, t, true)1182}1183func TestParseMultilineCmdExec(t *testing.T) {1184 expected := ast.NewTree("parser simple")1185 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))1186 cmd := ast.NewCommandNode(token.NewFileInfo(1, 1), "echo", true)1187 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 7), "hello world", true))1188 ln.Push(cmd)1189 expected.Root = ln1190 parserTest("parser simple", `(echo "hello world")`, expected, t, true)1191 expected = ast.NewTree("parser aws cmd")1192 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))1193 cmd = ast.NewCommandNode(token.NewFileInfo(2, 1), "aws", true)1194 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(2, 5), "ec2", false))1195 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(2, 9), "run-instances", false))1196 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(3, 3), "--image-id", false))1197 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(3, 14), "ami-xxxxxxxx", false))1198 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(4, 3), "--count", false))1199 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(4, 11), "1", false))1200 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(5, 3), "--instance-type", false))1201 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(5, 19), "t1.micro", false))1202 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(6, 3), "--key-name", false))1203 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(6, 14), "MyKeyPair", false))1204 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(7, 3), "--security-groups", false))1205 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(7, 21), "my-sg", false))1206 ln.Push(cmd)1207 expected.Root = ln1208 parserTest("parser simple", `(1209 aws ec2 run-instances1210 --image-id ami-xxxxxxxx1211 --count 11212 --instance-type t1.micro1213 --key-name MyKeyPair1214 --security-groups my-sg1215)`, expected, t, true)1216}1217func TestParseMultilineCmdAssign(t *testing.T) {1218 expected := ast.NewTree("parser simple assign")1219 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))1220 cmd := ast.NewCommandNode(token.NewFileInfo(1, 10), "echo", true)1221 cmd.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 16), "hello world", true))1222 assign, err := ast.NewExecAssignNode(token.NewFileInfo(1, 0),1223 []*ast.NameNode{ast.NewNameNode(token.NewFileInfo(1, 0), "hello", nil)},1224 cmd,1225 )1226 if err != nil {1227 t.Error(err)1228 return1229 }1230 ln.Push(assign)1231 expected.Root = ln1232 parserTest("parser simple", `hello <= (echo "hello world")`, expected, t, true)1233}1234func TestMultiPipe(t *testing.T) {1235 expected := ast.NewTree("parser pipe")1236 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))1237 first := ast.NewCommandNode(token.NewFileInfo(1, 1), "echo", false)1238 first.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 7), "hello world", true))1239 second := ast.NewCommandNode(token.NewFileInfo(1, 22), "awk", false)1240 second.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 27), "{print $1}", true))1241 pipe := ast.NewPipeNode(token.NewFileInfo(1, 20), true)1242 pipe.AddCmd(first)1243 pipe.AddCmd(second)1244 ln.Push(pipe)1245 expected.Root = ln1246 parserTest("parser pipe", `(echo "hello world" | awk "{print $1}")`, expected, t, true)1247 // get longer stringify1248 expected = ast.NewTree("parser pipe")1249 ln = ast.NewBlockNode(token.NewFileInfo(1, 0))1250 first = ast.NewCommandNode(token.NewFileInfo(2, 1), "echo", false)1251 first.AddArg(ast.NewStringExpr(token.NewFileInfo(2, 7), "hello world", true))1252 second = ast.NewCommandNode(token.NewFileInfo(3, 1), "awk", false)1253 second.AddArg(ast.NewStringExpr(token.NewFileInfo(3, 6), "{print AAAAAAAAAAAAAAAAAAAAAA}", true))1254 pipe = ast.NewPipeNode(token.NewFileInfo(2, 20), true)1255 pipe.AddCmd(first)1256 pipe.AddCmd(second)1257 ln.Push(pipe)1258 expected.Root = ln1259 parserTest("parser pipe", `(1260 echo "hello world" |1261 awk "{print AAAAAAAAAAAAAAAAAAAAAA}"1262)`, expected, t, true)1263}1264func TestFnVariadic(t *testing.T) {1265 // root1266 expected := ast.NewTree("variadic")1267 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))1268 // fn1269 fn := ast.NewFnDeclNode(token.NewFileInfo(1, 3), "println")1270 fn.AddArg(ast.NewFnArgNode(token.NewFileInfo(1, 11), "fmt", false))1271 fn.AddArg(ast.NewFnArgNode(token.NewFileInfo(1, 16), "arg", true))1272 tree := ast.NewTree("fn body")1273 lnBody := ast.NewBlockNode(token.NewFileInfo(1, 0))1274 print := ast.NewFnInvNode(token.NewFileInfo(2, 2), "print")1275 print.AddArg(ast.NewConcatExpr(token.NewFileInfo(1, 7), []ast.Expr{1276 ast.NewVarExpr(token.NewFileInfo(2, 7), "$fmt"),1277 ast.NewStringExpr(token.NewFileInfo(2, 12), "\n", true),1278 }))1279 print.AddArg(ast.NewVarVariadicExpr(token.NewFileInfo(2, 12), "$arg", true))1280 lnBody.Push(print)1281 tree.Root = lnBody1282 fn.SetTree(tree)1283 // root1284 ln.Push(fn)1285 expected.Root = ln1286 parserTest("fn", `fn println(fmt, arg...) {1287 print($fmt+"\n", $arg...)1288}`, expected, t, true)1289}1290func TestParseValidDotdotdot(t *testing.T) {1291 for _, tc := range []string{1292 // things that should not break1293 "ls ...",...
parse_regression_test.go
Source:parse_regression_test.go
...8 ast.DebugCmp = true9}10func TestParseIssue22(t *testing.T) {11 expected := ast.NewTree("issue 22")12 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))13 fn := ast.NewFnDeclNode(token.NewFileInfo(1, 3), "gocd")14 fn.AddArg(ast.NewFnArgNode(token.NewFileInfo(1, 8), "path", false))15 fnTree := ast.NewTree("fn")16 fnBlock := ast.NewBlockNode(token.NewFileInfo(1, 0))17 ifDecl := ast.NewIfNode(token.NewFileInfo(2, 1))18 ifDecl.SetLvalue(ast.NewVarExpr(token.NewFileInfo(2, 4), "$path"))19 ifDecl.SetOp("==")20 ifDecl.SetRvalue(ast.NewStringExpr(token.NewFileInfo(2, 13), "", true))21 ifTree := ast.NewTree("if")22 ifBlock := ast.NewBlockNode(token.NewFileInfo(2, 1))23 cdNode := ast.NewCommandNode(token.NewFileInfo(3, 2), "cd", false)24 arg := ast.NewVarExpr(token.NewFileInfo(3, 5), "$GOPATH")25 cdNode.AddArg(arg)26 ifBlock.Push(cdNode)27 ifTree.Root = ifBlock28 ifDecl.SetIfTree(ifTree)29 elseTree := ast.NewTree("else")30 elseBlock := ast.NewBlockNode(token.NewFileInfo(4, 9))31 args := make([]ast.Expr, 3)32 args[0] = ast.NewVarExpr(token.NewFileInfo(5, 5), "$GOPATH")33 args[1] = ast.NewStringExpr(token.NewFileInfo(5, 12), "/src/", true)34 args[2] = ast.NewVarExpr(token.NewFileInfo(5, 20), "$path")35 cdNodeElse := ast.NewCommandNode(token.NewFileInfo(5, 2), "cd", false)36 carg := ast.NewConcatExpr(token.NewFileInfo(5, 5), args)37 cdNodeElse.AddArg(carg)38 elseBlock.Push(cdNodeElse)39 elseTree.Root = elseBlock40 ifDecl.SetElseTree(elseTree)41 fnBlock.Push(ifDecl)42 fnTree.Root = fnBlock43 fn.SetTree(fnTree)44 ln.Push(fn)45 expected.Root = ln46 parserTest("issue 22", `fn gocd(path) {47 if $path == "" {48 cd $GOPATH49 } else {50 cd $GOPATH+"/src/"+$path51 }52}`, expected, t, true)53}54func TestParseIssue38(t *testing.T) {55 expected := ast.NewTree("parse issue38")56 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))57 fnInv := ast.NewFnInvNode(token.NewFileInfo(1, 0), "cd")58 args := make([]ast.Expr, 3)59 args[0] = ast.NewVarExpr(token.NewFileInfo(1, 3), "$GOPATH")60 args[1] = ast.NewStringExpr(token.NewFileInfo(1, 12), "/src/", true)61 args[2] = ast.NewVarExpr(token.NewFileInfo(1, 19), "$path")62 arg := ast.NewConcatExpr(token.NewFileInfo(1, 3), args)63 fnInv.AddArg(arg)64 ln.Push(fnInv)65 expected.Root = ln66 parserTest("parse issue38", `cd($GOPATH+"/src/"+$path)`, expected, t, true)67}68func TestParseIssue43(t *testing.T) {69 content := `fn gpull() {70 branch <= git rev-parse --abbrev-ref HEAD | xargs echo -n71 git pull origin $branch72 refreshPrompt()73}`74 expected := ast.NewTree("parse issue 41")75 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))76 fnDecl := ast.NewFnDeclNode(token.NewFileInfo(1, 3), "gpull")77 fnTree := ast.NewTree("fn")78 fnBlock := ast.NewBlockNode(token.NewFileInfo(1, 0))79 gitRevParse := ast.NewCommandNode(token.NewFileInfo(2, 11), "git", false)80 gitRevParse.AddArg(ast.NewStringExpr(token.NewFileInfo(2, 15), "rev-parse", true))81 gitRevParse.AddArg(ast.NewStringExpr(token.NewFileInfo(2, 25), "--abbrev-ref", false))82 gitRevParse.AddArg(ast.NewStringExpr(token.NewFileInfo(2, 38), "HEAD", false))83 branchAssign, err := ast.NewExecAssignNode(token.NewFileInfo(2, 1), []*ast.NameNode{84 ast.NewNameNode(token.NewFileInfo(2, 1),85 "branch",86 nil,87 )}, gitRevParse)88 if err != nil {89 t.Error(err)90 return91 }92 xargs := ast.NewCommandNode(token.NewFileInfo(2, 45), "xargs", false)93 xargs.AddArg(ast.NewStringExpr(token.NewFileInfo(2, 51), "echo", false))94 xargs.AddArg(ast.NewStringExpr(token.NewFileInfo(2, 56), "-n", false))95 pipe := ast.NewPipeNode(token.NewFileInfo(2, 43), false)96 pipe.AddCmd(gitRevParse)97 pipe.AddCmd(xargs)98 branchAssign.SetCommand(pipe)99 fnBlock.Push(branchAssign)100 gitPull := ast.NewCommandNode(token.NewFileInfo(1, 0), "git", false)101 gitPull.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 0), "pull", false))102 gitPull.AddArg(ast.NewStringExpr(token.NewFileInfo(1, 0), "origin", false))103 gitPull.AddArg(ast.NewVarExpr(token.NewFileInfo(1, 0), "$branch"))104 fnBlock.Push(gitPull)105 fnInv := ast.NewFnInvNode(token.NewFileInfo(1, 0), "refreshPrompt")106 fnBlock.Push(fnInv)107 fnTree.Root = fnBlock108 fnDecl.SetTree(fnTree)109 ln.Push(fnDecl)110 expected.Root = ln111 parserTest("parse issue 41", content, expected, t, true)112}113func TestParseIssue68(t *testing.T) {114 expected := ast.NewTree("parse issue #68")115 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))116 catCmd := ast.NewCommandNode(token.NewFileInfo(1, 0), "cat", false)117 catArg := ast.NewStringExpr(token.NewFileInfo(1, 4), "PKGBUILD", false)118 catCmd.AddArg(catArg)119 sedCmd := ast.NewCommandNode(token.NewFileInfo(1, 15), "sed", false)120 sedArg := ast.NewStringExpr(token.NewFileInfo(1, 20), `s#\$pkgdir#/home/i4k/alt#g`, true)121 sedCmd.AddArg(sedArg)122 sedRedir := ast.NewRedirectNode(token.NewFileInfo(1, 49))123 sedRedirArg := ast.NewStringExpr(token.NewFileInfo(1, 51), "PKGBUILD2", false)124 sedRedir.SetLocation(sedRedirArg)125 sedCmd.AddRedirect(sedRedir)126 pipe := ast.NewPipeNode(token.NewFileInfo(1, 13), false)127 pipe.AddCmd(catCmd)128 pipe.AddCmd(sedCmd)129 ln.Push(pipe)130 expected.Root = ln131 parserTest("parse issue #68", `cat PKGBUILD | sed "s#\\$pkgdir#/home/i4k/alt#g" > PKGBUILD2`, expected, t, false)132}133func TestParseIssue69(t *testing.T) {134 expected := ast.NewTree("parse-issue-69")135 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))136 parts := make([]ast.Expr, 2)137 parts[0] = ast.NewVarExpr(token.NewFileInfo(1, 5), "$a")138 parts[1] = ast.NewStringExpr(token.NewFileInfo(1, 9), "b", true)139 concat := ast.NewConcatExpr(token.NewFileInfo(1, 5), parts)140 listValues := make([]ast.Expr, 1)141 listValues[0] = concat142 list := ast.NewListExpr(token.NewFileInfo(1, 4), listValues)143 assign := ast.NewSingleAssignNode(token.NewFileInfo(1, 0),144 ast.NewNameNode(token.NewFileInfo(1, 0), "a", nil), list,145 )146 ln.Push(assign)147 expected.Root = ln148 parserTest("parse-issue-69", `a = ($a+"b")`, expected, t, true)149}150func TestParseImportIssue94(t *testing.T) {151 expected := ast.NewTree("test import")152 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))153 importStmt := ast.NewImportNode(token.NewFileInfo(1, 0), ast.NewStringExpr(token.NewFileInfo(1, 7), "common", false))154 ln.Push(importStmt)155 expected.Root = ln156 parserTest("test import", "import common", expected, t, true)157}158func TestParseIssue108(t *testing.T) {159 // keywords cannot be used as command arguments160 expected := ast.NewTree("parse issue #108")161 ln := ast.NewBlockNode(token.NewFileInfo(1, 0))162 catCmd := ast.NewCommandNode(token.NewFileInfo(1, 0), "cat", false)163 catArg := ast.NewStringExpr(token.NewFileInfo(1, 4), "spec.ebnf", false)164 catCmd.AddArg(catArg)165 grepCmd := ast.NewCommandNode(token.NewFileInfo(1, 16), "grep", false)166 grepArg := ast.NewStringExpr(token.NewFileInfo(1, 21), `-i`, false)167 grepArg2 := ast.NewStringExpr(token.NewFileInfo(1, 24), "rfork", false)168 grepCmd.AddArg(grepArg)169 grepCmd.AddArg(grepArg2)170 pipe := ast.NewPipeNode(token.NewFileInfo(1, 14), false)171 pipe.AddCmd(catCmd)172 pipe.AddCmd(grepCmd)173 ln.Push(pipe)174 expected.Root = ln175 parserTest("parse issue #108", `cat spec.ebnf | grep -i rfork`, expected, t, false)176}177func TestParseIssue123(t *testing.T) {178 parser := NewParser("invalid cmd assignment", `IFS <= ("\n")`)179 _, err := parser.Parse()180 if err == nil {181 t.Errorf("Must fail...")182 return183 }184 expected := "invalid cmd assignment:1:9: Unexpected token STRING. Expecting IDENT or ARG"...
doc_test.go
Source:doc_test.go
...4 "github.com/madlambda/nash/ast"5 "github.com/madlambda/nash/token"6)7func Example_AssignmentNode() {8 one := ast.NewNameNode(token.NewFileInfo(1, 0), "one", nil)9 two := ast.NewNameNode(token.NewFileInfo(1, 4), "two", nil)10 value1 := ast.NewStringExpr(token.NewFileInfo(1, 8), "1", true)11 value2 := ast.NewStringExpr(token.NewFileInfo(1, 10), "2", true)12 assign := ast.NewAssignNode(token.NewFileInfo(1, 0),13 []*ast.NameNode{one, two},14 []ast.Expr{value1, value2},15 )16 fmt.Printf("%s", assign)17 // Output: one, two = "1", "2"18}19func Example_AssignmentNode_Single() {20 operatingSystems := ast.NewNameNode(token.NewFileInfo(1, 0), "operatingSystems", nil)21 values := []ast.Expr{22 ast.NewStringExpr(token.NewFileInfo(1, 19), "plan9 from bell labs", true),23 ast.NewStringExpr(token.NewFileInfo(2, 19), "unix", true),24 ast.NewStringExpr(token.NewFileInfo(3, 19), "linux", true),25 ast.NewStringExpr(token.NewFileInfo(4, 19), "oberon", true),26 ast.NewStringExpr(token.NewFileInfo(5, 19), "windows", true),27 }28 list := ast.NewListExpr(token.NewFileInfo(0, 18), values)29 assign := ast.NewSingleAssignNode(token.NewFileInfo(1, 0),30 operatingSystems,31 list,32 )33 fmt.Printf("%s", assign)34 // Output: operatingSystems = (35 // "plan9 from bell labs"36 // "unix"37 // "linux"38 // "oberon"39 // "windows"40 // )41}...
Info
Using AI Code Generation
1import (2func main() {3 f, err := parser.ParseFile(fset, "2.go", nil, parser.ParseComments)4 if err != nil {5 fmt.Println(err)6 }7 fmt.Println("File Name: ", f.Name.Name)8 fmt.Println("Number of comments: ", len(f.Comments))9 fmt.Println("Number of declarations: ", len(f.Decls))10}
Info
Using AI Code Generation
1import (2func main() {3 node, err := parser.ParseFile(fset, "1.go", nil, parser.ParseComments)4 if err != nil {5 panic(err)6 }7 ast.Print(fset, node)8}9import "fmt"10func main() {11 fmt.Println("Hello World!")12}
Info
Using AI Code Generation
1import (2func main() {3 import "fmt"4 func main() {5 fmt.Println("Hello, playground")6 }`7 f, err := parser.ParseFile(fset, "", src, 0)8 if err != nil {9 fmt.Println(err)10 }11 for _, s := range f.Imports {12 fmt.Println(s.Path.Value)13 }14}
Info
Using AI Code Generation
1import (2func main() {3 fset := token.NewFileSet()4 f, _ := parser.ParseFile(fset, "1.go", nil, parser.ParseComments)5 ast.Inspect(f, func(n ast.Node) bool {6 switch x := n.(type) {7 fmt.Println(x.Name)8 fmt.Println(x.Value)9 }10 })11}
Info
Using AI Code Generation
1import (2func main() {3 fset := token.NewFileSet()4 node, err := parser.ParseFile(fset, "1.go", nil, parser.ParseComments)5 if err != nil {6 fmt.Println(err)7 os.Exit(1)8 }9 ast.Print(fset, node)10}11import "fmt"12func main() {13 fmt.Println("Hello World")14}
Info
Using AI Code Generation
1import (2func main() {3 fset := token.NewFileSet()4 node, err := parser.ParseFile(fset, "1.go", nil, parser.ParseComments)5 if err != nil {6 log.Fatal(err)7 }8 ast.Inspect(node, func(n ast.Node) bool {9 switch x := n.(type) {10 log.Println(x.Name.Name)11 log.Println(x.Type.Params.List)12 log.Println(x.Type.Results.List)13 log.Println(x.Body.List)14 log.Println(x.Tok)15 log.Println(x.Lhs)16 log.Println(x.Rhs)17 log.Println(x.X)18 log.Println(x.Fun)19 log.Println(x.Args)20 log.Println(x.Name)21 log.Println(x.Value)22 log.Println(x.Op)23 log.Println(x.X)24 log.Println(x.Y)25 log.Println(x.Cond)26 log.Println(x.Body.List)27 log.Println(x.Else)28 log.Println(x.Results)29 log.Println(x.Names)30 log.Println(x.Type)31 log.Println(x.X)32 log.Println(x.Len)33 log.Println(x.Elt)34 log.Println(x.X)35 log.Println(x.Index)36 log.Println(x.Type)37 log.Println(x.Elts)38 log.Println(x.Key)39 log.Println(x.Value)40 log.Println(x.Key)41 log.Println(x.Value)42 log.Println(x.X)43 log.Println(x.Body.List)44 log.Println(x.Cond)45 log.Println(x.Body.List)46 log.Println(x.X)47 log.Println(x.Type)48 log.Println(x.X)49 log.Println(x.Sel)50 log.Println(x.Tag)51 log.Println(x.Body.List
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.
Get 100 minutes of automation test minutes FREE!!