| 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')
 |