OILS / opy / _regtest / src / osh / ast_lib.py View on Github | oilshell.org

110 lines, 68 significant
1#!/usr/bin/python
2"""
3ast_lib.py
4
5Helpers for osh/osh.asdl
6"""
7
8import sys
9
10from asdl import format as fmt
11from osh.meta import Id
12
13
14_ColoredString = fmt._ColoredString
15MakeTree = fmt.MakeTree
16_STRING_LITERAL = fmt._STRING_LITERAL
17_OTHER_TYPE = fmt._OTHER_TYPE
18
19
20def _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
28def _GetFieldNames(node):
29 # Don't let the 'spids' field disable abbreviation
30 return [n for n, _ in node.fields if n != 'spids']
31
32
33def 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
106def 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')