📄 crt.c
字号:
CompWEAKSet(gn->INNER);
if (gn->type == T_ALT) CompWEAKSet(gn->ALT);
break;
}
gp = gn->next;
}
Set_Done(&set);
}
/* compute all WEAK sets */
static void CompAllWEAKSets(void)
{
ForEachNTermGraph((Graph_Func) CompWEAKSet);
}
/* compute set of all terminals except pragmas */
static void CompALLTermsSet(void)
{
Set_Clean(&ALL_TERMS);
Set_AddRange(&ALL_TERMS, 1, Collection_Count(&term_tab) - 1);
}
static void Func_NTermDeclared(PNTermNode ntn, int ntp)
{
if (ntp == 0) return;
if (ntn->graph == NIL) {
if (Q_option) {
fprintf(lstfile, "(%s) (%d, %d )",
source_name, ntn->line_use, 0);
fprintf(lstfile, " %s Not Declared\n", ntn->name);
}
else {
fprintf(lstfile, "\"%s\", Line %d, Col %d :",
source_name, ntn->line_use, 0);
fprintf(lstfile, "**** %s Not Declared\n", ntn->name);
}
Errors++;
} else
if (!ntn->reachable) {
if (Q_option) {
fprintf(lstfile, "(%s) (%d, %d )",
source_name, ntn->line_dec, 0);
fprintf(lstfile, " %s Declared but not used\n", ntn->name);
}
else {
fprintf(lstfile, "\"%s\", Line %d, Col %d :",
source_name, ntn->line_dec, 0);
fprintf(lstfile, "**** %s Declared but not used\n", ntn->name);
}
Errors++;
}
}
/* check if a nonterminal was use but not defined, or defined and not used */
static void CheckNTermDeclared(void)
{
Collection_ForEachPos(&nterm_tab, (Collection_FuncPos) Func_NTermDeclared);
}
static void Func_NTermNullable(PNTermNode ntn, int ntp)
{
if (! ntn->nullable || ntp == 0) return;
if (Q_option) {
fprintf(lstfile, "(%s) (%d, %d )",
source_name, S_Line, 0);
fprintf(lstfile, " Warning : %s is nullable\n", ntn->name);
}
else {
fprintf(lstfile, "\"%s\", Line %d, Col %d :",
source_name, S_Line, 0);
fprintf(lstfile, "**** Warning : %s is nullable\n", ntn->name);
}
}
/* check if a nonterminal is nullable */
static void CheckNTermNullable(void)
{
Collection_ForEachPos(&nterm_tab, (Collection_FuncPos) Func_NTermNullable);
}
/* check for nonterminal circular derivations */
static int CompCircularGraph(int gp)
{
PGraphNode gn;
int t;
while (gp > NIL) {
gn = GetGraphP(gp);
CR_ASSERT(gn != NULL);
switch(gn->type) {
case T_T :
case T_WT:
return FALSE;
case T_NT :
{
PNTermNode ntn = GetNTermP(gn->SYMLINK);
CR_ASSERT(ntn != NULL);
if (gn->SYMLINK == CurrentNt) return CurrentNt;
if (Set_IsItem(&Set1, gn->SYMLINK)) return FALSE;
Set_AddItem(&Set1, gn->SYMLINK);
if (CompCircularGraph(ntn->graph)) return gn->SYMLINK;
break;
}
case T_OPT:
case T_REP:
case T_ALT:
if ((t = CompCircularGraph(gn->INNER)) != FALSE) return t;
if (gn->type == T_ALT)
if ((t = CompCircularGraph(gn->ALT)) != FALSE) return t;
break;
}
if (!IsNullableNode(gp)) break; /* Nullable => Continue */
gp = gn->next;
}
return FALSE;
}
static void Func_CheckCircular(PNTermNode ntn, int ntp)
{
int t;
Set_Clean(&Set1);
CurrentNt = ntp;
if ((t = CompCircularGraph(ntn->graph)) != FALSE) {
PNTermNode ntn1 = GetNTermP(t);
if (Q_option)
fprintf(lstfile, " Circular Derivation %s -> %s\n", ntn->name, ntn1->name);
else
fprintf(lstfile, "**** Circular Derivation %s -> %s\n", ntn->name, ntn1->name);
Errors++;
}
}
static void CheckCircular(void)
{
Collection_ForEachPos(&nterm_tab, (Collection_FuncPos) Func_CheckCircular);
}
static int IsTerminalGraph(int gp)
{
PGraphNode gn;
while (gp > NIL) {
gn = GetGraphP(gp);
CR_ASSERT(gn != NULL);
switch(gn->type) {
case T_NT:
if (!Set_IsItem(&Set1, gn->SYMLINK)) return FALSE;
break;
case T_ALT:
if (!IsTerminalGraph(gn->INNER) &&
((gn->ALT == NIL) || !IsTerminalGraph(gn->ALT))) return FALSE;
break;
}
gp = gn->next;
}
return TRUE;
}
/* check if a nonterminal can derive to terminals */
static void CheckDeriveTerminals(void)
{
PNTermNode ntn;
int c, i, change;
Set_Clean(&Set1);
c = Collection_Count(&nterm_tab);
do {
change = FALSE;
for (i = 1; i < c; i++) /* for each Nonterminal */
if (!Set_IsItem(&Set1, i)) {
ntn = GetNTermP(i);
CR_ASSERT(ntn != NULL);
if (IsTerminalGraph(ntn->graph)) {
Set_AddItem(&Set1, i);
change = TRUE;
}
}
} while (change);
for (i = 1; i < c; i++) /* for each nonterminal */
if (!Set_IsItem(&Set1, i)) {
ntn = GetNTermP(i);
CR_ASSERT(ntn != NULL);
if (Q_option)
fprintf(lstfile, " %s Can't derive to Terminals\n", ntn->name);
else
fprintf(lstfile, "**** %s Can't derive to Terminals\n", ntn->name);
Errors++;
}
}
/* Generate LL(1) errors */
static void LL1Error(int c, int i)
{
PNTermNode ntn;
PTermNode tn;
ntn = GetNTermP(CurrentNt);
CR_ASSERT(ntn != NULL);
if (Q_option) {
fprintf(lstfile, "(%s) (%d, %d )",
source_name, S_Line, 0);
fprintf(lstfile, " LL(1) Error in %s: ", ntn->name);
}
else {
fprintf(lstfile, "\"%s\", Line %d, Col %d :",
source_name, S_Line, 0);
fprintf(lstfile, "**** LL(1) Error in %s: ", ntn->name);
}
if (i > 0) {
tn = GetTermP(i);
fprintf(lstfile, "%s is the ", tn->name);
}
switch (c) {
case 1:
fprintf(lstfile, "start of several alternatives.\n");
break;
case 2:
fprintf(lstfile, "start & successor of nullable structures.\n");
break;
case 3:
fprintf(lstfile, "an ANY node matches no symbol.\n");
break;
}
}
/* check if two sets have items in common */
static void CheckSets(int cond, Set *s1, Set *s2)
{
int i, c;
Set_GetRange(s1, &i, &c);
for (; i <= c; i++)
if (Set_IsItem(s1, i) && Set_IsItem(s2, i)) LL1Error(cond, i);
}
/* perform LL(1) checks in graph */
static void Func_CheckLL1Graph(int gp)
{
PGraphNode gn;
while (gp > NIL) {
gn = GetGraphP(gp);
CR_ASSERT(gn != NULL);
switch(gn->type) {
case T_ALT:
{
PGraphNode gn1;
int gp1;
gp1 = gp;
Set_Clean(&Set1);
while (gp1 > NIL) {
gn1 = GetGraphP(gp1);
CR_ASSERT(gn1 != NULL);
Set_Clean(&Set2);
CompExpected(gn1->INNER, CurrentNt, &Set2);
CheckSets(1, &Set1, &Set2);
Set_Union(&Set1, &Set2);
gp1 = gn1->ALT;
}
gp1 = gp;
while (gp1 > NIL) {
gn1 = GetGraphP(gp1);
CR_ASSERT(gn1 != NULL);
Func_CheckLL1Graph(gn1->INNER);
gp1 = gn1->ALT;
}
break;
}
case T_OPT:
case T_REP:
Set_Clean(&Set1);
Set_Clean(&Set2);
CompExpected(gn->INNER, CurrentNt, &Set1);
CompExpected(abs(gn->next), CurrentNt, &Set2);
CheckSets(2, &Set1, &Set2);
Func_CheckLL1Graph(gn->INNER);
break;
case T_ANY:
Set_Clean(&Set1);
GetSymSet(gn->SETLINK1, &Set1);
if (Set_Empty(&Set1)) LL1Error(3, 0);
break;
}
gp = gn->next;
}
}
static void CheckLL1(void)
{
ForEachNTermGraph((Graph_Func) Func_CheckLL1Graph);
}
/* compute all symbol sets needed */
void CompSymbolSets(void)
{
CheckNTermDeclared();
if (Errors) return;
CheckDeriveTerminals();
if (Errors) return;
CompALLTermsSet();
SetupPragmas();
CompAllFollowNodes();
CompAllNullable();
CheckNTermNullable();
CheckCircular();
if (Errors) return;
CompAllFirstSets();
CompAllFollowSets();
CompAllANYSets();
CompAllFirstSets(); /* Second Time: In very few cases */
CompAllFollowSets(); /* ANY sets can add information to first */
CompAllANYSets(); /* and Follow */
CompAllSYNCSets();
CompAllWEAKSets();
CheckLL1();
}
/* get expected next symbols */
void CompExpected(int gp, int nterm, Set *set)
{
CompNextFirstSet(gp, set);
if (IsNullableNextGraph(gp)) GetNTermFollow(nterm, set);
}
/*****************************************************************
*** General purpose Functions ***
*****************************************************************/
/* add ignore sets */
void AddIgnore(Set *set)
{
int cp;
PClassNode cn;
cp = FindClass("@ignore_chars");
if (cp != UNDEF) {
cn = GetClassP(cp);
Set_Union(&cn->data, set);
}
}
/* install a symbol */
int NewSym(PName name, int typ)
{
int sp = 0;
switch (typ) {
case T_T:
case T_WT:
sp = NewTerm(name);
break;
case T_P:
sp = NewPragma(name);
break;
case T_NT:
sp = NewNTerm(name);
break;
}
return sp;
}
/* find symbol */
int FindSym(PName name, int *typ)
{
int sp;
sp = FindClass(name);
if (sp > UNDEF) {
*typ = T_CLASS;
return sp;
}
sp = FindTerm(name);
if (sp > UNDEF) {
*typ = T_T;
return sp;
}
sp = FindPragma(name);
if (sp > UNDEF) {
*typ = T_P;
return sp;
}
sp = FindNTerm(name);
if (sp > UNDEF) {
*typ = T_NT;
return sp;
}
return UNDEF;
}
/* print ascii char */
void PrintAscii(int s)
{
if (s <= 32) fprintf(lstfile, " #%d ", s);
else fprintf(lstfile, "%c", s);
}
/* print integer */
void PrintInt(int s)
{
fprintf(lstfile, "%d ", s);
}
/* print terminal */
static void PrintTerm(int tp)
{
PTermNode tn;
tn = GetTermP(tp);
fprintf(lstfile, "%s ", tn->name);
}
/* print nonterminal */
static void PrintNTerm(int ntp)
{
PNTermNode ntn;
ntn = GetNTermP(ntp);
CR_ASSERT(ntn != NULL);
fprintf(lstfile, "%s ", ntn->name);
}
/* create & initialize all module variables */
void InitTab(void)
{
Collection_Init(&nterm_tab, sizeof(NTermNode), NTERM_SIZE, NTERM_EXTEND);
Collection_Init(&term_tab, sizeof(TermNode), TERM_SIZE, TERM_EXTEND);
Collection_Init(&nodes_tab, sizeof(GraphNode), NODES_SIZE, NODES_EXTEND);
Collection_Init(&class_tab, sizeof(ClassNode), CLASS_SIZE, CLASS_EXTEND);
Collection_Init(&symset_tab, sizeof(SymSetNode), SYMSET_SIZE, SYMSET_EXTEND);
Collection_Init(&pragma_tab, sizeof(PragmaNode), PRAGMA_SIZE, PRAGMA_EXTEND);
Collection_Init(&name_tab, sizeof(NameNode), NAME_SIZE, NAME_EXTEND);
Set_Init(&ANY_SET);
Set_Init(&ALL_TERMS);
Set_Init(&FirstVisited);
Set_Init(&FollowVisited);
Set_Init(&Set1);
Set_Init(&Set2);
Set_Clean(&ANY_SET);
(void) NewSymSet(&ANY_SET, T_SYNC); /* ALL SYNCS symset 0 */
Set_AddItem(&ANY_SET, ' ');
(void) NewClass("@ignore_chars", &ANY_SET); /* IGNORE SET 0 */
(void) NewSym("EOF", T_T); /* EOF_Sym term 0 */
(void) NewSym("@NTERM", T_NT); /* No Terminal 0 */
(void) MakeGraphNode(0); /* graph Node 0 */
Set_AddRange(&ANY_SET, 1, 255); /* ANY SET */
}
void CleanGraphTab(void)
{
Collection_Clean(&nodes_tab);
(void) MakeGraphNode(0); /* graph Node 0 */
}
/* destroy all module variables */
void DoneTab(void)
{
Collection_Done(&nterm_tab);
Collection_Done(&term_tab);
Collection_Done(&nodes_tab);
Collection_Done(&class_tab);
Collection_Done(&symset_tab);
Collection_Done(&pragma_tab);
Collection_Done(&name_tab);
Set_Done(&ANY_SET);
Set_Done(&ALL_TERMS);
Set_Done(&FirstVisited);
Set_Done(&FollowVisited);
Set_Done(&Set1);
Set_Done(&Set2);
}
char *SetVar(char *s)
{
char name[200], value[200];
char *n = name, *v = value;
/* Get the variable name */
while (*s && *s != '=') *n++ = *s++;
*n='\0';
if (*s == '=') s++;
/* Get the variable Value */
while (*s) *v++ = *s++;
*v = '\0';
/* printf("Variable %s = %s \n", name, value); */
if (stricmp(name, "CRHEXT") == 0) strcpy(h_ext, value);
if (stricmp(name, "CRCEXT") == 0) strcpy(c_ext, value);
if (stricmp(name, "CRFRAMES") == 0) strcpy(Frames_Path, value);
return s;
}
void SetOptions(char *s)
{
while (*s) {
switch (*s) {
case 'A' :
case 'a' :
L_option = TRUE;
A_option = TRUE;
S_option = TRUE;
break;
case 'C' :
case 'c' :
C_option = TRUE;
break;
case 'F' :
case 'f' :
L_option = TRUE;
F_option = TRUE;
S_option = TRUE;
break;
case 'G' :
case 'g' :
L_option = TRUE;
G_option = TRUE;
S_option = TRUE;
break;
case 'L' :
case 'l' :
L_option = TRUE;
break;
case 'O' :
case 'o' :
O_option = TRUE;
break;
case 'P' :
case 'p' :
P_option = TRUE;
break;
case 'Q' :
case 'q' :
Q_option = TRUE;
break;
case 'S' :
case 's' :
L_option = TRUE;
S_option = TRUE;
break;
case 'T' :
case 't' :
T_option = TRUE;
break;
case 'D' :
case 'd' :
if (s[1] == '\0')
D_option = TRUE;
else {
s++;
s=SetVar(s);
return;
}
break;
case 'X' :
case 'x' :
GenCplusplus = TRUE;
strcpy(c_ext, "cpp");
strcpy(h_ext, "hpp");
break;
case 'Z' :
case 'z' :
Z_option = TRUE;
strcpy(c_ext, "cpp");
strcpy(h_ext, "hpp");
break;
}
s++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -