#ifndef PARSE_TREE_H #define PARSE_TREE_H /*********** Data Structures ***********/ /* A token is-a int, what else? */ typedef int token_type; /* These are the kind of parse tree nodes; see struct node def below. */ typedef enum { MODULE_NODE, /* 0 */ BLOCK_NODE, /* 1 */ DECL_NODE, /* 2 */ STMT_NODE, /* 3 */ EXPR_LIST_NODE, /* 4 */ EXPR_NODE, /* 5 */ PROC_CALL_NODE, /* 6 */ TYPE_NODE, /* 7 */ ATOM_NODE /* 8 */ } kind_of_node; /* This is the def of pretty-printing info that will expand later on. */ typedef struct { char *stuff; } print_spec; /* This is the def of the kind of thing that attachments will point to. Again, this will expand later on. */ typedef int* thing; /* The type nodep is a pointer to a parsetree node. It's used *everywhere* so the name is short and sweet, contrary the author's normal tendency for mnemonic verbosity. */ typedef struct node *nodep; /* This is the def of a parse tree node. It's composed of two major parts: a fixed header and a union of components. The header contains the kind of node, its print image and a general attachment field. The components part varies for each different kind of node; in general it contains pointers to the node's children. Note that the field header.kind serves effectively as the union tag. */ struct node { /* Fixed Header Part: */ struct { kind_of_node kind; /* General kind such as stmt, operator */ token_type name; /* Specific name such as YIF, '+' */ print_spec print_image; /* This is for later on */ thing attachment; /* So is this */ int length; /* length of type */ } header; /* Variant Components Part: */ union { /* MODULE_NODE, for any one kind of module. * header.name = YMODULE for program module * YIMPLE for implementation module * YDEF for definition module */ struct { nodep name; nodep parms; /* For module parms extension */ nodep priority; nodep imports; nodep exports; nodep body; /* This is either a block or defs */ } module; /* BLOCK_NODE, for the bodies of modules and procs */ struct { nodep decls; nodep stmts; } block; /* DECL_NODE, for all types of decls */ struct { union { /* NULL -- Klaus allows these syntactically. */ nodep nulldecl; /* YCONST */ struct { nodep name; nodep expr; nodep next; } consta; /* YTYPE */ struct { nodep name; nodep type; nodep next; } type; /* YVAR */ struct { nodep vars; nodep type; nodep next; } var; /* YPROC */ struct { nodep name; /* empty if proc type */ nodep formals; nodep type; /* empty if not a function */ nodep body; /* empty if proc header or proc type */ } proc; /* Formal parm (tag = '(') */ struct { bool isvar; /* true if this is a var parm */ bool isarray; /* true if this is an open array*/ nodep vars; /* empty if parm in a proc type */ nodep type; } parm; /* NOTE: name tag is '(' */ /* Variant field (tag = YCASE) */ struct { /* a variant field */ nodep tagfield; nodep casefields; nodep elsefield; } variant; /* YMODULE */ nodep module; /* Just point to a module node */ /* YIMPORT */ struct { /* an import decl */ nodep from; nodep names; } import; /* YEXPORT */ struct { /* an export decl */ bool isqual; /* true if qualified */ nodep names; } export; } kind; nodep next; } decl; /* STMT_NODE, for an assignment stmt */ struct { union { /* NULL stmt */ int nullstmt; /* YASSMNT_OP */ struct { nodep var; nodep expr; } assmnt; /* YPROCEDURE */ nodep proccallstmt; /* ptr to a PROC_CALL_NODE It's done this way so next field can be handled uniformly for all stmts. */ /* YIF */ struct { nodep expr; nodep thenpart; nodep elsifparts; /* empty if no else */ nodep elsepart; /* empty if no else */ } ifstmt; /* YELSIF */ struct { nodep expr; nodep thenpart; } elsif; /* YCASE */ struct { nodep expr; nodep cases; nodep elsepart; /* empty if no else */ } casestmt; /* YOF */ /* a labeled stmtseq */ struct { nodep labellist; nodep stmtseq; } ofpart; /* YWHILE */ struct { nodep expr; nodep body; } whilestmt; /* YREPEAT */ struct { nodep body; nodep expr; } repeatstmt; /* YLOOP */ struct { nodep body; } loopstmt; /* YFOR */ struct { nodep var; nodep startexpr; nodep endexpr; nodep byexpr; nodep body; } forstmt; /* YWITH */ struct { nodep desig; nodep body; } withstmt; /* YRETURN */ nodep returnstmt; /* holds return expr, if any */ } kind; nodep next; } stmt; /* EXPR_LIST_NODE, for stringing together expr's without having to put * a frequently wasted next field in expr nodes themselves. */ struct { nodep expr; nodep next; } exprlist; /* EXPR_NODE, for both binary and unary operators */ struct { nodep left_operand; nodep right_operand; /* NULL if unary op */ } expr; /* PROC_CALL_NODE, for a proc call in either an expr or as a stmt. */ struct { nodep desig; nodep actuals; } proccall; /* TYPE_NODE, for a type structure */ union { /* NULL -- a forward ref to a not-yet resolved type. */ nodep resolved; /* Yident */ nodep name; /* a type ident, including qualident */ /* '(' enums ')' */ nodep enumidents; /* an enumeration type */ /* YDOTDOT */ struct { /* a subrange type */ nodep name; nodep lower; nodep upper; int upperbound, /* upper array bound */ lowerbound; /* lower array bound */ } subrange; /* YARRAY */ struct { /* an array type */ nodep bounds; nodep basetype; } arraytype; /* YRECORD */ nodep fields; /* a record type */ /* YCASE */ struct { /* a variant part */ nodep caselabels; nodep fields; } variant; /* YSET or YPOINTER */ nodep basetype; /* base type for a set or pointer */ /* YPROCEDURE */ nodep proctype; /* a procedure type */ } type; /* ATOM_NODE, for one or more atoms, where atom includes var, int, real (others later). Note that header.name is the tag for these guys */ struct { union { int integer; float real; char *text; char character; char *string; } val; int offset; /* this is used to set the offset of record fields */ nodep next; } atom; } components; }; /* end of struct node */ /*********** Prototypes ***********/ /*-*********************************************************************** Function: NewNode() Purpose: Create a new parse tree node Arguments: kind - the type of node name - a node-specific tag Returns: A ptr to the newly created node. ***********************************************************************-*/ nodep NewNode( kind_of_node kind, token_type name ); #endif PARSE_TREE_H