Franck Pommereau

started to replace parser

# cast.py: extracted from cparse.py by Franck Pommereau (2018)
# ---------------------------------------------------------------
# cparse.py
#
# Atul Varma
# Python C Compiler - Parser
# $Id: cparse.py,v 1.2 2004/05/27 16:25:08 varmaa Exp $
# ---------------------------------------------------------------
# ---------------------------------------------------------------
# ABSTRACT SYNTAX TREE - NODES
# ---------------------------------------------------------------
class Node:
"Base class for all nodes on the abstract syntax tree."
def __init__ (self, lineno=0, colno=0, filename="<string>") :
self.lineno = lineno
self.colno = colno
self.filename = filename
def loc (self) :
return "%s:%s:%s" % (self.filename, self.lineno, self.colno)
def is_null(self):
"""Returns whether the node represents a null node."""
return 0
def is_const(self):
"""Returns whether the node is a constant numeric number
(e.g., "5")."""
return 0
def has_address(self):
"""Returns whether the node has an address (i.e., is a valid
lvalue)."""
return hasattr(self, "has_addr")
def set_has_address(self):
"""Tells the node that has an address (is an lvalue).
Ultimately, the address of the node should be placed in the
output_addr attribute."""
self.has_addr = 1
self.output_addr = 0
def calculate(self):
"""Calculates the constant numeric value of the node and
its subnodes, if one exists. For instance, if a node
corresponds to the expression "5+3", then this method
would return 8."""
return None
def accept(self, visitor):
"""Accept method for visitor classes (see cvisitor.py)."""
return self._accept(self.__class__, visitor)
def _accept(self, klass, visitor):
"""Accept implementation. This is actually a recursive
function that dynamically figures out which visitor method to
call. This is done by appending the class' name to 'v', so if
the node class is called MyNode, then this method tries
calling visitor.vMyNode(). If that node doesn't exist, then
it recursively attempts to call the visitor method
corresponding to the class' superclass (e.g.,
visitor.vNode())."""
visitor_method = getattr(visitor, "v%s" % klass.__name__, None)
if visitor_method == None:
bases = klass.__bases__
last = None
for i in bases:
last = self._accept(i, visitor)
return last
else:
return visitor_method(self)
class NullNode(Node):
"""A null node is like a null terminator for AST's."""
def __init__(self, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.type = 'void'
def is_null(self):
return 1
class ArrayExpression(Node):
"""This is an expression with array notation, like "a[5+b]"."""
def __init__(self, expr, index, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.expr = expr
self.index = index
class StringLiteral(Node):
"""A string literal, e.g. the string "Hello World" in
printf("Hello World")."""
def __init__(self, str, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self._str = str
self.type = PointerType(BaseType('char'))
def append_str(self, str):
self._str += str
def get_str(self):
return self._str
def get_sanitized_str(self):
"""Returns a 'sanitized' version of the string, converting
all carriage returns to '\n' symbols, etc."""
return self._str.replace('\n', '\\n')
class Id(Node):
"""An identifier, which can correspond to the name of
a function, variable, etc..."""
def __init__(self, name, lineno, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.name = name
class Const(Node):
"""A numeric constant (i.e., an integral literal), such as
the number 5."""
def __init__(self, value, type, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.value = value
self.type = type
def calculate(self):
return self.value
def is_const(self):
return 1
class Unaryop(Node):
"""Any generic unary operator. This is an abstract base class."""
def __init__(self, node, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.expr = node
class Negative(Unaryop):
"""A negative unary operator, e.g. '-5'."""
def calculate(self):
val = self.expr.calculate()
if val is not None:
return -val
return None
class Pointer(Unaryop):
"""A pointer dereference, e.g. '*a'."""
pass
class AddrOf(Unaryop):
"""An address-of operator, e.g. '&a'."""
pass
class Binop(Node):
"""Any binary operator, such as that for arithmetic operations
(+/-/*), assignment operations (=/+=/-=), and so forth."""
# List of assignment operators.
ASSIGN_OPS = ['=', '+=', '-=']
def __init__(self, left, right, op, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.left = left
self.right = right
self.op = op
def calculate(self):
left = self.left.calculate()
right = self.right.calculate()
if left is not None and right is not None:
return int(eval("%d %s %d" % (left, self.op, right)))
else:
return None
class IfStatement(Node):
"""An if/then/else statement."""
def __init__(self, expr, then_stmt, else_stmt, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.expr = expr
self.then_stmt = then_stmt
self.else_stmt = else_stmt
class BreakStatement(Node):
"""A break statement (used while in a loop structure to bust out
of it)."""
pass
class ContinueStatement(Node):
"""A continue statement (used while in a loop structure to bust
back to the beginning of it)."""
pass
class ReturnStatement(Node):
"""A return statement, used to exit a function and optionally
return a value."""
def __init__(self, expr, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.expr = expr
class ForLoop(Node):
"""A for loop."""
def __init__(self, begin_stmt, expr, end_stmt, stmt, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.expr = expr
self.stmt = stmt
self.begin_stmt = begin_stmt
self.end_stmt = end_stmt
class WhileLoop(Node):
"""A while loop."""
def __init__(self, expr, stmt, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.expr = expr
self.stmt = stmt
class NodeList(Node):
"""A list of nodes. This is an abstract base class."""
def __init__(self, node=None, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.nodes = []
if node is not None:
self.nodes.append(node)
def add(self, node):
self.nodes.append(node)
class ArgumentList(NodeList):
"""A list of arguments for a function expression. e.g., the list
'5,2,3' in 'a = my_func(5,2,3)'."""
pass
class ParamList(NodeList):
"""A list of parameters for a function prototype, e.g. the list
'int a, char b, char c' in 'int my_func(int a, char b, char c)'."""
def __init__(self, node=None, lineno=0, colno=0, filename="<string>"):
NodeList.__init__(self, node, lineno, colno, filename)
self.has_ellipsis = 0
class StatementList(NodeList):
"""Any list of statements. For instance, this can be the list of
statements in a function body."""
pass
class TranslationUnit(NodeList):
"""A list of nodes representing the program itself."""
pass
class DeclarationList(NodeList):
"""A list of variable declarations, such as the ones put
at the beginning of a compound statement (e.g., the beginning
of a function body)."""
pass
class FunctionExpression(Node):
"""An execution of a function, e.g. 'my_func(a,b,c)'."""
def __init__(self, function, arglist, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.function = function
self.arglist = arglist
class CompoundStatement(Node):
"""A compound statement, e.g. '{ int i; i += 1; }'."""
def __init__(self, declaration_list, statement_list, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.declaration_list = declaration_list
self.statement_list = statement_list
class FunctionDefn(Node):
"""A node representing a function definition (its declaration
and body)."""
def __init__(self, declaration, body, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
self.type = declaration.type
self.name = declaration.name
self.extern = declaration.extern
self.static = declaration.static
self.body = body
class Declaration(Node):
"""A node representing a declaration of a function or
variable."""
def __init__(self, name, type=None, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
if type is None:
type = NullNode()
self.extern = 0
self.static = 0
self.type = type
self.name = name
self.is_used = 0
def set_base_type(self, type):
if self.type.is_null():
self.type = type
else:
self.type.set_base_type(type)
def add_type(self, type):
type.set_base_type(self.type)
self.type = type
# ---------------------------------------------------------------
# ABSTRACT SYNTAX TREE - TYPE SYSTEM
# ---------------------------------------------------------------
class Type(Node):
"""A node representing the type of another node. For instance,
the Binop node representing '5 + a', where a is an int, will have
a Type node associated with it that represents the fact that
the result of the Binop is an int.
Types can also be nested, so that for instance you can have
a type like 'pointer(pointer(int))' which represents a
double-pointer to an int.
This is an abstract base class."""
def __init__(self, child=None, lineno=0, colno=0, filename="<string>"):
Node.__init__(self, lineno, colno, filename)
if child is None:
child = NullNode()
self.child = child
def set_base_type(self, type):
"""Set the base (innermost) type of a type. For instance,
calling this with a pointer(int) type on a pointer() type
will give you a pointer(pointer(int))."""
if self.child.is_null():
self.child = type
else:
self.child.set_base_type(type)
def get_string(self):
"""Return a string corresponding to the type, e.g.
'pointer(pointer(int))'."""
raise NotImplementedError()
def get_outer_string(self):
"""Return only the outermost type of a type. e.g.,
calling this on a pointer(pointer(int)) type will
return 'pointer'."""
raise NotImplementedError()
def is_function(self):
"""Returns whether or not this type represents a
function."""
return 0
class BaseType(Type):
"""A base type representing ints, chars, etc..."""
def __init__(self, type_str, child=None, lineno=0, colno=0, filename="<string>"):
Type.__init__(self, child, lineno, colno, filename)
self.type_str = type_str
def get_string(self):
return self.type_str
def get_outer_string(self):
return self.type_str
class FunctionType(Type):
"""A type representing a function (for function prototypes and
function calls)."""
def __init__(self, params=None, child=None, lineno=0, colno=0, filename="<string>"):
Type.__init__(self, child, lineno, colno, filename)
if (params == None):
params = NullNode()
self.params = params
def get_string(self):
param_str = ""
for param in self.params.nodes:
param_str += "," + param.type.get_string()
return "function(%s)->%s" % (param_str[1:], self.child.get_string())
def get_outer_string(self):
return 'function'
def is_function(self):
return 1
def get_return_type(self):
"""Returns the return type of the function. Internally,
this is stored as the nested type within the function."""
return self.child
def get_params(self):
"""Returns the list of parameters for the function."""
return self.params
class PointerType(Type):
"""A type representing a pointer to another (nested) type."""
def get_string(self):
return "pointer(%s)" % self.child.get_string()
def get_outer_string(self):
return 'pointer'
......@@ -10,130 +10,8 @@
import ply.yacc as yacc
from .clex import tokens
# ---------------------------------------------------------------
# ABSTRACT SYNTAX TREE - NODES
# ---------------------------------------------------------------
class Node:
"Base class for all nodes on the abstract syntax tree."
def is_null(self):
"""Returns whether the node represents a null node."""
return 0
def is_const(self):
"""Returns whether the node is a constant numeric number
(e.g., "5")."""
return 0
def has_address(self):
"""Returns whether the node has an address (i.e., is a valid
lvalue)."""
return hasattr(self, "has_addr")
def set_has_address(self):
"""Tells the node that has an address (is an lvalue).
Ultimately, the address of the node should be placed in the
output_addr attribute."""
self.has_addr = 1
self.output_addr = 0
def calculate(self):
"""Calculates the constant numeric value of the node and
its subnodes, if one exists. For instance, if a node
corresponds to the expression "5+3", then this method
would return 8."""
return None
def accept(self, visitor):
"""Accept method for visitor classes (see cvisitor.py)."""
return self._accept(self.__class__, visitor)
def _accept(self, klass, visitor):
"""Accept implementation. This is actually a recursive
function that dynamically figures out which visitor method to
call. This is done by appending the class' name to 'v', so if
the node class is called MyNode, then this method tries
calling visitor.vMyNode(). If that node doesn't exist, then
it recursively attempts to call the visitor method
corresponding to the class' superclass (e.g.,
visitor.vNode())."""
visitor_method = getattr(visitor, "v%s" % klass.__name__, None)
if visitor_method == None:
bases = klass.__bases__
last = None
for i in bases:
last = self._accept(i, visitor)
return last
else:
return visitor_method(self)
class NullNode(Node):
"""A null node is like a null terminator for AST's."""
def __init__(self):
self.type = 'void'
def is_null(self):
return 1
class ArrayExpression(Node):
"""This is an expression with array notation, like "a[5+b]"."""
def __init__(self, expr, index):
self.expr = expr
self.index = index
class StringLiteral(Node):
"""A string literal, e.g. the string "Hello World" in
printf("Hello World")."""
def __init__(self, str):
self._str = str
self.type = PointerType(BaseType('char'))
def append_str(self, str):
self._str += str
def get_str(self):
return self._str
def get_sanitized_str(self):
"""Returns a 'sanitized' version of the string, converting
all carriage returns to '\n' symbols, etc."""
return self._str.replace('\n', '\\n')
class Id(Node):
"""An identifier, which can correspond to the name of
a function, variable, etc..."""
def __init__(self, name, lineno):
self.name = name
self.lineno = lineno
class Const(Node):
"""A numeric constant (i.e., an integral literal), such as
the number 5."""
def __init__(self, value, type):
self.value = value
self.type = type
def calculate(self):
return self.value
def is_const(self):
return 1
from .clex import tokens # needed by yacc.yacc()
from .cast import * # the content of cast.py was originally here
def _get_calculated(node):
"""Attempts to calculate the numeric value of the expression,
......@@ -142,296 +20,12 @@ def _get_calculated(node):
this function just returns the node unmodified."""
result = node.calculate()
if result != None:
if result is not None:
result = int(result)
return Const(result, BaseType('int'))
else:
return node
class Unaryop(Node):
"""Any generic unary operator. This is an abstract base class."""
def __init__(self, node):
self.expr = node
class Negative(Unaryop):
"""A negative unary operator, e.g. '-5'."""
def calculate(self):
val = self.expr.calculate()
if val != None:
return -val
return None
class Pointer(Unaryop):
"""A pointer dereference, e.g. '*a'."""
pass
class AddrOf(Unaryop):
"""An address-of operator, e.g. '&a'."""
pass
class Binop(Node):
"""Any binary operator, such as that for arithmetic operations
(+/-/*), assignment operations (=/+=/-=), and so forth."""
# List of assignment operators.
ASSIGN_OPS = ['=', '+=', '-=']
def __init__(self, left, right, op):
self.left = left
self.right = right
self.op = op
def calculate(self):
left = self.left.calculate()
right = self.right.calculate()
if left != None and right != None:
return int(eval("%d %s %d" % (left, self.op, right)))
else:
return None
class IfStatement(Node):
"""An if/then/else statement."""
def __init__(self, expr, then_stmt, else_stmt):
self.expr = expr
self.then_stmt = then_stmt
self.else_stmt = else_stmt
class BreakStatement(Node):
"""A break statement (used while in a loop structure to bust out
of it)."""
pass
class ContinueStatement(Node):
"""A continue statement (used while in a loop structure to bust
back to the beginning of it)."""
pass
class ReturnStatement(Node):
"""A return statement, used to exit a function and optionally
return a value."""
def __init__(self, expr):
self.expr = expr
class ForLoop(Node):
"""A for loop."""
def __init__(self, begin_stmt, expr, end_stmt, stmt):
self.expr = expr
self.stmt = stmt
self.begin_stmt = begin_stmt
self.end_stmt = end_stmt
class WhileLoop(Node):
"""A while loop."""
def __init__(self, expr, stmt):
self.expr = expr
self.stmt = stmt
class NodeList(Node):
"""A list of nodes. This is an abstract base class."""
def __init__(self, node=None):
self.nodes = []
if node != None:
self.nodes.append(node)
def add(self, node):
self.nodes.append(node)
class ArgumentList(NodeList):
"""A list of arguments for a function expression. e.g., the list
'5,2,3' in 'a = my_func(5,2,3)'."""
pass
class ParamList(NodeList):
"""A list of parameters for a function prototype, e.g. the list
'int a, char b, char c' in 'int my_func(int a, char b, char c)'."""
def __init__(self, node=None):
NodeList.__init__(self, node)
self.has_ellipsis = 0
class StatementList(NodeList):
"""Any list of statements. For instance, this can be the list of
statements in a function body."""
pass
class TranslationUnit(NodeList):
"""A list of nodes representing the program itself."""
pass
class DeclarationList(NodeList):
"""A list of variable declarations, such as the ones put
at the beginning of a compound statement (e.g., the beginning
of a function body)."""
pass
class FunctionExpression(Node):
"""An execution of a function, e.g. 'my_func(a,b,c)'."""
def __init__(self, function, arglist):
self.function = function
self.arglist = arglist
class CompoundStatement(Node):
"""A compound statement, e.g. '{ int i; i += 1; }'."""
def __init__(self, declaration_list, statement_list):
self.declaration_list = declaration_list
self.statement_list = statement_list
class FunctionDefn(Node):
"""A node representing a function definition (its declaration
and body)."""
def __init__(self, declaration, body):
self.type = declaration.type
self.name = declaration.name
self.extern = declaration.extern
self.static = declaration.static
self.body = body
class Declaration(Node):
"""A node representing a declaration of a function or
variable."""
def __init__(self, name, type=None):
if type == None:
type = NullNode()
self.extern = 0
self.static = 0
self.type = type
self.name = name
self.is_used = 0
def set_base_type(self, type):
if self.type.is_null():
self.type = type
else:
self.type.set_base_type(type)
def add_type(self, type):
type.set_base_type(self.type)
self.type = type
# ---------------------------------------------------------------
# ABSTRACT SYNTAX TREE - TYPE SYSTEM
# ---------------------------------------------------------------
class Type(Node):
"""A node representing the type of another node. For instance,
the Binop node representing '5 + a', where a is an int, will have
a Type node associated with it that represents the fact that
the result of the Binop is an int.
Types can also be nested, so that for instance you can have
a type like 'pointer(pointer(int))' which represents a
double-pointer to an int.
This is an abstract base class."""
def __init__(self, child=None):
if child == None:
child = NullNode()
self.child = child
def set_base_type(self, type):
"""Set the base (innermost) type of a type. For instance,
calling this with a pointer(int) type on a pointer() type
will give you a pointer(pointer(int))."""
if self.child.is_null():
self.child = type
else:
self.child.set_base_type(type)
def get_string(self):
"""Return a string corresponding to the type, e.g.
'pointer(pointer(int))'."""
raise NotImplementedError()
def get_outer_string(self):
"""Return only the outermost type of a type. e.g.,
calling this on a pointer(pointer(int)) type will
return 'pointer'."""
raise NotImplementedError()
def is_function(self):
"""Returns whether or not this type represents a
function."""
return 0
class BaseType(Type):
"""A base type representing ints, chars, etc..."""
def __init__(self, type_str, child=None):
Type.__init__(self, child)
self.type_str = type_str
def get_string(self):
return self.type_str
def get_outer_string(self):
return self.type_str
class FunctionType(Type):
"""A type representing a function (for function prototypes and
function calls)."""
def __init__(self, params=None, child=None):
Type.__init__(self, child)
if (params == None):
params = NullNode()
self.params = params
def get_string(self):
param_str = ""
for param in self.params.nodes:
param_str += "," + param.type.get_string()
return "function(%s)->%s" % (param_str[1:], self.child.get_string())
def get_outer_string(self):
return 'function'
def is_function(self):
return 1
def get_return_type(self):
"""Returns the return type of the function. Internally,
this is stored as the nested type within the function."""
return self.child
def get_params(self):
"""Returns the list of parameters for the function."""
return self.params
class PointerType(Type):
"""A type representing a pointer to another (nested) type."""
def get_string(self):
return "pointer(%s)" % self.child.get_string()
def get_outer_string(self):
return 'pointer'
# ---------------------------------------------------------------
# PARSER GRAMMAR / AST CONSTRUCTION
#
......
......@@ -177,7 +177,14 @@ class CodeGenVisitor (Visitor) :
def concat (cls, outfile, chunks) :
outfile.write("# Generated by cct\n"
"# Franck Pommereau (2018)\n"
"# Adapted from Atul Varma's c.py (Spring 2004)\n")
"# Adapted from Atul Varma's c.py (Spring 2004)\n\n")
outfile.write("#\n"
"# on computer start: call main and halt\n"
"#\n\n"
"IRQ0:\n"
" set R9 @main\n"
" call R9\n"
" halt\n")
for c in chunks :
s = c.curr_str.getvalue()
if s.strip() :
......@@ -194,13 +201,6 @@ class CodeGenVisitor (Visitor) :
outfile.write("\n#\n# string literals from file %r\n#\n\n"
% c.path)
outfile.write(s)
outfile.write("\n#\n"
"# call main\n"
"#\n\n"
"IRQ0:\n"
" set R9 @main\n"
" call R9\n"
" halt\n")
def _calc_function_var_addrs(self, symtab, last_fp_loc):
self._calc_function_arg_addrs(symtab)
......@@ -353,7 +353,7 @@ class CodeGenVisitor (Visitor) :
label_str = "_LC%d" % self.__str_literal_label
self.str_literal_dict[str] = label_str
str = str.replace('\n', '\\12')
str = str.replace('\n', '\\n')
self.str_literal_str.write("""%s:\n str "%s\\0"\n""" % (label_str, str))
self.__class__.__str_literal_label += 1
return label_str
......
......@@ -340,11 +340,9 @@ class SymtabVisitor(Visitor):
# TODO: might be best to just move this to the code
# generation phase, since this doesn't have anything to
# do with symbol table generation.
param_num = 0
for param in node.nodes:
for param_num, param in enumerate(node.nodes):
param.accept(self)
param.param_num = param_num
param_num += 1
def vTranslationUnit(self, node):
self.root_symtab = Symtab()
......
import pycparser
from . import cast
def _coord (node) :
if node.coord is not None :
return {"lineno" : node.coord.line,
"colno" : node.coord.column - 1,
"filename" : node.coord.file}
else :
return {}
class ast2ast (object) :
def __call__ (self, node) :
return getattr(self, "v" + node.__class__.__name__)(node)
# # This is the top of the AST, representing a single C file (a
# # translation unit in K&R jargon). It contains a list of
# # "external-declaration"s, which is either declarations (Decl),
# # Typedef or function definitions (FuncDef).
# #
# FileAST: [ext**]
def vFileAST (self, node) :
ret = cast.TranslationUnit(None, **_coord(node))
for _, child in node.children() :
ret.add(self(child))
return ret
# # name: the variable being declared
# # quals: list of qualifiers (const, volatile)
# # funcspec: list function specifiers (i.e. inline in C99)
# # storage: list of storage specifiers (extern, register, etc.)
# # type: declaration type (probably nested with all the modifiers)
# # init: initialization value, or None
# # bitsize: bit field size, or None
# #
# Decl: [name, quals, storage, funcspec, type*, init*, bitsize*]
def vDecl (self, node) :
typ = self(node.type)
ret = cast.Declaration(node.name, typ, **_coord(node))
ret.extern = "extern" in node.storage
ret.static = "static" in node.quals
return ret
# # A typedef declaration.
# # Very similar to Decl, but without some attributes
# #
# Typedef: [name, quals, storage, type*]
def vTypedef (self, node) :
raise NotImplementedError("typdef")
# # type <decl>(args)
# #
# FuncDecl: [args*, type*]
def vFuncDecl (self, node) :
return cast.FunctionType(self(node.args), self(node.type))
# # a list of comma separated function parameter declarations
# #
# ParamList: [params**]
def vParamList (self, node) :
pass
# # A base type declaration
# #
# TypeDecl: [declname, quals, type*]
def vTypeDecl (self, node) :
pass
# # Function definition: a declarator for the function name and
# # a body, which is a compound statement.
# # There's an optional list of parameter declarations for old
# # K&R-style definitions
# #
# FuncDef: [decl*, param_decls**, body*]
def vFuncDef (self, node) :
pass
# # ArrayDecl is a nested declaration of an array with the given type.
# # dim: the dimension (for example, constant 42)
# # dim_quals: list of dimension qualifiers, to support C99's allowing 'const'
# # and 'static' within the array dimension in function declarations.
# ArrayDecl: [type*, dim*, dim_quals]
# ArrayRef: [name*, subscript*]
# # op: =, +=, /= etc.
# #
# Assignment: [op, lvalue*, rvalue*]
# BinaryOp: [op, left*, right*]
# Break: []
# Case: [expr*, stmts**]
# Cast: [to_type*, expr*]
# # Compound statement in C99 is a list of block items (declarations or
# # statements).
# #
# Compound: [block_items**]
# # Compound literal (anonymous aggregate) for C99.
# # (type-name) {initializer_list}
# # type: the typename
# # init: InitList for the initializer list
# #
# CompoundLiteral: [type*, init*]
# # type: int, char, float, etc. see CLexer for constant token types
# #
# Constant: [type, value]
# Continue: []
# DeclList: [decls**]
# Default: [stmts**]
# DoWhile: [cond*, stmt*]
# # Represents the ellipsis (...) parameter in a function
# # declaration
# #
# EllipsisParam: []
# # An empty statement (a semicolon ';' on its own)
# #
# EmptyStatement: []
# # Enumeration type specifier
# # name: an optional ID
# # values: an EnumeratorList
# #
# Enum: [name, values*]
# # A name/value pair for enumeration values
# #
# Enumerator: [name, value*]
# # A list of enumerators
# #
# EnumeratorList: [enumerators**]
# # A list of expressions separated by the comma operator.
# #
# ExprList: [exprs**]
# # for (init; cond; next) stmt
# #
# For: [init*, cond*, next*, stmt*]
# # name: Id
# # args: ExprList
# #
# FuncCall: [name*, args*]
# Goto: [name]
# ID: [name]
# # Holder for types that are a simple identifier (e.g. the built
# # ins void, char etc. and typedef-defined types)
# #
# IdentifierType: [names]
# If: [cond*, iftrue*, iffalse*]
# # An initialization list used for compound literals.
# #
# InitList: [exprs**]
# Label: [name, stmt*]
# # A named initializer for C99.
# # The name of a NamedInitializer is a sequence of Nodes, because
# # names can be hierarchical and contain constant expressions.
# #
# NamedInitializer: [name**, expr*]
# PtrDecl: [quals, type*]
# Return: [expr*]
# # name: struct tag name
# # decls: declaration of members
# #
# Struct: [name, decls**]
# # type: . or ->
# # name.field or name->field
# #
# StructRef: [name*, type, field*]
# Switch: [cond*, stmt*]
# # cond ? iftrue : iffalse
# #
# TernaryOp: [cond*, iftrue*, iffalse*]
# Typename: [name, quals, type*]
# UnaryOp: [op, expr*]
# # name: union tag name
# # decls: declaration of members
# #
# Union: [name, decls**]
# While: [cond*, stmt*]
# Pragma: [string]
def parse (path, *cpp_args) :
ast = pycparser.parse_file(path, use_cpp=True, cpp_args=list(cpp_args))
return ast2ast()(ast)
if __name__ == "__main__" :
tree = parse(",test.c", "-DTTC")