/********************************************************** ** PARSER_C.FRM ** Coco/R C Support Frames. ** Author: Frankie Arzu ** ** Jun 12, 1996 Version 1.06 ** Many fixes and suggestions thanks to ** Pat Terry **********************************************************/ #include "crs.h" #include "crp.h" #include "crt.h" #include "crf.h" #include "cra.h" #include "crp.h" #include "crs.h" #include #include static void FixString(char *name) { int i, j, len, spaces, start; len = strlen(name); if (len == 2) { SemError(129); return; } if (ignore_case) upcase(name); spaces = FALSE; start = name[0]; for (i = 1; i <= len-2; i++) { if (name[i] > 0 && name[i] <= ' ') spaces = TRUE; if (name[i] == '\\') { if (name[i+1] == '\\' || name[i+1] == '\'' || name[i+1] == '\"') { for (j = i; j < len; j++) name[j] = name[j+1]; len--; } } } if (spaces) SemError(124); } static void MatchLiteral (int sp) /* store string either as token or as literal */ { PTermNode sn, sn1; int matched_sp; sn = GetTermP(sp); matched_sp = MatchDFA((unsigned char *) sn->name, sp); if (matched_sp != 0) { sn1 = GetTermP(matched_sp); sn1->type = T_CLASSLITTOKEN; sn->type = T_LITTOKEN; } else sn->type= T_CLASSTOKEN; } static void SetCtx (int gp) /* set transition code to contextTrans */ { PGraphNode gn; while (gp > 0) { gn = GetGraphP(gp); if (gn->type == T_CHAR || gn->type == T_CLASS) gn->CONTEXT = T_CONTEXT; else if (gn->type == T_OPT || gn->type == T_REP) SetCtx(gn->INNER); else if (gn->type == T_ALT) { SetCtx(gn->INNER); SetCtx(gn->ALT); } gp = gn->next; } } static void StringClass(char *s, Set *items) { s[strlen(s)-1]=0; s++; /* Ignore First and Last character */ while (*s) Set_AddItem(items, *s++); } /**************************************************************************/ Error_Func Custom_Error = 0L; static int Sym; static int errors = 0; /*number of detected errors*/ static int ErrDist = MinErrDist; #define MAXSYM 3 /* Production prototypes */ static void CR(void); static void Ident(char *s); static void Declaration(int *startedDFA); static void Attribs(int *n); static void SemText(int *n); static void Expression(int *n); static void SetDecl(void); static void TokenDecl(int sec_type); static void NameDecl(void); static void TokenExpr(int *n); static void CompSet(PSet items); static void SimSet(PSet items); static void String(char *s); static void ChrSet(int *n); static void Term(int *n); static void Factor(int *n); static void Symbol(char *name); static void TokenTerm(int *n); static void TokenFactor(int *n); #define NSETBITS 16 static unsigned short int SymSet[][MAXSYM] = { /*EOF_Sym identSym stringSym PRODUCTIONSSym EqualSym ENDSym CHARACTERSSym TOKENSSym NAMESSym PRAGMASSym COMMENTSSym IGNORESym LparenPointSym */ {0x7EC7,0x4,0x80}, /*identSym stringSym PointSym ANYSym LparenSym BarSym WEAKSym LbrackSym LbraceSym SYNCSym LparenPointSym */ {0x106,0xBA80,0x82}, /*identSym ENDSym */ {0x202,0x0,0x0}, /*PointSym RparenSym RbrackSym RbraceSym */ {0x100,0x4400,0x1}, /*identSym stringSym PointSym ANYSym LparenSym RparenSym BarSym WEAKSym LbrackSym RbrackSym LbraceSym RbraceSym SYNCSym LparenPointSym */ {0x106,0xFE80,0x83}, /*PRODUCTIONSSym PointSym CHARACTERSSym TOKENSSym NAMESSym PRAGMASSym COMMENTSSym TOSym NESTEDSym IGNORESym RparenSym RbrackSym RbraceSym */ {0x7D40,0x4407,0x1}, /*identSym stringSym LparenSym LbrackSym LbraceSym */ {0x6,0xA200,0x0}, {0x0} }; void GenError(int errno) { if (ErrDist >= MinErrDist) { if (Custom_Error != 0L) (*Custom_Error) (errno, S_NextLine, S_NextCol, S_NextPos); errors++; } ErrDist = 0; } void SynError(int errno) { if (errno <= MAXERROR) errno = MAXERROR; if (ErrDist >= MinErrDist) { if (Custom_Error != 0L) (*Custom_Error) (errno, S_NextLine, S_NextCol, S_NextPos); errors++; } ErrDist = 0; } void SemError(int errno) { if (errno <= MAXERROR) errno = MAXERROR; if (ErrDist >= MinErrDist) { if (Custom_Error != 0L) (*Custom_Error) (errno, S_Line, S_Col, S_Pos); errors++; } ErrDist = 0; } static void Get(void) { do { Sym = S_Get(); if (Sym <= MAXT) ErrDist ++; else { if (Sym == OptionsSym) { /*42*/ char s[100]; LookAheadString(s, sizeof(s)-1); SetOptions(s); } else /* Empty Stmt */ ; S_NextPos = S_Pos; S_NextCol = S_Col; S_NextLine = S_Line; S_NextLen = S_Len; } } while (Sym > MAXT); } static int In (unsigned short int *SymbolSet, int i) { return SymbolSet[i / NSETBITS] & (1 << (i % NSETBITS)); } static void Expect (int n) { if (Sym == n) Get(); else GenError(n); } static void ExpectWeak (int n, int follow) { if (Sym == n) Get(); else { GenError(n); while (!(In(SymSet[follow], Sym) || In(SymSet[0], Sym))) Get(); } } static int WeakSeparator (int n, int syFol, int repFol) { unsigned short int s[MAXSYM]; int i; if (Sym == n) { Get(); return 1; } if (In(SymSet[repFol], Sym)) return 0; for (i = 0; i < MAXSYM; i++) s[i] = SymSet[0][i] | SymSet[syFol][i] | SymSet[repFol][i]; GenError(n); while (!In(s, Sym)) Get(); return In(SymSet[syFol], Sym); } int Successful(void) { return errors == 0; } /* Productions */ static void CR(void) { Name name1; int attr, sem, exp, is_new, sp, type; int startedDFA = FALSE; PNTermNode sn; Expect(COMPILERSym); Ident(compiler_name); global_defs.pos = S_NextPos; global_defs.line = S_NextLine; while (Sym >= identSym && Sym <= COMPILERSym || Sym >= EqualSym && Sym <= ENDSym || Sym >= FROMSym && Sym <= NESTEDSym || Sym >= CASESym && Sym <= No_Sym) { Get(); } global_defs.len = (int) (S_NextPos-global_defs.pos); while (Sym >= CHARACTERSSym && Sym <= COMMENTSSym || Sym == IGNORESym) { Declaration(&startedDFA); } while (!(Sym == EOF_Sym || Sym == PRODUCTIONSSym)) { GenError(43); Get(); } if (Successful()) { /* No Errors so far */ if (!MakeDeterministic()) SemError(127); }; Expect(PRODUCTIONSSym); while (Sym == identSym) { attr = NIL; sem = NIL; Ident(name1); if ((sp = FindSym(name1, &type)) != UNDEF) { is_new = FALSE; if (type != T_NT) { SemError(108); return; } else { sn = GetNTermP(sp); if (sn->graph) SemError(107); sn->line_dec = S_Line; } } else { sp = NewSym(name1, T_NT); sn = GetNTermP(sp); is_new = TRUE; sn->line_dec = S_Line; }; if (Sym == LessSym || Sym == LessPointSym) { Attribs(&attr); } if (!is_new) { if (sn->has_attr && !attr) SemError(105); if (!sn->has_attr && attr) SemError(105); } if (attr) { sn->attr = attr; sn->has_attr = TRUE; }; ExpectWeak(EqualSym,1); if (Sym == LparenPointSym) { SemText(&sem); } Expression(&exp); if (sem) { (void) LinkGraph(sem, exp); exp = sem; }; ExpectWeak(PointSym,2); sn = GetNTermP(sp); /* reload */ sn->graph = exp; while (!(Sym >= EOF_Sym && Sym <= identSym || Sym == ENDSym)) { GenError(44); Get(); } } Expect(ENDSym); Ident(name1); if (strcmp(name1, compiler_name)) SemError(117); if((sp = FindSym(compiler_name, &type)) != UNDEF) { if (type!=T_NT) SemError(108); else { sn = GetNTermP(sp); if (sn->has_attr) SemError(112); sn->reachable=TRUE; } } else SemError(111); no_sym = NewSym("not", T_T); Expect(PointSym); if (dirty_DFA && !MakeDeterministic()) SemError(127); } static void Ident(char *s) { Expect(identSym); LexString(s, MAX_ID_LEN-1); } static void Declaration(int *startedDFA) { Set ignore; int n1, n2, nested = FALSE; switch (Sym) { case CHARACTERSSym: Get(); while (Sym == identSym) { SetDecl(); } break; case TOKENSSym: Get(); while (Sym >= identSym && Sym <= stringSym) { TokenDecl(T_T); } break; case NAMESSym: Get(); while (Sym == identSym) { NameDecl(); } break; case PRAGMASSym: Get(); while (Sym >= identSym && Sym <= stringSym) { TokenDecl(T_P); } break; case COMMENTSSym: Get(); Expect(FROMSym); TokenExpr(&n1); Expect(TOSym); TokenExpr(&n2); if (Sym == NESTEDSym) { Get(); nested = TRUE; } if (n1 * n2) NewComment(n1, n2, nested); break; case IGNORESym: Get(); if (Sym == CASESym) { Get(); if (*startedDFA) SemError(130); ignore_case = TRUE; } else if (Sym >= identSym && Sym <= stringSym || Sym >= ANYSym && Sym <= CHRSym) { Set_Init(&ignore); CompSet(&ignore); AddIgnore(&ignore); if (Set_IsItem(&ignore,0)) SemError(119); Set_Done(&ignore); } else GenError(45); break; default :GenError(46); break; } *startedDFA = TRUE; } static void Attribs(int *n) { long P; int Len, Line, Col; if (Sym == LessSym) { Get(); P = S_Pos+1; Line = S_Line; Col = S_Col; while (Sym >= identSym && Sym <= LessSym || Sym >= LessPointSym && Sym <= No_Sym) { if (Sym >= identSym && Sym <= stringSym || Sym >= numberSym && Sym <= LessSym || Sym >= LessPointSym && Sym <= No_Sym) { Get(); } else if (Sym == badstringSym) { Get(); SemError(102); } else GenError(47); } Expect(GreaterSym); Len = (int) (S_Pos - P); *n = MakeSemGraph(T_ATTR, P, Len, Line, Col); } else if (Sym == LessPointSym) { Get(); P = S_Pos+2; Line = S_Line; Col = S_Col; while (Sym >= identSym && Sym <= LessPointSym || Sym >= LparenPointSym && Sym <= No_Sym) { if (Sym >= identSym && Sym <= stringSym || Sym >= numberSym && Sym <= LessPointSym || Sym >= LparenPointSym && Sym <= No_Sym) { Get(); } else if (Sym == badstringSym) { Get(); SemError(102); } else GenError(48); } Expect(PointGreaterSym); Len = (int) (S_Pos - P); *n = MakeSemGraph(T_ATTR, P, Len, Line, Col); } else GenError(49); } static void SemText(int *n) { long P; int Len, Line, Col; Expect(LparenPointSym); P = S_Pos+2; Line = S_Line; Col = S_Col; while (Sym >= identSym && Sym <= LparenPointSym || Sym == No_Sym) { if (Sym >= identSym && Sym <= stringSym || Sym >= numberSym && Sym <= PointGreaterSym || Sym == No_Sym) { Get(); } else if (Sym == badstringSym) { Get(); SemError(102); } else if (Sym == LparenPointSym) { Get(); SemError(109); } else GenError(50); } Expect(PointRparenSym); Len = (int) (S_Pos - P); *n = MakeSemGraph(T_SEM, P, Len, Line, Col); } static void Expression(int *n) { int n0 = NIL, n1, n2, SX_Line; Term(&n1); while (WeakSeparator(BarSym,4,3)) { if (n0 == NIL) n0 = n1 = MakeGraph(T_ALT, n1); SX_Line = S_Line; Term(&n2); n2 = MakeGraph(T_ALT, n2); SetGraphLine(n2,SX_Line); n1 = LinkAltGraph(n1, n2); } *n = (n0 ? n0 : n1); } static void SetDecl(void) { Name name; Set items; Set_Init(&items); Ident(name); if (FindClass(name) != UNDEF) SemError(107); Expect(EqualSym); CompSet(&items); Expect(PointSym); if (Set_Empty(&items)) SemError(101); (void) NewClass(name, &items); Set_Done(&items); } static void TokenDecl(int sec_type) { char name[MAX_STR_LEN]; int p = 0, sp, type; if (Sym == identSym) { Ident(name); if ((sp = FindSym(name, &type)) != UNDEF) SemError(107); else sp = NewSym(name, sec_type); while (!(Sym >= EOF_Sym && Sym <= stringSym || Sym >= PRODUCTIONSSym && Sym <= EqualSym || Sym >= CHARACTERSSym && Sym <= COMMENTSSym || Sym == IGNORESym || Sym == LparenPointSym)) { GenError(51); Get(); } if (Sym == EqualSym) { Get(); TokenExpr(&p); if (sec_type == T_T) ConvertToStates(p, sp); else ConvertToStates(p, sp+FIRST_PRAGMA); Expect(PointSym); } else if (Sym >= identSym && Sym <= stringSym || Sym == PRODUCTIONSSym || Sym >= CHARACTERSSym && Sym <= COMMENTSSym || Sym == IGNORESym || Sym == LparenPointSym) { P_option = TRUE; } else GenError(52); } else if (Sym == stringSym) { String(name); P_option = TRUE; if ((sp = FindSym(name, &type)) != UNDEF) SemError(107); else sp = NewSym(name, sec_type); } else GenError(53); if (Sym == LparenPointSym) { SemText(&p); if (sec_type == T_T) SemError(114); else SetPragmaText(sp, p); } } static void NameDecl(void) { Name username, name; Ident(username); Expect(EqualSym); if (Sym == identSym) { Ident(name); } else if (Sym == stringSym) { String(name); } else GenError(54); Expect(PointSym); NewName(name, username); } static void TokenExpr(int *n) { int n0 = NIL, n1, n2; TokenTerm(&n1); while (WeakSeparator(BarSym,6,5)) { if (n0 == NIL) n0 = n1 = MakeGraph(T_ALT, n1); TokenTerm(&n2); n2 = MakeGraph(T_ALT, n2); n1 = LinkAltGraph(n1, n2); } *n = (n0 ? n0 : n1); } static void CompSet(PSet items) { Set set1, set2; Set_Init(&set1); Set_Init(&set2); SimSet(&set1); while (Sym >= PlusSym && Sym <= MinusSym) { if (Sym == PlusSym) { Get(); SimSet(&set2); Set_Union(&set1, &set2); } else if (Sym == MinusSym) { Get(); SimSet(&set2); Set_Diference(&set1, &set2); } else GenError(55); Set_Clean(&set2); } Set_Union(items, &set1); Set_Done(&set1); Set_Done(&set2); } static void SimSet(PSet items) { Name name; char str[MAX_STR_LEN]; int n1, n2; switch (Sym) { case identSym: Ident(name); if (FindClass(name) == UNDEF) SemError(115); GetClassWithName(name, items); break; case stringSym: String(str); StringClass(str, items); break; case CHRSym: ChrSet(&n1); if (Sym == Range) { Get(); ChrSet(&n2); Set_AddRange(items, n1, n2); } else if (Sym == PRODUCTIONSSym || Sym == PointSym || Sym >= CHARACTERSSym && Sym <= COMMENTSSym || Sym == IGNORESym || Sym >= PlusSym && Sym <= MinusSym) { Set_AddItem(items, n1); } else GenError(56); break; case ANYSym: Get(); Set_Union(items, &ANY_SET); break; default :GenError(57); break; } } static void String(char *s) { Expect(stringSym); LexString(s, MAX_STR_LEN-1); FixString(s); } static void ChrSet(int *n) { char str[5]; int x; Expect(CHRSym); Expect(LparenSym); if (Sym == numberSym) { Get(); LexString(str, sizeof(str)-1); x = atoi(str); if (x > 255) { SemError(118); x = 0; } *n = x; } else if (Sym == stringSym) { Get(); LexString(str, sizeof(str)-1); if (strlen(str) != 3) SemError(118); *n = str[1]; } else GenError(58); Expect(RparenSym); } static void Term(int *n) { int n0 = NIL, n1, n2; if (Sym >= identSym && Sym <= stringSym || Sym == ANYSym || Sym == LparenSym || Sym >= WEAKSym && Sym <= LbrackSym || Sym == LbraceSym || Sym == SYNCSym || Sym == LparenPointSym) { Factor(&n1); n0 = n1; while (Sym >= identSym && Sym <= stringSym || Sym == ANYSym || Sym == LparenSym || Sym >= WEAKSym && Sym <= LbrackSym || Sym == LbraceSym || Sym == SYNCSym || Sym == LparenPointSym) { Factor(&n2); n1 = LinkGraph(n1, n2); } } else if (Sym == PointSym || Sym >= RparenSym && Sym <= BarSym || Sym == RbrackSym || Sym == RbraceSym) { n0 = MakeSemGraph(T_SEM, -1, 0, S_Line, S_Col); } *n = n0; } static void Factor(int *n) { char name1[MAX_STR_LEN]; int weak = 0, SX_Line; int n1, n2 = NIL; int sp, is_new, type; PNTermNode snt; switch (Sym) { case identSym: case stringSym: case WEAKSym: if (Sym == WEAKSym) { Get(); weak = 1; } Symbol(name1); sp = FindSym(name1, &type); if (type == T_CLASS) SemError(104); if (weak && type == T_T) type = T_WT; if (weak && type == T_NT) SemError(123); n1 = MakeGraph(type, sp); if (type == T_NT) { snt = GetNTermP(sp); is_new = snt->graph == 0; snt->line_use = S_Line; snt->reachable = TRUE; }; if (Sym == LessSym || Sym == LessPointSym) { Attribs(&n2); (void) LinkAltGraph(n1, n2); if (type != T_NT) SemError(103); else { if(!is_new && !snt->has_attr) SemError(105); if (is_new) snt->has_attr = TRUE; }; } else if (Sym >= identSym && Sym <= stringSym || Sym == PointSym || Sym == ANYSym || Sym >= LparenSym && Sym <= SYNCSym || Sym == LparenPointSym) { if (type == T_NT) if (!is_new && snt->has_attr) SemError(105); } else GenError(59); break; case LparenSym: Get(); Expression(&n1); Expect(RparenSym); break; case LbrackSym: Get(); SX_Line = S_Line; Expression(&n1); Expect(RbrackSym); n1 = MakeGraph(T_OPT, n1); SetGraphLine(n1,SX_Line); break; case LbraceSym: Get(); SX_Line = S_Line; Expression(&n1); Expect(RbraceSym); n1 = MakeGraph(T_REP, n1); SetGraphLine(n1,SX_Line); break; case LparenPointSym: SemText(&n1); break; case ANYSym: Get(); n1 = MakeGraph(T_ANY, 0); break; case SYNCSym: Get(); n1 = MakeGraph(T_SYNC, 0); break; default :GenError(60); break; } *n = n1; } static void Symbol(char *name) { int sp, type; if (Sym == identSym) { Ident(name); sp = FindSym(name, &type); if (sp == UNDEF) sp = NewSym(name, T_NT); } else if (Sym == stringSym) { String(name); sp = FindSym(name, &type); if (sp == UNDEF) { sp = NewSym(name, T_T); MatchLiteral(sp); }; } else GenError(61); } static void TokenTerm(int *n) { int n0 = NIL, n1, n2; TokenFactor(&n1); n0 = n1; while (Sym >= identSym && Sym <= stringSym || Sym == LparenSym || Sym == LbrackSym || Sym == LbraceSym) { TokenFactor(&n2); n1 = LinkGraph(n1, n2); } if (Sym == CONTEXTSym) { Get(); Expect(LparenSym); TokenExpr(&n2); Expect(RparenSym); SetCtx(n2); n1 = LinkGraph(n1, n2); } *n = n0; } static void TokenFactor(int *n) { char name[MAX_STR_LEN]; int p = 0; switch (Sym) { case identSym: Ident(name); if ((p = FindClass(name)) == UNDEF) { /* Just Create a valid node */ p = MakeGraph(T_CHAR, 0); SemError(115); } else p = MakeGraph(T_CLASS, p); break; case stringSym: String(name); p = StrToGraph((unsigned char *) name); break; case LparenSym: Get(); TokenExpr(&p); Expect(RparenSym); break; case LbrackSym: Get(); TokenExpr(&p); Expect(RbrackSym); p = MakeGraphOp(T_OPT, p); break; case LbraceSym: Get(); TokenExpr(&p); Expect(RbraceSym); p = MakeGraphOp(T_REP, p); break; default :GenError(62); break; } *n = p; } void Parse(void) { S_Reset(); Get(); CR(); }