Added Ast printer

pull/4814/head
Daniel Mensinger 6 years ago
parent ccad493e85
commit 46320bfba8
No known key found for this signature in database
GPG Key ID: 54DD94C131E277D4
  1. 4
      mesonbuild/ast/__init__.py
  2. 192
      mesonbuild/ast/printer.py
  3. 6
      mesonbuild/rewriter.py

@ -18,8 +18,10 @@
__all__ = [ __all__ = [
'AstInterpreter', 'AstInterpreter',
'RewriterInterpreter', 'RewriterInterpreter',
'AstVisitor' 'AstVisitor',
'AstPrinter'
] ]
from .interpreter import (AstInterpreter, RewriterInterpreter) from .interpreter import (AstInterpreter, RewriterInterpreter)
from .visitor import AstVisitor from .visitor import AstVisitor
from .printer import AstPrinter

@ -15,8 +15,196 @@
# This class contains the basic functionality needed to run any interpreter # This class contains the basic functionality needed to run any interpreter
# or an interpreter-based tool # or an interpreter-based tool
from .. import mparser
from . import AstVisitor from . import AstVisitor
arithmic_map = {
'add': '+',
'sub': '-',
'mod': '%',
'mul': '*',
'div': '/'
}
class AstPrinter(AstVisitor): class AstPrinter(AstVisitor):
def __init__(self): def __init__(self, indent: int = 2, arg_newline_cutoff: int = 5):
pass self.result = ''
self.indent = indent
self.arg_newline_cutoff = arg_newline_cutoff
self.level = 0
self.ci = ''
self.is_newline = True
def inc_indent(self):
self.level += self.indent
def dec_indent(self):
self.level -= self.indent
def append(self, data: str):
if self.is_newline:
self.result += ' ' * self.level
self.result += data
self.is_newline = False
def appendS(self, data: str):
if self.result[-1] not in [' ', '\n']:
data = ' ' + data
self.append(data + ' ')
def newline(self):
self.result += '\n'
self.is_newline = True
def visit_BooleanNode(self, node: mparser.BooleanNode):
self.append('true' if node.value else 'false')
def visit_IdNode(self, node: mparser.IdNode):
self.append(node.value)
def visit_NumberNode(self, node: mparser.NumberNode):
self.append(str(node.value))
def visit_StringNode(self, node: mparser.StringNode):
self.append("'" + node.value + "'")
def visit_ContinueNode(self, node: mparser.ContinueNode):
self.append('continue')
def visit_BreakNode(self, node: mparser.BreakNode):
self.append('break')
def visit_ArrayNode(self, node: mparser.ArrayNode):
self.append('[')
self.inc_indent()
node.args.accept(self)
self.dec_indent()
self.append(']')
def visit_DictNode(self, node: mparser.DictNode):
self.append('{')
self.inc_indent()
node.args.accept(self)
self.dec_indent()
self.append('}')
def visit_OrNode(self, node: mparser.OrNode):
node.left.accept(self)
self.appendS('or')
node.right.accept(self)
def visit_AndNode(self, node: mparser.AndNode):
node.left.accept(self)
self.appendS('and')
node.right.accept(self)
def visit_ComparisonNode(self, node: mparser.ComparisonNode):
node.left.accept(self)
self.appendS(mparser.comparison_map[node.ctype])
node.right.accept(self)
def visit_ArithmeticNode(self, node: mparser.ArithmeticNode):
node.left.accept(self)
self.appendS(arithmic_map[node.operation])
node.right.accept(self)
def visit_NotNode(self, node: mparser.NotNode):
self.appendS('not')
node.value.accept(self)
def visit_CodeBlockNode(self, node: mparser.CodeBlockNode):
for i in node.lines:
i.accept(self)
self.newline()
def visit_IndexNode(self, node: mparser.IndexNode):
self.append('[')
node.index.accept(self)
self.append(']')
def visit_MethodNode(self, node: mparser.MethodNode):
node.source_object.accept(self)
self.append('.' + node.name + '(')
self.inc_indent()
node.args.accept(self)
self.dec_indent()
self.append(')')
def visit_FunctionNode(self, node: mparser.FunctionNode):
self.append(node.func_name + '(')
self.inc_indent()
node.args.accept(self)
self.dec_indent()
self.append(')')
def visit_AssignmentNode(self, node: mparser.AssignmentNode):
self.append(node.var_name + ' = ')
node.value.accept(self)
def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode):
self.append(node.var_name + ' += ')
node.value.accept(self)
def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode):
varnames = [x.value for x in node.varnames]
self.appendS('foreach')
self.appendS(', '.join(varnames))
self.appendS(':')
node.items.accept(self)
self.newline()
self.inc_indent()
node.block.accept(self)
self.dec_indent()
self.append('endforeach')
def visit_IfClauseNode(self, node: mparser.IfClauseNode):
prefix = ''
for i in node.ifs:
self.appendS(prefix + 'if')
prefix = 'el'
i.accept(self)
if node.elseblock:
self.append('else')
self.indent()
self.inc_indent()
node.elseblock.accept(self)
self.dec_indent()
self.append('endif')
def visit_UMinusNode(self, node: mparser.UMinusNode):
self.appendS('-')
node.value.accept(self)
def visit_IfNode(self, node: mparser.IfNode):
node.condition.accept(self)
self.newline()
self.inc_indent()
node.block.accept(self)
self.dec_indent()
def visit_TernaryNode(self, node: mparser.TernaryNode):
node.condition.accept(self)
self.appendS('?')
node.trueblock.accept(self)
self.appendS(':')
node.falseblock.accept(self)
def visit_ArgumentNode(self, node: mparser.ArgumentNode):
break_args = True if (len(node.arguments) + len(node.kwargs)) > self.arg_newline_cutoff else False
for i in node.arguments + list(node.kwargs.values()):
if not isinstance(i, mparser.ElementaryNode):
break_args = True
if break_args:
self.newline()
for i in node.arguments:
i.accept(self)
self.append(',')
if break_args:
self.newline()
for key, val in node.kwargs.items():
self.append(key)
self.appendS(':')
val.accept(self)
self.append(',')
if break_args:
self.newline()

@ -23,7 +23,7 @@
# - move targets # - move targets
# - reindent? # - reindent?
from .ast import (AstInterpreter, AstVisitor) from .ast import (AstInterpreter, AstVisitor, AstPrinter)
from mesonbuild.mesonlib import MesonException from mesonbuild.mesonlib import MesonException
from mesonbuild import mlog from mesonbuild import mlog
import sys, traceback import sys, traceback
@ -35,7 +35,6 @@ def add_arguments(parser):
help='Print the parsed AST.') help='Print the parsed AST.')
def run(options): def run(options):
print('This tool is highly experimental, use with care.')
rewriter = AstInterpreter(options.sourcedir, '') rewriter = AstInterpreter(options.sourcedir, '')
try: try:
rewriter.load_root_meson_file() rewriter.load_root_meson_file()
@ -43,8 +42,9 @@ def run(options):
rewriter.parse_project() rewriter.parse_project()
rewriter.run() rewriter.run()
visitor = AstVisitor() visitor = AstPrinter()
rewriter.ast.accept(visitor) rewriter.ast.accept(visitor)
print(visitor.result)
except Exception as e: except Exception as e:
if isinstance(e, MesonException): if isinstance(e, MesonException):
mlog.exception(e) mlog.exception(e)

Loading…
Cancel
Save