blob: 9a0e52e1f1925efcf8b1ccf091349e2ab3297e47 [file] [edit]
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
#
# SPDX-License-Identifier: BSD-2-Clause
#
#
'''
An example of how to use the AST traversal functionality.
'''
from __future__ import absolute_import, division, print_function, \
unicode_literals
import os, sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../..')))
import camkes.ast as ast
import camkes.parser as parser
def basic_visit(parent, node, ignored):
sys.stdout.write(' %s\n' % type(node))
return ast.TRAVERSAL_RECURSE
def code_gen_enter(parent, node, state):
if isinstance(node, ast.Method):
if node.return_type is not None:
sys.stdout.write(node.return_type)
else:
sys.stdout.write('void ')
sys.stdout.write('%s(' % node.name)
state['infunction'] = True
state['firstparameter'] = True
return ast.TRAVERSAL_RECURSE
elif isinstance(node, ast.Parameter) and state.get('infunction', False):
if not state.get('firstparameter', True):
sys.stdout.write(', ')
sys.stdout.write('%s %s' % (node.type, node.name))
state['firstparameter'] = False
return ast.TRAVERSAL_CONTINUE
return ast.TRAVERSAL_RECURSE
def code_gen_exit(parent, node, ignored):
if isinstance(node, ast.Method):
sys.stdout.write(') {\n /* hello world */\n}\n')
return ast.TRAVERSAL_RECURSE
def code_constructor(parent, node, state):
if not isinstance(node, ast.Parameter) and not isinstance(node, ast.Type):
state['infunction'] = None
if isinstance(node, ast.Method):
if node.name not in state['functions']:
state['functions'][node.name] = []
state['infunction'] = node.name
return ast.TRAVERSAL_RECURSE
elif isinstance(node, ast.Parameter) or isinstance(node, ast.Type) and state['infunction'] is not None:
state['functions'][state['infunction']].append(node)
return ast.TRAVERSAL_CONTINUE
return ast.TRAVERSAL_RECURSE
def main():
if len(sys.argv) != 2:
sys.stderr.write('Usage: %s inputfile\n' % sys.argv[0])
return -1
with open(sys.argv[1], 'rt') as f:
s = f.read()
a = parser.parse_to_ast(s)
sys.stdout.write('Traverse the AST and print the types of nodes:\n')
ast.traverse(a, basic_visit, None, None)
sys.stdout.write('\nNow let\'s try some basic online code generation:\n')
ast.traverse(a, code_gen_enter, code_gen_exit, {})
sys.stdout.write('\nHow about the same offline:\n')
state = {
'functions':{},
'infunction':None,
}
ast.traverse(a, code_constructor, None, state)
for k, v in state['functions'].items():
if v[0] is not None:
sys.stdout.write(v[0])
else:
sys.stdout.write('void ')
sys.stdout.write('%(name)s(%(params)s) {\n /* hello world */\n}\n' % {
'name':k,
'params':', '.join(map(lambda x: '%s %s' % (x.type, x.name), v[1:])),
})
return 0
if __name__ == '__main__':
sys.exit(main())