1 | #!/usr/bin/python
|
2 | """
|
3 | ast_lib.py
|
4 |
|
5 | Helpers for osh/osh.asdl
|
6 | """
|
7 |
|
8 | import sys
|
9 |
|
10 | from asdl import format as fmt
|
11 | from osh.meta import Id
|
12 |
|
13 |
|
14 | _ColoredString = fmt._ColoredString
|
15 | MakeTree = fmt.MakeTree
|
16 | _STRING_LITERAL = fmt._STRING_LITERAL
|
17 | _OTHER_TYPE = fmt._OTHER_TYPE
|
18 |
|
19 |
|
20 | def _AbbreviateToken(token, out):
|
21 | if token.id != Id.Lit_Chars:
|
22 | c = _ColoredString(str(token.id), _OTHER_TYPE)
|
23 | out.append(c)
|
24 |
|
25 | out.append(_ColoredString(token.val, _STRING_LITERAL))
|
26 |
|
27 |
|
28 | def _GetFieldNames(node):
|
29 | # Don't let the 'spids' field disable abbreviation
|
30 | return [n for n, _ in node.fields if n != 'spids']
|
31 |
|
32 |
|
33 | def AbbreviateNodes(obj, node):
|
34 | """
|
35 | Args:
|
36 | obj: py_meta.Obj to print
|
37 | node: homogeneous node after MakeTree prints it; can be mutated
|
38 | """
|
39 | if node.node_type == 'token':
|
40 | node.abbrev = True
|
41 | node.node_type = 'T'
|
42 | node.show_node_type = False
|
43 | node.left = '<'
|
44 | node.right = '>'
|
45 | _AbbreviateToken(obj, node.unnamed_fields)
|
46 |
|
47 | elif node.node_type == 'LiteralPart':
|
48 | node.abbrev = True
|
49 | node.node_type = 'L'
|
50 | node.show_node_type = False
|
51 |
|
52 | _AbbreviateToken(obj.token, node.unnamed_fields)
|
53 |
|
54 | elif node.node_type == 'SimpleVarSub':
|
55 | node.abbrev = True
|
56 | node.node_type = '$'
|
57 | _AbbreviateToken(obj.token, node.unnamed_fields)
|
58 |
|
59 | elif node.node_type == 'BracedVarSub':
|
60 | if _GetFieldNames(node) != ['token']:
|
61 | return # we have other fields to display; don't abbreviate
|
62 |
|
63 | node.abbrev = True
|
64 | node.node_type = '${'
|
65 | _AbbreviateToken(obj.token, node.unnamed_fields)
|
66 |
|
67 | elif node.node_type == 'DoubleQuotedPart':
|
68 | node.abbrev = True
|
69 | node.node_type = 'DQ'
|
70 |
|
71 | for part in obj.parts:
|
72 | node.unnamed_fields.append(MakeTree(part, AbbreviateNodes))
|
73 |
|
74 | # Only abbreviate 'foo', not $'foo\n'
|
75 | elif (node.node_type == 'SingleQuotedPart' and
|
76 | obj.left.id == Id.Left_SingleQuote):
|
77 | node.abbrev = True
|
78 | node.node_type = 'SQ'
|
79 |
|
80 | for token in obj.tokens:
|
81 | node.unnamed_fields.append(MakeTree(token, AbbreviateNodes))
|
82 |
|
83 | elif node.node_type == 'CompoundWord':
|
84 | node.abbrev = True
|
85 | node.node_type = 'W'
|
86 | node.show_node_type = False
|
87 | node.left = '{'
|
88 | node.right = '}'
|
89 |
|
90 | for part in obj.parts:
|
91 | node.unnamed_fields.append(MakeTree(part, AbbreviateNodes))
|
92 |
|
93 | elif node.node_type == 'SimpleCommand':
|
94 | if _GetFieldNames(node) != ['words']:
|
95 | return # we have other fields to display; don't abbreviate
|
96 |
|
97 | node.abbrev = True
|
98 | node.node_type = 'C'
|
99 |
|
100 | for w in obj.words:
|
101 | # Recursively call MakeTree here?
|
102 | # Well actually then the printer needs to recursively handle it
|
103 | node.unnamed_fields.append(MakeTree(w, AbbreviateNodes))
|
104 |
|
105 |
|
106 | def PrettyPrint(node, f=sys.stdout):
|
107 | ast_f = fmt.DetectConsoleOutput(f)
|
108 | tree = fmt.MakeTree(node, AbbreviateNodes)
|
109 | fmt.PrintTree(tree, ast_f)
|
110 | f.write('\n')
|