git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@399 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Dave Beazley 2000-04-10 15:25:07 +00:00
commit b0da03b33f

View file

@ -1,9 +1,8 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* tree.c * tree.c
* *
* This file provides some general purpose functions for manipulating * This file provides some general purpose functions for walking through
* parse trees. Note: This is primarily a debugging module at this * parse trees.
* point. Maybe it will evolve into something else later.
* *
* Author(s) : David Beazley (beazley@cs.uchicago.edu) * Author(s) : David Beazley (beazley@cs.uchicago.edu)
* *
@ -15,6 +14,8 @@
static char cvsroot[] = "$Header$"; static char cvsroot[] = "$Header$";
static DOHHash *rules = 0;
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Swig_dump_tags() * Swig_dump_tags()
* *
@ -46,178 +47,75 @@ Swig_dump_tags(DOH *obj, DOH *root) {
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Swig_add_rule() * Swig_add_rule()
* *
* Adds a new rule to a ruleset. Rules are specified using a subset of CSS2 * Adds a new rule to the tree walking code.
* (Cascading Style Sheet) syntax. For example:
*
* "function" - Applies to a function
* "class function" - Applies to any function inside a class
* "class > function" - Applies to an immediate child.
* "foo * bar" - Wildcard. Matches zero or more tags in between.
*
* Note: "foo * bar" is the same as "foo bar".
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
void void
Swig_add_rule(DOH *ruleset, DOH *ruleobj, DOH *action) { Swig_add_rule(DOHString_or_char *name, int (*action)(DOH *node, void *clientdata))
DOH *rule, *rulelist, *nextruleset, *r, *robj;
int c, i, ntags = 0, lastid = 0, isid = 0;
rule = NewString(ruleobj);
/* Split the rule into a list */
rulelist = NewList();
Seek(rule,0,SEEK_SET);
r = NewString("");
while ((c = Getc(rule)) != EOF) {
if (c == ' ') {
if (lastid && isid) {
Insert(rulelist,0,"*");
ntags++;
}
ntags++;
Insert(rulelist,0,r);
r = NewString("");
lastid = isid;
isid = 0;
} else if (isalnum(c)) {
isid = 1;
Putc(c,r);
} else {
Putc(c,r);
}
}
if (lastid && isid) {
Insert(rulelist,0,"*");
ntags++;
}
ntags++;
Insert(rulelist,0,r);
nextruleset = ruleset;
/* Now, try to insert the rule into the table */
for (i = 0; i < ntags; i++) {
ruleset = nextruleset;
r = Getitem(rulelist,i);
if (Cmp(r,">")) {
robj = Getattr(ruleset,r); /* Get a rule entry (if any) */
if (robj) {
/* If the rule already exists, extract the next ruleset in case we need it */
nextruleset = Getattr(robj,"ruleset");
} else {
/* No rule exists. Create an entry and store it in the ruleset */
robj = NewHash();
nextruleset = NewHash();
Setattr(robj,"ruleset",nextruleset);
Setattr(ruleset, r, robj);
}
}
}
/* For the last rule, insert the action into robj */
Setattr(robj,"action",action);
/* Printf(stdout,"%s\n", rulelist); */
Delete(rule);
Delete(rulelist);
}
/* -----------------------------------------------------------------------------
* Swig_match_rule()
*
* Given a ruleset and a list of nodes, this function tries to find the longest
* matching rule.
* ----------------------------------------------------------------------------- */
DOH *
Swig_match_rule(DOH *ruleset, DOH *nodelist)
{ {
DOH *tag, *action = 0, *robj = 0, *wobj = 0, *bestobj = 0, *candidates; if (!rules) rules = NewHash();
int i, ntags, bestlen = 0, wildcard = 0; if (action)
ntags = Len(nodelist); Setattr(rules,name,NewVoid((void *) action,0));
if (ntags <= 0) return 0; else
Delattr(rules,name);
i = ntags - 1;
while (i >= 0) {
tag = Getattr(Getitem(nodelist,i),"tag");
/* See if there is any matching tag at all */
robj = Getattr(ruleset,tag);
if (robj) {
wobj = 0;
wildcard = 0;
} else if (!robj && wildcard) {
robj = wobj;
wildcard++;
} else if (!robj) {
robj = Getattr(ruleset,"*");
if (robj) {
wildcard = 1;
wobj = robj;
}
}
if (!robj)
return bestobj;
/* Got at least one match. Search for others */
action = Getattr(robj,"action");
if (action) {
bestobj = action;
}
if (wildcard != 1)
i--;
ruleset = Getattr(robj,"ruleset");
}
return bestobj;
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Swig_emit_rules() * Swig_add_rules()
* *
* Given a node, this function fires all of the rules for its siblings by * Add a complete set of rules to the rule system
* invoking a user-supplied callback function. The ruleset is a set of
* handling rules as created by Swig_add_rule. context is a list containing
* the context of node (all enclosing parent nodes).
*
* Note: child nodes are not processed (as a handler function might want to
* take special action or ignore the children).
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
void void
Swig_emit_rules(DOH *ruleset, DOH *context, DOH *node, Swig_add_rules(SwigRule ruleset[]) {
int (*actionhandler)(DOH *ruleset, DOH *context, DOH *node, DOH *action)) { int i = 0;
while (ruleset[i].name) {
DOH *act; Swig_add_rule(ruleset[i].name, ruleset[i].action);
DOH *next; i++;
while (node) {
Append(context,node);
act = Swig_match_rule(ruleset,context);
if (act) {
(*actionhandler)(ruleset,context,node,act);
}
Delitem(context, DOH_END);
node = Getattr(node,"sibling");
} }
} }
#ifdef TEST /* -----------------------------------------------------------------------------
* Swig_clear_rules()
int main() { *
DOH *a; * Clears all of the existing rules
DOH *tags; * ----------------------------------------------------------------------------- */
DOH *action = NewString("*action*");
DOH *ruleset = NewHash();
Swig_add_rule(ruleset,"function","*function*");
Swig_add_rule(ruleset,"class *","*memberfunction*");
Swig_add_rule(ruleset,"foo","*foo*");
tags = NewList();
Append(tags,"includefile");
Append(tags,"class");
Append(tags,"function");
Append(tags,"foo");
a = Swig_match_rule(ruleset, tags);
if (a)
Printf(stdout,"%s\n", a);
void
Swig_clear_rules()
{
if (rules) Delete(rules);
rules = NewHash();
} }
#endif /* -----------------------------------------------------------------------------
* int Swig_emit()
*
* Emit an action for a specific object
* ----------------------------------------------------------------------------- */
int
Swig_emit(DOH *obj, void *clientdata) {
DOH *tag;
DOH *actionobj;
int (*action)(DOH *obj, void *clientdata);
int ret;
assert(obj);
if (!rules) return -1;
while (obj) {
tag = Getattr(obj,"tag");
actionobj = Getattr(rules,tag);
if (!actionobj) return -1;
action = (int (*)(DOH *, void *)) Data(actionobj);
ret = (*action)(obj,clientdata);
if (ret < 0) return -1;
obj = Getattr(obj,"sibling");
}
return 0;
}