<commit_before>/*-------------------------------------------------------------------------
  Author (C) 2008, <NAME> <<EMAIL>>

  This program is free software; you can redistribute it and/or modify it 
  under the terms of the GNU General Public License as published by the 
  Free Software Foundation; either version 2, or (at your option) any 
  later version.

  This program is distributed in the hope that it will be useful, but 
  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
  for more details.

  You should have received a copy of the GNU General Public License along 
  with this program; if not, write to the Free Software Foundation, Inc., 
  59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

  As an exception, it is allowed to write an extension of Coco/R that is
  used as a plugin in non-free software.

  If not otherwise stated, any source code generated by Coco/R (other than 
  Coco/R itself) does not fall under the GNU General Public License.
-------------------------------------------------------------------------*/
#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  "Tab.h"
#include  "Symbol.h"

Tab_t *
Tab(Tab_t * self, Parser_t * parser) {
    if (!ArrayList(&self->terminals)) goto errquit0;
    if (!ArrayList(&self->pragmas)) goto errquit1;
    if (!ArrayList(&self->nonterminals)) goto errquit2;
    return self;
#if 0
 errquit3:
    ArrayList_Destruct(&self->nonterminals);
#endif
 errquit2:
    ArrayList_Destruct(&self->pragmas);
 errquit1:
    ArrayList_Destruct(&self->terminals);
 errquit0:
    return NULL;
}

Symbol_t *
Tab_NewSym(Tab_t * self, int typ, const char * name, int line)
{
    Symbol_t * sym;

#if 0  /* Is this possible */
    if (!strcmp(name, "\"\"")) {
	self->parser->SemErr("empty token now allowed");
	name = "???";
    }
#endif
    if (!(sym = malloc(sizeof(Symbol_t)))) return NULL;
    if (!(Symbol(sym, typ, name, line))) { free(sym); return NULL; }

    if (typ == node_t) {
	sym->n = self->terminals.Count;
	ArrayList_Add(&self->terminals, sym);
    } else if (typ == node_pr) {
	ArrayList_Add(&self->pragmas, sym);
    } else if (typ == node_nt) {
	sym->n = self->nonterminals.Count;
	ArrayList_Add(&self->nonterminals, sym);
    }
    return sym;
}

Symbol_t *
Tab_FindSym(Tab_t * self, const char * name)
{
    int idx; Symbol_t * sym;
    for (idx = 0; idx < self->terminals.Count; ++idx) {
	sym = (Symbol_t *)ArrayList_Get(&self->terminals, idx);
	if (!strcmp(sym->name, name)) return sym;
    }
    for (idx = 0; idx < self->nonterminals.Count; ++idx) {
	sym = (Symbol_t *)ArrayList_Get(&self->nonterminals, idx);
	if (!strcmp(sym->name, name)) return sym;
    }
    return NULL;
}

void
Tab_PrintSymbolTable(Tab_t * self)
{
    int idx; Symbol_t * sym; HTIterator_t iter;
    DumpBuffer_t dbuf; char buf[128];

    fprintf(self->trace, "Symbol Table:\n");
    fprintf(self->trace, "------------\n\n");
    fprintf(self->trace, " nr name          typ  hasAt graph  del    line tokenKind\n");

    for (idx = 0; idx < self->terminals.Count; ++idx) {
	sym = (Symbol_t *)ArrayList_Get(&self->terminals, idx);
	DumpBuffer(&dbuf, buf, sizeof(buf));
	Symbol_Dump(sym, &dbuf);
	fprintf(self->trace, "%s\n", buf);
    }

    for (idx = 0; idx < self->pragmas.Count; ++idx) {
	sym = (Symbol_t *)ArrayList_Get(&self->pragmas, idx);
	DumpBuffer(&dbuf, buf, sizeof(buf));
	Symbol_Dump(sym, &dbuf);
	fprintf(self->trace, "%s\n", buf);
    }

    for (idx = 0; idx < self->nonterminals.Count; ++idx) {
	sym = (Symbol_t *)ArrayList_Get(&self->nonterminals, idx);
	DumpBuffer(&dbuf, buf, sizeof(buf));
	Symbol_Dump(sym, &dbuf);
	fprintf(self->trace, "%s\n", buf);
    }

    fprintf(self->trace, "\nLiteral Tokens:\n");
    fprintf(self->trace, "--------------\n");

    HashTable_GetIterator(&self->literals, &iter);
    while (HTIterator_Forward(&iter)) {
	fprintf(self->trace, "_%s =  %s.\n",
		((Symbol_t *)HTIterator_Value(&iter))->name,
		HTIterator_Key(&iter));
    }
    fprintf(self->trace, "\n");
}

void
Tab_SetDDT(Tab_t * self, const char * s)
{
    while (*s) {
	if (*s >= '0' && *s <= '9') self->ddt[*s - '0'] = TRUE;
	else switch (*s) {
	    case 'A': case 'a': self->ddt[0] = TRUE; break; /* trace automation */<commit_msg>* Add more funcs.<commit_after>/*-------------------------------------------------------------------------
  Author (C) 2008, <NAME> <<EMAIL>>

  This program is free software; you can redistribute it and/or modify it 
  under the terms of the GNU General Public License as published by the 
  Free Software Foundation; either version 2, or (at your option) any 
  later version.

  This program is distributed in the hope that it will be useful, but 
  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
  for more details.

  You should have received a copy of the GNU General Public License along 
  with this program; if not, write to the Free Software Foundation, Inc., 
  59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

  As an exception, it is allowed to write an extension of Coco/R that is
  used as a plugin in non-free software.

  If not otherwise stated, any source code generated by Coco/R (other than 
  Coco/R itself) does not fall under the GNU General Public License.
-------------------------------------------------------------------------*/
#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  "Tab.h"
#include  "Graph.h"
#include  "Node.h"
#include  "Symbol.h"

Tab_t *
Tab(Tab_t * self, Parser_t * parser) {
    Bool_t malloced;
    if (!(self = AllocObject(self, sizeof(Tab_t), &malloced))) goto errquit0;
    if (!ArrayList(&self->terminals)) goto errquit1;
    if (!ArrayList(&self->pragmas)) goto errquit2;
    if (!ArrayList(&self->nonterminals)) goto errquit3;
    if (!ArrayList(&self->nodes)) goto errquit4;
    return self;
 errquit4:
    ArrayList_Destruct(&self->nonterminals);
 errquit3:
    ArrayList_Destruct(&self->pragmas);
 errquit2:
    ArrayList_Destruct(&self->terminals);
 errquit1:
    if (malloced) free(self);
 errquit0:
    return NULL;
}

Symbol_t *
Tab_NewSym(Tab_t * self, int typ, const char * name, int line)
{
    Symbol_t * sym;

#if 0  /* Is this possible */
    if (!strcmp(name, "\"\"")) {
	self->parser->SemErr("empty token now allowed");
	name = "???";
    }
#endif
    if (!(sym = malloc(sizeof(Symbol_t)))) return NULL;
    if (!(Symbol(sym, typ, name, line))) { free(sym); return NULL; }

    if (typ == node_t) {
	sym->n = self->terminals.Count;
	ArrayList_Add(&self->terminals, sym);
    } else if (typ == node_pr) {
	ArrayList_Add(&self->pragmas, sym);
    } else if (typ == node_nt) {
	sym->n = self->nonterminals.Count;
	ArrayList_Add(&self->nonterminals, sym);
    }
    return sym;
}

Symbol_t *
Tab_FindSym(Tab_t * self, const char * name)
{
    int idx; Symbol_t * sym;
    for (idx = 0; idx < self->terminals.Count; ++idx) {
	sym = (Symbol_t *)ArrayList_Get(&self->terminals, idx);
	if (!strcmp(sym->name, name)) return sym;
    }
    for (idx = 0; idx < self->nonterminals.Count; ++idx) {
	sym = (Symbol_t *)ArrayList_Get(&self->nonterminals, idx);
	if (!strcmp(sym->name, name)) return sym;
    }
    return NULL;
}

void
Tab_PrintSymbolTable(Tab_t * self)
{
    int idx; Symbol_t * sym; HTIterator_t iter;
    DumpBuffer_t dbuf; char buf[128];

    fprintf(self->trace, "Symbol Table:\n");
    fprintf(self->trace, "------------\n\n");
    fprintf(self->trace, " nr name          typ  hasAt graph  del    line tokenKind\n");

    for (idx = 0; idx < self->terminals.Count; ++idx) {
	sym = (Symbol_t *)ArrayList_Get(&self->terminals, idx);
	DumpBuffer(&dbuf, buf, sizeof(buf));
	Symbol_Dump(sym, &dbuf);
	fprintf(self->trace, "%s\n", buf);
    }

    for (idx = 0; idx < self->pragmas.Count; ++idx) {
	sym = (Symbol_t *)ArrayList_Get(&self->pragmas, idx);
	DumpBuffer(&dbuf, buf, sizeof(buf));
	Symbol_Dump(sym, &dbuf);
	fprintf(self->trace, "%s\n", buf);
    }

    for (idx = 0; idx < self->nonterminals.Count; ++idx) {
	sym = (Symbol_t *)ArrayList_Get(&self->nonterminals, idx);
	DumpBuffer(&dbuf, buf, sizeof(buf));
	Symbol_Dump(sym, &dbuf);
	fprintf(self->trace, "%s\n", buf);
    }

    fprintf(self->trace, "\nLiteral Tokens:\n");
    fprintf(self->trace, "--------------\n");

    HashTable_GetIterator(&self->literals, &iter);
    while (HTIterator_Forward(&iter)) {
	fprintf(self->trace, "_%s =  %s.\n",
		((Symbol_t *)HTIterator_Value(&iter))->name,
		HTIterator_Key(&iter));
    }
    fprintf(self->trace, "\n");
}

void
Tab_PrintSet(Tab_t * self, BitArray_t * s, int indent)
{
    int col, len, idx; Symbol_t * sym;
    col = indent;
    for (idx = 0; idx < self->terminals.Count; ++idx) {
	sym = (Symbol_t *)ArrayList_Get(&self->terminals, idx);
	if (!BitArray_Get(s, sym->n)) continue;
	len = strlen(sym->name);
	if (col + len >= 80) {
	    fprintf(self->trace, "\n");
	    for (col = 1; col < indent; ++col) fprintf(self->trace, " ");
	}
	fprintf(self->trace, "%s ", sym->name);
	col += len + 1;
    }
    if (col == indent) fprintf(self->trace, "-- empty set --");
    fprintf(self->trace, "\n");
}

Node_t *
Tab_NewNodeTSL(Tab_t * self, int typ, Symbol_t * sym, int line)
{
    Node_t * node;
    if (!(node = Node(NULL, typ, sym, line))) goto errquit0;
    node->n = self->nodes.Count;
    if (!ArrayList_Add(&self->nodes, node)) goto errquit1;
    return node;
 errquit1:
    Node_Destruct(node); free(node);
 errquit0:
    return NULL;
}

Node_t *
Tab_NewNodeTS(Tab_t * self, int typ, Node_t * sub)
{
    Node_t * node;
    if (!(node = Tab_NewNodeTSL(self, typ, NULL, 0))) return NULL;
    node->sub = sub;
    return node;
}

Node_t *
Tab_NewNodeTVL(Tab_t * self, int typ, int val, int line)
{
    Node_t * node;
    if (!(node = Tab_NewNodeTSL(self, typ, NULL, line))) return NULL;
    node->val = val;
    return node;
}

void
Tab_MakeFirstAlt(Tab_t * self, Graph_t * g)
{
    g->l = Tab_NewNodeTS(self, node_alt, g->l);
    g->l->line = g->l->sub->line;
    g->l->next = g->r;
    g->r = g->l;
}

void
Tab_MakeAlternative(Tab_t * self, Graph_t * g1, Graph_t * g2)
{
    /* HERE */
}

void
Tab_SetDDT(Tab_t * self, const char * s)
{
    while (*s) {
	if (*s >= '0' && *s <= '9') self->ddt[*s - '0'] = TRUE;
	else switch (*s) {
	    case 'A': case 'a': self->ddt[0] = TRUE; break; /* trace automation */
{'fraction_non_alphanumeric': 0.1882825193539138, 'fraction_numerical': 0.008984038994552232, 'mean_word_length': 3.0827155676941085, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 128, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6221438', 'n_tokens_mistral': 3743, 'n_tokens_neox': 3617, 'n_words': 1040}