#include "global.h"
#include "list.h"
#include "irep.h"
#include "fsa.h"
LexRuleList LexRule::ruleSet;
LexRule::LexRule(char* n)
{
_name = allocate(strlen(n)+1); strcpy(_name, n);
_hasDefinition = FALSE;
_isIgnored = FALSE;
_isToken = FALSE;
_filter = 0;
LexRule *thisRule = this;
ruleSet.append(thisRule);
}
// The member function find() uses the iterator facility to traverse the
// list for a rule name that matches the target.
LexRule *LexRuleList::find(char *target)
{
listIter<LexRule *> forEach(this);
LexRule **item;
while (item = forEach())
if (strcmp((*item)->name(), target) == 0)
return(*item);
return 0;
}
// Each rule specification of a token is converted in turn to an
// appropriate FSA via invoking the member function process() with the
// initial state. It in turn invokes the process() member function of
// each LexNode instance. Ultimately, it returns the final state. A
// rule with an empty body does not need to generate additional states.
fsaState *LexRule::process(fsaState *init)
{
fsaState *dest;
#ifdef DEBUGPRINT
printf("%s = ", name());
#endif
dest = (body() ? body()->process(init) : 0);
#ifdef DEBUGPRINT
printf(".\n");
#endif
return dest;
}
// Since the process() member function for LexNode is a stub it should
// not be invoked but redefined in derived classes.
fsaState *LexNode::process(fsaState *)
{
error(INTERNAL, "Node::process");
}
// The FSA is extended for a terminal symbol by making a new FSA state
// and including an appropriate transition from source to destination
// states.
fsaState *LexCharNode::process(fsaState *init)
{
fsaState *dest;
#ifdef DEBUGPRINT
if (ch1() == ch2())
printf("#%d ", ch1());
else
printf("#%d .. #%d ", ch1(), ch2());
#endif
dest = new fsaState();
for (int i = ch1(); i <= ch2(); i++)
init->transitions.append(new Transition(i, dest));
// The conversion process continues along the rule sequence so that
// it returns the final FSA state for that sequence.
return(next ? next->process(dest) : dest);
}
// The FSA is extended for a nonterminal symbol by recursively
// invoking process() for the nonterminal rule. As before, the
// conversion procedure subsequently resumes for follower nodes.
fsaState *LexNonTermNode::process(fsaState *init)
{
LexNode *rule;
#ifdef DEBUGPRINT
printf("%s ", nonterm()->name());
#endif
rule = nonterm()->body();
fsaState *dest = (rule ? rule->process(init) : init);
return(next ? next->process(dest) : dest);
}
// The FSA is extended for an alternative node by recursively invoking
// process() for the alternative rules. Null transitions are
// subsequently required to merge the two alternatives to a common
// state. As before, the conversion procedure subsequently resumes for
// follower nodes.
fsaState *LexSelectNode::process(fsaState *init)
{
fsaState *dest1, *dest2, *dest;
#ifdef DEBUGPRINT
printf("( ");
#endif
dest1 = (fsaState *) (alt1() ? alt1()->process(init) : init);
#ifdef DEBUGPRINT
printf("| ");
#endif
dest2 = (fsaState *) (alt2() ? alt2()->process(init) : init);
#ifdef DEBUGPRINT
printf(") ");
#endif
dest = new fsaState();
dest1->transitions.append(new Transition(Transition::NOCHAR, dest));
dest2->transitions.append(new Transition(Transition::NOCHAR, dest));
return(next ? next->process(dest) : dest);
}
// The FSA is extended for a repetitive node by recursively invoking
// process() for the repetitive rules. Appropriate null transitions are
// subsequently required to connect sub-FSAs to reflect the semantics of
// repetition. As before, the conversion procedure subsequently resumes
// for follower nodes.
fsaState *LexRepeatNode::process(fsaState *init)
{
fsaState *start, *dest, *loop, *final;
#ifdef DEBUGPRINT
printf("{ ");
#endif
start = new fsaState();
init->transitions.append(new Transition(Transition::NOCHAR, start));
dest = (repetition() ? repetition()->process(start) : start);
if (separator()) {
#ifdef DEBUGPRINT
printf(", ");
#endif
loop = separator()->process(dest);
} else
loop = dest;
loop->transitions.append(new Transition(Transition::NOCHAR, start));
final = new fsaState();
dest->transitions.append(new Transition(Transition::NOCHAR, final));
if (atLeastOne()) {
#ifdef DEBUGPRINT
printf("}+ ")
#endif
;
} else {
init->transitions.append(new Transition(Transition::NOCHAR, final));
#ifdef DEBUGPRINT
printf("} ");
#endif
}
return(next ? next->process(final) : final);
}
syntax highlighted by Code2HTML, v. 0.9.1