Skip to content
This repository was archived by the owner on Aug 27, 2018. It is now read-only.

Commit a7280a2

Browse files
authored
Merge pull request #127 from myitcv/syntax_viewer_fixes
examples/sites/syntaxviewer: fix handling of print error and properly print Pos in shell printer
2 parents 0caedd4 + a10f478 commit a7280a2

File tree

11 files changed

+321
-214
lines changed

11 files changed

+321
-214
lines changed

.vendor.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@
2424
./_vendor/src/honnef.co/go/js/xhr 00e3346113aed89b501ead4e863c7c3d04fa0c5b git@github.com:dominikh/go-js-xhr
2525
./_vendor/src/honnef.co/go/js/util 96b8dd9d16214b6cd9d8c8e84b3a375da4688108 git@github.com:dominikh/go-js-util
2626
./_vendor/src/honnef.co/go/js/dom 0a64a2db1425c1881d4ec762370250c65f44b85b git@github.com:dominikh/go-js-dom
27-
./_vendor/src/mvdan.cc/sh 0e64bc087f8341d164c07a5edba1e37417bd2df4 git@github.com:mvdan/sh
27+
./_vendor/src/mvdan.cc/sh 43f0b783abe67b568ff4fe4d0b84c44d73eac979 git@github.com:mvdan/sh
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
index.js*
2+
_js.js*
3+
*.log
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# mvdan-sh
2+
3+
This package is a JavaScript version of a shell package written in Go, available
4+
at https://github.com/mvdan/sh.
5+
6+
It is transpiled from Go to JS using GopherJS, available at
7+
https://github.com/gopherjs/gopherjs
8+
9+
Here is a simple usage example:
10+
11+
```
12+
const sh = require('mvdan-sh')
13+
const syntax = sh.syntax
14+
15+
var p = syntax.NewParser()
16+
17+
var src = "echo 'foo'"
18+
var f = p.Parse(src, "src.js")
19+
20+
var stmt = f.StmtList.Stmts[0]
21+
var args = stmt.Cmd.Args
22+
console.log(args[0])
23+
```

_vendor/src/mvdan.cc/sh/_js/build

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/sh
2+
3+
gopherjs build -o index.js || exit 1
4+
5+
node testmain.js || exit 1
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/gopherjs/gopherjs/js"
8+
9+
"mvdan.cc/sh/syntax"
10+
)
11+
12+
func main() {
13+
exps := js.Module.Get("exports")
14+
15+
exps.Set("syntax", map[string]interface{}{})
16+
17+
stx := exps.Get("syntax")
18+
stx.Set("NodeType", func(node syntax.Node) string {
19+
typ := fmt.Sprintf("%T", node)
20+
if i := strings.LastIndexAny(typ, "*.]"); i >= 0 {
21+
typ = typ[i+1:]
22+
}
23+
return typ
24+
})
25+
stx.Set("NewParser", func() *js.Object {
26+
p := syntax.NewParser()
27+
return js.MakeWrapper(jsParser{p})
28+
})
29+
stx.Set("Walk", syntax.Walk)
30+
}
31+
32+
func throw(v interface{}) {
33+
js.Global.Call("$throwRuntimeError", fmt.Sprint(v))
34+
}
35+
36+
type jsParser struct {
37+
*syntax.Parser
38+
}
39+
40+
func (p jsParser) Parse(src, name string) *js.Object {
41+
f, err := p.Parser.Parse(strings.NewReader(src), name)
42+
if err != nil {
43+
throw(err)
44+
}
45+
return js.MakeWrapper(f)
46+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "mvdan-sh",
3+
"version": "0.0.5",
4+
"description": "A shell parser and formatter (POSIX/Bash/mksh)",
5+
"main": "index.js",
6+
"repository": "https://github.com/mvdan/sh",
7+
"author": "Daniel Martí",
8+
"license": "BSD-3-Clause",
9+
"files": [
10+
"README.md",
11+
"index.js"
12+
],
13+
"keywords": [
14+
"shell",
15+
"bash",
16+
"sh",
17+
"parser",
18+
"ast",
19+
"syntax",
20+
"posix",
21+
"bash-parser"
22+
]
23+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
const assert = require('assert').strict
2+
3+
const sh = require('./index')
4+
5+
var syntax = sh.syntax
6+
var p = syntax.NewParser()
7+
8+
{
9+
// parsing a simple program
10+
var src = "echo 'foo'"
11+
var f = p.Parse(src, "src")
12+
13+
var stmts = f.StmtList.Stmts
14+
assert.strictEqual(stmts.length, 1)
15+
16+
var args = stmts[0].Cmd.Args
17+
assert.strictEqual(args.length, 2)
18+
assert.strictEqual(args[0].Parts.length, 1)
19+
assert.strictEqual(args[0].Parts[0].Value, "echo")
20+
}
21+
22+
{
23+
// accessing fields or methods creates separate objects
24+
var src = "echo 'foo'"
25+
var f = p.Parse(src, "src")
26+
27+
assert.strictEqual(f.StmtList.Stmts == f.StmtList.Stmts, false)
28+
assert.strictEqual(f.StmtList.Stmts === f.StmtList.Stmts, false)
29+
var stmts = f.StmtList.Stmts
30+
assert.strictEqual(stmts == stmts, true)
31+
assert.strictEqual(stmts === stmts, true)
32+
}
33+
34+
{
35+
// parse errors
36+
var src = "echo ${"
37+
try {
38+
var f = p.Parse(src, "src")
39+
assert.fail("did not error")
40+
} catch (err) {
41+
}
42+
}
43+
44+
{
45+
// getting the types of nodes
46+
var src = "echo 'foo'"
47+
var f = p.Parse(src, "src")
48+
49+
var cmd = f.StmtList.Stmts[0].Cmd
50+
assert.strictEqual(syntax.NodeType(cmd), "CallExpr")
51+
assert.strictEqual(syntax.NodeType(cmd.Args[0].Parts[0]), "Lit")
52+
}
53+
54+
{
55+
// running Walk
56+
var src = "foo bar"
57+
var f = p.Parse(src, "src")
58+
59+
var nilCount = 0
60+
var nonNilCount = 0
61+
var seenBar = false
62+
syntax.Walk(f, function(node) {
63+
if (node == null) {
64+
nilCount++
65+
} else {
66+
nonNilCount++
67+
if (node.Value == "bar") {
68+
seenBar = true
69+
}
70+
}
71+
return true
72+
})
73+
assert.strictEqual(nonNilCount, 7)
74+
assert.strictEqual(nilCount, 7)
75+
assert.strictEqual(seenBar, true)
76+
}

_vendor/src/mvdan.cc/sh/syntax/example_walk_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,54 @@ func ExampleWalk() {
2626
syntax.NewPrinter().Print(os.Stdout, f)
2727
// Output: echo $FOO "and $BAR"
2828
}
29+
30+
func ExampleDebugPrint() {
31+
in := strings.NewReader(`echo 'foo'`)
32+
f, err := syntax.NewParser().Parse(in, "")
33+
if err != nil {
34+
return
35+
}
36+
syntax.DebugPrint(os.Stdout, f)
37+
// Output:
38+
// *syntax.File {
39+
// . Name: ""
40+
// . StmtList: syntax.StmtList {
41+
// . . Stmts: []*syntax.Stmt (len = 1) {
42+
// . . . 0: *syntax.Stmt {
43+
// . . . . Comments: []syntax.Comment (len = 0) {}
44+
// . . . . Cmd: *syntax.CallExpr {
45+
// . . . . . Assigns: []*syntax.Assign (len = 0) {}
46+
// . . . . . Args: []*syntax.Word (len = 2) {
47+
// . . . . . . 0: *syntax.Word {
48+
// . . . . . . . Parts: []syntax.WordPart (len = 1) {
49+
// . . . . . . . . 0: *syntax.Lit {
50+
// . . . . . . . . . ValuePos: 1:1
51+
// . . . . . . . . . ValueEnd: 1:5
52+
// . . . . . . . . . Value: "echo"
53+
// . . . . . . . . }
54+
// . . . . . . . }
55+
// . . . . . . }
56+
// . . . . . . 1: *syntax.Word {
57+
// . . . . . . . Parts: []syntax.WordPart (len = 1) {
58+
// . . . . . . . . 0: *syntax.SglQuoted {
59+
// . . . . . . . . . Left: 1:6
60+
// . . . . . . . . . Right: 1:10
61+
// . . . . . . . . . Dollar: false
62+
// . . . . . . . . . Value: "foo"
63+
// . . . . . . . . }
64+
// . . . . . . . }
65+
// . . . . . . }
66+
// . . . . . }
67+
// . . . . }
68+
// . . . . Position: 1:1
69+
// . . . . Semicolon: 0:0
70+
// . . . . Negated: false
71+
// . . . . Background: false
72+
// . . . . Coprocess: false
73+
// . . . . Redirs: []*syntax.Redirect (len = 0) {}
74+
// . . . }
75+
// . . }
76+
// . . Last: []syntax.Comment (len = 0) {}
77+
// . }
78+
// }
79+
}

_vendor/src/mvdan.cc/sh/syntax/walk.go

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33

44
package syntax
55

6-
import "fmt"
6+
import (
7+
"fmt"
8+
"io"
9+
"reflect"
10+
)
711

812
func walkStmts(sl StmtList, f func(Node) bool) {
913
for _, s := range sl.Stmts {
@@ -219,3 +223,86 @@ func Walk(node Node, f func(Node) bool) {
219223

220224
f(nil)
221225
}
226+
227+
// DebugPrint prints the provided syntax tree, spanning multiple lines and with
228+
// indentation. Can be useful to investigate the content of an AST.
229+
func DebugPrint(w io.Writer, node Node) error {
230+
p := debugPrinter{out: w}
231+
p.print(reflect.ValueOf(node))
232+
return p.err
233+
}
234+
235+
type debugPrinter struct {
236+
out io.Writer
237+
level int
238+
err error
239+
}
240+
241+
func (p *debugPrinter) printf(format string, args ...interface{}) {
242+
_, err := fmt.Fprintf(p.out, format, args...)
243+
if err != nil && p.err == nil {
244+
p.err = err
245+
}
246+
}
247+
248+
func (p *debugPrinter) newline() {
249+
p.printf("\n")
250+
for i := 0; i < p.level; i++ {
251+
p.printf(". ")
252+
}
253+
}
254+
255+
func (p *debugPrinter) print(x reflect.Value) {
256+
switch x.Kind() {
257+
case reflect.Interface:
258+
if x.IsNil() {
259+
p.printf("nil")
260+
return
261+
}
262+
p.print(x.Elem())
263+
case reflect.Ptr:
264+
if x.IsNil() {
265+
p.printf("nil")
266+
return
267+
}
268+
p.printf("*")
269+
p.print(x.Elem())
270+
case reflect.Slice:
271+
p.printf("%s (len = %d) {", x.Type(), x.Len())
272+
if x.Len() > 0 {
273+
p.level++
274+
p.newline()
275+
for i := 0; i < x.Len(); i++ {
276+
p.printf("%d: ", i)
277+
p.print(x.Index(i))
278+
if i == x.Len()-1 {
279+
p.level--
280+
}
281+
p.newline()
282+
}
283+
}
284+
p.printf("}")
285+
286+
case reflect.Struct:
287+
switch v := x.Interface().(type) {
288+
case Pos:
289+
p.printf("%v:%v", v.Line(), v.Col())
290+
return
291+
}
292+
t := x.Type()
293+
p.printf("%s {", t)
294+
p.level++
295+
p.newline()
296+
for i := 0; i < t.NumField(); i++ {
297+
p.printf("%s: ", t.Field(i).Name)
298+
p.print(x.Field(i))
299+
if i == x.NumField()-1 {
300+
p.level--
301+
}
302+
p.newline()
303+
}
304+
p.printf("}")
305+
default:
306+
p.printf("%#v", x.Interface())
307+
}
308+
}

examples/sites/syntaxviewer/app.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,11 @@ func (a AppDef) handleEvent() {
152152
st.Ast = err.Error()
153153
return
154154
}
155-
fprint(b, f, nil)
155+
156+
if err := syntax.DebugPrint(b, f); err != nil {
157+
st.Ast = err.Error()
158+
return
159+
}
156160
}
157161

158162
st.Ast = b.String()

0 commit comments

Comments
 (0)