This source file includes following definitions.
- _newNode
- makeRule
- findRule
- beginRule
- Rule_setExpression
- makeVariable
- makeName
- makeDot
- makeCharacter
- makeString
- makeClass
- makeAction
- makePredicate
- makeAlternate
- Alternate_append
- makeSequence
- Sequence_append
- makePeekFor
- makePeekNot
- makeQuery
- makeStar
- makePlus
- dumpStack
- push
- top
- pop
- Node_fprint
- Node_print
- Rule_fprint
- Rule_print
- Rule_free
- freeRules
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "greg.h"
Node *actions= 0;
Node *rules= 0;
Node *thisRule= 0;
Node *start= 0;
FILE *output= 0;
int actionCount= 0;
int ruleCount= 0;
int lastToken= -1;
static inline Node *_newNode(NodeType type, int size)
{
Node *node= calloc(1, size);
node->type= type;
((struct Any *) node)->errblock= NULL;
return node;
}
#define newNode(T) _newNode(T, sizeof(struct T))
Node *makeRule(char *name, int starts)
{
Node *node= newNode(Rule);
node->rule.name= strdup(name);
node->rule.id= ++ruleCount;
node->rule.flags= starts ? RuleUsed : 0;
node->rule.next= rules;
rules= node;
return node;
}
Node *findRule(char *name, int starts)
{
Node *n;
char *ptr;
for (ptr= name; *ptr; ptr++) if ('-' == *ptr) *ptr= '_';
for (n= rules; n; n= n->any.next)
{
assert(Rule == n->type);
if (!strcmp(name, n->rule.name))
return n;
}
return makeRule(name, starts);
}
Node *beginRule(Node *rule)
{
actionCount= 0;
return thisRule= rule;
}
void Rule_setExpression(Node *node, Node *expression)
{
assert(node);
#ifdef DEBUG
Node_print(node); fprintf(stderr, " [%d]<- ", node->type); Node_print(expression); fprintf(stderr, "\n");
#endif
assert(Rule == node->type);
node->rule.expression= expression;
if (!start || !strcmp(node->rule.name, "start"))
start= node;
}
Node *makeVariable(char *name)
{
Node *node;
assert(thisRule);
for (node= thisRule->rule.variables; node; node= node->variable.next)
if (!strcmp(name, node->variable.name))
return node;
node= newNode(Variable);
node->variable.name= strdup(name);
node->variable.next= thisRule->rule.variables;
thisRule->rule.variables= node;
return node;
}
Node *makeName(Node *rule)
{
Node *node= newNode(Name);
node->name.rule= rule;
node->name.variable= 0;
rule->rule.flags |= RuleUsed;
return node;
}
Node *makeDot(void)
{
return newNode(Dot);
}
Node *makeCharacter(char *text)
{
Node *node= newNode(Character);
node->character.value= strdup(text);
return node;
}
Node *makeString(char *text)
{
Node *node= newNode(String);
node->string.value= strdup(text);
return node;
}
Node *makeClass(char *text)
{
Node *node= newNode(Class);
node->cclass.value= (unsigned char *)strdup(text);
return node;
}
Node *makeAction(char *text)
{
Node *node= newNode(Action);
char name[1024];
assert(thisRule);
sprintf(name, "_%d_%s", ++actionCount, thisRule->rule.name);
node->action.name= strdup(name);
node->action.text= strdup(text);
node->action.list= actions;
node->action.rule= thisRule;
actions= node;
{
char *ptr;
for (ptr= node->action.text; *ptr; ++ptr)
if ('$' == ptr[0] && '$' == ptr[1])
ptr[1]= ptr[0]= 'y';
}
return node;
}
Node *makePredicate(char *text)
{
Node *node= newNode(Predicate);
node->predicate.text= strdup(text);
return node;
}
Node *makeAlternate(Node *e)
{
if (Alternate != e->type)
{
Node *node= newNode(Alternate);
assert(e);
assert(!e->any.next);
node->alternate.first=
node->alternate.last= e;
return node;
}
return e;
}
Node *Alternate_append(Node *a, Node *e)
{
assert(a);
a= makeAlternate(a);
assert(a->alternate.last);
assert(e);
a->alternate.last->any.next= e;
a->alternate.last= e;
return a;
}
Node *makeSequence(Node *e)
{
if (Sequence != e->type)
{
Node *node= newNode(Sequence);
assert(e);
assert(!e->any.next);
node->sequence.first=
node->sequence.last= e;
return node;
}
return e;
}
Node *Sequence_append(Node *a, Node *e)
{
assert(a);
a= makeSequence(a);
assert(a->sequence.last);
assert(e);
a->sequence.last->any.next= e;
a->sequence.last= e;
return a;
}
Node *makePeekFor(Node *e)
{
Node *node= newNode(PeekFor);
node->peekFor.element= e;
return node;
}
Node *makePeekNot(Node *e)
{
Node *node= newNode(PeekNot);
node->peekNot.element= e;
return node;
}
Node *makeQuery(Node *e)
{
Node *node= newNode(Query);
node->query.element= e;
return node;
}
Node *makeStar(Node *e)
{
Node *node= newNode(Star);
node->star.element= e;
return node;
}
Node *makePlus(Node *e)
{
Node *node= newNode(Plus);
node->plus.element= e;
return node;
}
static Node *stack[1024];
static Node **stackPointer= stack;
#ifdef DEBUG
static void dumpStack(void)
{
Node **p;
for (p= stack + 1; p <= stackPointer; ++p)
{
fprintf(stderr, "### %ld\t", p - stack);
Node_print(*p);
fprintf(stderr, "\n");
}
}
#endif
Node *push(Node *node)
{
assert(node);
assert(stackPointer < stack + 1023);
#ifdef DEBUG
dumpStack(); fprintf(stderr, " PUSH "); Node_print(node); fprintf(stderr, "\n");
#endif
return *++stackPointer= node;
}
Node *top(void)
{
assert(stackPointer > stack);
return *stackPointer;
}
Node *pop(void)
{
assert(stackPointer > stack);
#ifdef DEBUG
dumpStack(); fprintf(stderr, " POP\n");
#endif
return *stackPointer--;
}
static void Node_fprint(FILE *stream, Node *node)
{
assert(node);
switch (node->type)
{
case Freed: return;
case Rule: fprintf(stream, " %s", node->rule.name); break;
case Variable: fprintf(stream, " %s", node->variable.name); break;
case Name: fprintf(stream, " %s", node->name.rule->rule.name); break;
case Dot: fprintf(stream, " ."); break;
case Character: fprintf(stream, " '%s'", node->character.value); break;
case String: fprintf(stream, " \"%s\"", node->string.value); break;
case Class: fprintf(stream, " [%s]", node->cclass.value); break;
case Action: fprintf(stream, " { %s }", node->action.text); break;
case Predicate: fprintf(stream, " ?{ %s }", node->action.text); break;
case Alternate: node= node->alternate.first;
fprintf(stream, " (");
Node_fprint(stream, node);
while ((node= node->any.next))
{
fprintf(stream, " |");
Node_fprint(stream, node);
}
fprintf(stream, " )");
break;
case Sequence: node= node->sequence.first;
fprintf(stream, " (");
Node_fprint(stream, node);
while ((node= node->any.next))
Node_fprint(stream, node);
fprintf(stream, " )");
break;
case PeekFor: fprintf(stream, "&"); Node_fprint(stream, node->query.element); break;
case PeekNot: fprintf(stream, "!"); Node_fprint(stream, node->query.element); break;
case Query: Node_fprint(stream, node->query.element); fprintf(stream, "?"); break;
case Star: Node_fprint(stream, node->query.element); fprintf(stream, "*"); break;
case Plus: Node_fprint(stream, node->query.element); fprintf(stream, "+"); break;
default:
fprintf(stream, "\nunknown node type %d\n", node->type);
exit(1);
}
}
void Node_print(Node *node) { Node_fprint(stderr, node); }
static void Rule_fprint(FILE *stream, Node *node)
{
assert(node);
assert(Rule == node->type);
fprintf(stream, "%s.%d =", node->rule.name, node->rule.id);
if (node->rule.expression)
Node_fprint(stream, node->rule.expression);
else
fprintf(stream, " UNDEFINED");
fprintf(stream, " ;\n");
}
void Rule_print(Node *node) { Rule_fprint(stderr, node); }
void Rule_free(Node *node)
{
switch (node->type)
{
case Freed: return;
case Rule:
{
Node *var= node->rule.variables;
#ifdef DEBUG
fprintf(stderr, "free Rule %s.%d\n", node->rule.name, node->rule.id);
#endif
free(node->rule.name);
while (var) {
Node *tmp= var->any.next; Rule_free(var); var= tmp;
}
if (node->rule.expression)
Rule_free(node->rule.expression);
break;
}
case Name: break;
case Variable: free(node->variable.name); break;
case Dot: break;
case Character: free(node->character.value); break;
case String: free(node->string.value); break;
case Class: free(node->cclass.value); break;
case Action:
#ifdef DEBUG
fprintf(stderr, "free Action %s\n", node->action.name);
#endif
free(node->action.text); free(node->action.name); break;
case Predicate: free(node->predicate.text); break;
case Alternate:
{
Node *root= node;
#ifdef DEBUG
fprintf(stderr, "free Alternate %p\n", node);
#endif
node= node->alternate.first;
while (node->any.next) {
Node *tmp= node->any.next; Rule_free(node); node= tmp;
}
Rule_free(node);
node= root;
break;
}
case Sequence:
{
Node *root= node;
#ifdef DEBUG
fprintf(stderr, "free Sequence %p\n", node);
#endif
node= node->sequence.first;
while (node->any.next) {
Node *tmp= node->any.next; Rule_free(node); node= tmp;
}
Rule_free(node);
node= root;
break;
}
case PeekFor: break;
case PeekNot: break;
case Query: break;
case Star: break;
case Plus: break;
default:
fprintf(stderr, "\nunknown node type %d\n", node->type);
return;
}
assert(node);
node->type = Freed;
if (((struct Any *)node)->errblock)
free(((struct Any *)node)->errblock);
#ifndef DD_CYCLE
free(node);
#endif
}
void freeRules (void) {
Node *n;
for (n= rules; n; ) {
if (n->type > 0) {
Node *tmp= n->any.next;
Rule_free(n);
if (tmp)
n= tmp->any.next;
else
n= NULL;
}
else {
n= n->any.next;
}
}
#ifdef DD_CYCLE
for (n= rules; n; ) {
if (n->type == Freed) {
Node *tmp= n->any.next;
free(n);
if (tmp)
n= tmp->any.next;
else
n= NULL;
}
else {
n= n->any.next;
}
}
#endif
}