github.com/cilki/sh@v2.6.4+incompatible/_js/testmain.js (about) 1 const assert = require('assert').strict 2 const stream = require('stream') 3 4 const sh = require('./index') 5 6 const syntax = sh.syntax 7 const parser = syntax.NewParser() 8 const printer = syntax.NewPrinter() 9 10 { 11 // parsing a simple program 12 const src = "echo 'foo'" 13 var f = parser.Parse(src, "src") 14 15 var stmts = f.StmtList.Stmts 16 assert.equal(stmts.length, 1) 17 18 var args = stmts[0].Cmd.Args 19 assert.equal(args.length, 2) 20 assert.equal(args[0].Parts.length, 1) 21 assert.equal(args[0].Parts[0].Value, "echo") 22 } 23 24 { 25 // accessing fields or methods creates separate objects 26 const src = "echo 'foo'" 27 var f = parser.Parse(src, "src") 28 29 assert.equal(f.StmtList.Stmts == f.StmtList.Stmts, false) 30 assert.equal(f.StmtList.Stmts === f.StmtList.Stmts, false) 31 var stmts = f.StmtList.Stmts 32 assert.equal(stmts == stmts, true) 33 assert.equal(stmts === stmts, true) 34 } 35 36 { 37 // parse errors 38 const src = "echo ${" 39 try { 40 parser.Parse(src, "src") 41 assert.fail("did not error") 42 } catch (err) { 43 } 44 } 45 46 { 47 // node types, operators, and positions 48 const src = "foo || bar" 49 var f = parser.Parse(src, "src") 50 51 var cmd = f.StmtList.Stmts[0].Cmd 52 assert.equal(syntax.NodeType(cmd), "BinaryCmd") 53 54 // TODO: see https://github.com/myitcv/gopherjs/issues/26 55 // assert.equal(syntax.String(cmd.Op), "||") 56 57 assert.equal(cmd.Pos().String(), "1:1") 58 assert.equal(cmd.OpPos.String(), "1:5") 59 assert.equal(cmd.OpPos.Line(), 1) 60 assert.equal(cmd.OpPos.Col(), 5) 61 assert.equal(cmd.OpPos.Offset(), 4) 62 } 63 64 { 65 // running Walk 66 const src = "foo bar" 67 var f = parser.Parse(src, "src") 68 69 var nilCount = 0 70 var nonNilCount = 0 71 var seenBar = false 72 var seenCall = false 73 syntax.Walk(f, function(node) { 74 var typ = syntax.NodeType(node) 75 if (node == null) { 76 nilCount++ 77 assert.equal(typ, "nil") 78 } else { 79 nonNilCount++ 80 if (node.Value == "bar") { 81 seenBar = true 82 } 83 assert.notEqual(typ, "nil") 84 } 85 if (typ == "CallExpr") { 86 seenCall = true 87 } 88 return true 89 }) 90 assert.equal(nonNilCount, 7) 91 assert.equal(nilCount, 7) 92 assert.equal(seenBar, true) 93 assert.equal(seenCall, true) 94 } 95 96 { 97 // printing 98 const src = "echo 'foo'" 99 var f = parser.Parse(src, "src") 100 101 var out = printer.Print(f) 102 assert.equal(out, "echo 'foo'\n") 103 } 104 105 { 106 // parser options 107 const parser = syntax.NewParser( 108 syntax.KeepComments, 109 syntax.Variant(syntax.LangMirBSDKorn), 110 syntax.StopAt("$$") 111 ) 112 const src = "echo ${|stmts;} # bar\n$$" 113 var f = parser.Parse(src, "src") 114 115 var out = printer.Print(f) 116 assert.equal(out, "echo ${|stmts;} # bar\n") 117 } 118 119 { 120 // parsing a readable stream 121 const src = new stream.Readable 122 src.push("echo foo") 123 src.push(null) 124 125 var f = parser.Parse(src, "src") 126 127 var cmd = f.StmtList.Stmts[0].Cmd 128 assert.equal(cmd.Args.length, 2) 129 } 130 131 { 132 // using the parser interactively 133 const inputs = [ 134 "foo\n", 135 "bar; baz\n", 136 "\n", 137 "'incom\n", 138 "plete'\n", 139 ] 140 const wantCallbacks = [ 141 {"count": 1, "incomplete": false}, 142 {"count": 2, "incomplete": false}, 143 {"count": 0, "incomplete": false}, 144 {"count": 0, "incomplete": true}, 145 {"count": 1, "incomplete": false}, 146 ] 147 var gotCallbacks = [] 148 149 const src = {"read": function(size) { 150 if (inputs.length == 0) { 151 if (gotCallbacks.length == 0) { 152 throw "did not see any callbacks before EOF" 153 } 154 return null // EOF 155 } 156 s = inputs[0] 157 inputs.shift() 158 return s 159 }} 160 161 parser.Interactive(src, function(stmts) { 162 gotCallbacks.push({ 163 "count": stmts.length, 164 "incomplete": parser.Incomplete(), 165 }) 166 return true 167 }) 168 assert.deepEqual(gotCallbacks, wantCallbacks) 169 }