#include "global.h"
#include "list.h"
#include "source.h"
#include "lex.h"
#include "parser.h"
#include "irep.h"
#include "lexparse.h"
#include "fsa.h"
#include "fsatab.h"
// The constructor function for FsaTable converts the FSA transitions
// into a table form for convenient output.
FsaTable::FsaTable(list<odfsaState *> *x)
{
int offset = 0;
listIter<odfsaState *> each(x);
odfsaState **s;
Transition *t;
maxChar = (Transition::maxChar > 127 ? 255 : 127);
states = x->length();
table = (short int **) allocate(states * sizeof(short int *));
final = (LexRule **) allocate(states * sizeof(LexRule *));
for (int i=0; i<states; i++) {
s = each();
table[i] = (short int *) allocate(maxChar * sizeof(short int));
if (!offset)
offset = (*s)->id();
if (odfsaState::initialPartition == (*s))
initState = (*s)->id() - offset;
final[i] = (*s)->associatedToken();
for (int j=1; j<=maxChar; j++) {
t = (*s)->transitions.findTrigger(j);
table[i][j-1] = (t ? t->destination()->id() - offset: -1);
}
}
}
// The following are member functions for printing out appropriate code
// fragements in response to the predetermined markers in the template
// file.
void FsaTable::pr_nomodsWarning(FILE *ofdes) {
fprintf(ofdes, "This is a generated file. Modifications are futile.");
}
void FsaTable::pr_initialState(FILE *ofdes)
{
fprintf(ofdes, "%d", initState);
}
void FsaTable::pr_states(FILE *ofdes)
{
fprintf(ofdes, "%d", states);
}
void FsaTable::pr_charSet(FILE *ofdes)
{
fprintf(ofdes, "%d", maxChar+2);
}
void FsaTable::pr_finalStates(FILE *ofdes)
{
fprintf(ofdes, "{\n");
for (int i=0; i<states; i++) {
if (i != 0)
fprintf(ofdes, ",\n");
if (final[i]) {
if (final[i]->isIgnored())
fprintf(ofdes, "\t{ 0, ");
else
fprintf(ofdes, "\t{ %s, ", final[i]->name());
if (final[i]->filter())
fprintf(ofdes, "_fil_%s }", final[i]->name());
else
fprintf(ofdes, "0 }");
} else
fprintf(ofdes, "\t{ -1, 0 }");
}
fprintf(ofdes, "}");
}
void FsaTable::pr_filters(FILE *ofdes)
{
for (int i=0; i<states; i++)
if (final[i] && final[i]->filter()) {
for (int j=0; j<i; j++)
if (final[j] == final[i])
goto skip;
fprintf(ofdes, "void _fil_%s", final[i]->name());
fprintf(ofdes, "(GLexer *lex, LexToken &token)\n");
fprintf(ofdes, "{%s\n%s\n}\n",
"if (!lex) abort();", final[i]->filter());
skip: ;
}
}
void FsaTable::pr_prelude(FILE *ofdes)
{
if (LexGenParser::prelude)
fprintf(ofdes, "%s\n", LexGenParser::prelude);
}
void FsaTable::pr_postlude(FILE *ofdes)
{
if (LexGenParser::postlude)
fprintf(ofdes, "%s\n", LexGenParser::postlude);
}
// The writer class produces formatted tables. This is useful for the
// initialisation of large arrays to represent transition functions.
class writer {
FILE *fdes;
int col, first;
char buf[16];
public:
void print(int);
void print(char *);
writer(FILE *);
~writer();
};
void FsaTable::pr_stateTransition(FILE *ofdes)
{
writer v(ofdes);
for (int i=0; i<states; i++) {
v.print("\n");
{ writer w(ofdes);
w.print(-1); w.print(-1);
for (int j=1; j<=maxChar; j++)
w.print(table[i][j-1]);
}
}
}
void writer::print(char *s)
{
if (!first) {
fprintf(fdes, ", "); col += 2;
}
first = FALSE;
col += strlen(s);
if (col > 70) {
col = 0;
fprintf(fdes, "\n");
}
fprintf(fdes, "%s", s);
}
void writer::print(int i)
{
if (!first) {
fprintf(fdes, ", "); col += 2;
}
first = FALSE;
sprintf(buf, "%d", i);
col += strlen(buf);
if (col > 70) {
col = 0;
fprintf(fdes, "\n");
}
fprintf(fdes, "%s", buf);
}
writer::writer(FILE *fd)
{
fdes = fd;
col = 0;
first = TRUE;
fprintf(fdes, "{");
}
writer::~writer()
{
fprintf(fdes, "}");
}
syntax highlighted by Code2HTML, v. 0.9.1