Tree Library
The AST tree library, in lib/astlib.c, is used in transform mode to perform tree rewriting, although some of them may be useful in nontransform mode.
ast_append
void ast_append(a,b). Add b to the end of a’s sibling list. Appending a
NULL pointer is illegal.
*ast_bottom
AST *ast_bottom(a). Find the bottom of a’s child list (going straight down).
*ast_cut_between
AST *ast_cut_between(a,b). Unlink all siblings between a and b and return a pointer to the first element of the sibling list that was unlinked. Basically, all this routine does is to make a point to b and make sure that the tail of the sibling list, which was unlinked, does not point to b. The routine ensures that a and b are (perhaps indirectly) connected to start with.
ast_insert_after
void ast_insert_after(a,b). Add subtree b immediately after a as its sibling. If b is a sibling list at its top level, then the last sibling of b points to the previous right sibling of a.Inserting a NULL pointer has no effect.
*ast_find_all
AST *ast_find_all(t, u, cursor). Find all occurrences of u in t. cursor (a pointer to an AST pointer) must be initialized to t. It eventually returns NULL when no more occurrences of u are found. This function is useful for iterating over every occurrence of a particular subtree. For example,
/* find all scalar assignments withing a statement list */ AST *scalar_assign = #( #[Assign], #[Var] );
AST *cursor = statement_list;
while ((p=ast_find_all(statement_list, scalar_assign, &cursor))) {
/* perform an operation on ’p’ */ }
where ast_node() (the function invoked by references to #[]) is assumed to take a single argument—a token type—and assignments are structured as:
Assign
This function does not seem to work if you make nested calls to it; i.e., a loop containing an ast_find_all() which contains another call to
ast_find_all().
ast_free
void ast_free(t). Recursively walk t, freeing all the nodes in a depth-first order. This is perhaps not very useful because more than a free() may be required to properly destroy a node.
*ast_make
AST *ast_ make(root, child1, ..., childn, NULL). Create a tree
with root as the root of the specified n children. If root is NULL, then a sibling list is constructed. If childi is a list of sibling, then childi+1 will be attached to the last sibling of childi. Any NULL childi results in childi-1 being the last sibling. The root must not have children to begin with.
A shorthand can be used in a description read by SORCERER:
#(root, child_1, ..., child_n) } ast_match
int ast_match(t,u). Returns true if t and u are the same (the trees have the same tree structure and tokenSORAST fields); else it returns false. If both trees are NULL, true is returned.
ast_match_partial
int ast_match_partial(t,u). Returns true if u matches t (beginning at root), but u can be smaller than t (i.e., a subtree of t).
ast_nsiblings
int ast_nsiblings(t). Returns the number of siblings of t.
ast_scan
int ast_scan(template, t, labelptr1, ..., labelptrn). This
function is analogous to scanf. It tries to match tree t against template and return the number of labels that were successfully mapped. The template is a string consisting of a SORCERER tree description with an optional set of node labels. For every label specified in template, the address of a SORAST pointer must be passed. Upon return from ast_scan(), the pointers will point to the requested nodes in t. This function can only be conveniently used from within a SORCERER description file and requires the use of the #tokdefs directive; it can be used in nontransform mode. Consider the following example.
n = ast_scan("#( %1:A %2:B %3:C )", t, &x, &y, &z);
which SORCERER converts to before the call to ast_scan()}:
n = ast_scan("#( %1:7 %2:8 %3:9 )", t, &x, &y, &z);
where the token types of A, B, and C are 7, 8, and 9, respectively. After the call, pointers x, y, and z will point to the root, the first child and the second child, respectively; n will be 3.
C Programming Interface
The order of label specification in template is not significant.
*ast_sibling_index
AST *ast_sibling_index(t,i). Return a pointer to the ith sibling where the sibling to the right of t is i==2. A index of i==1, returns t.
*ast_tail
AST *ast_tail(a). Find the end of a’s sibling list and return a pointer to it.
*ast_to_slist
SList *ast_to_slist(t). Return a list containing the siblings of t. This can be useful for walking a list of subtrees without having to parse it. For example,
<<SList *stats;>> slist
: ( stat )* <<stats = ast_to_list(_root);>> ;
where _root is the argument passed to every function that points to the input tree node. In this case, the variable stats will be a list with an element (SORAST *) for each statement in the statement list.
*slist_to_ast
AST *slist_to_ast(list). Return a tree composed of the elements of
list with a sibling for each element in list.
List Library
The SORCERER list library, lib/sorlist.c, is a simple linked-list manager that makes lists of pointers. The pointer for a new list must be initialized to NULL as any non-empty list has a sentinel node whose elem field pointer is really a pointer to the last element.
*slist_iterate
void *slist_iterate(list,cursor). Iterate over a list of elements in
list; return a pointer to a new element in list upon every call and NULL when no more are left. It can be used like this:
cursor = mylist;
while ( (p=slist_iterate(mylist,\&cursor)) ) { /* place with element p */
}
Lists can also be traversed with
SList *p;
for (p = list->next; p!=NULL; p=p->next) {
slist_add
void slist_add(list, e). Add element e to list . Any non-empty list has a sentinel node whose elem pointer is really a pointer to the last element. Elements are appended to the list. For example,
SList *Strings = NULL; list_add(&Strings, "hi"); list_add(&Strings, "there"); slist_free
void slist_free(list). Free a list (frees all of the nodes used to hold pointers to actual elements). It does not effect the elements tracked by the list.
Stack Library
The SORCERER stack library, lib/sstack.c, is a simple linked-list style stack of pointers. There is no sentinel node, and a pointer for a stack must be initialized to NULL
initially.
sstack_push
void sstack_push(st,e). Push element e on stack st where e can be a pointer to any object. For example,
SStack *st = NULL;
sstack_push(&st, "I push");
sstack_push(&st, "therefore, I’m a stack"); *sstack_pop
void *sstack_pop(st). Pop the top element off of stack st and return it. For example,
SStack *st = NULL; char *s;
sstack_push(&st, "over the edge"); s = sstack_pop(&st);
printf("%s\n", s);
should print "over the edge".
Integer Stack Library
The SORCERER SIntStack library, lib/sintstack.c, is a simple array-based stack of integers. Stacks of integers are common (such as saving the scope/level of programming language); hence, we have constructed a stack which is much easier to use and faster than the normal stack routines. Overflow and underflow conditions are trapped.
*sint_newstack
SIntStack *sint_newstack(size). Make a new stack with a maximum depth of size and return a pointer to it.
C Programming Interface
sint_freestack
void sint_freestack(SIntStack *st). Destroys a stack created by
sint_newstack().
sint_push
void sint_push(st, i). Push integer i onto stack st. For example,
SIntStack *st = sint_newstack(100); sint_push(st, 42);
sint_push(st, 3); sint_pop
int sint_pop(st). Pop the top integer off the stack and return it.
SIntStack *st = sint_newstack(10); sint_push(st, 3);
printf("%d\n", sint_pop(st));
would print "3".
sint_stacksize
int sint_stacksize(st). Returns the number of integers currently on the stack.
sint_stackreset
void sint_stackreset(st). Remove all integers from the stack.
sint_stackempty
int sint_stackempty(st). Returns true if there are no integers on stack st.
sint_top
int sint_top(st). Return the top integer on the stack without affecting the state of the stack.