Exp BinExp(ExpTag Tag, Exp A, Exp B) { Exp C, D; int Diff; for (As = 0; A->Tag == Tag; A = A->Body.Arg[1]) InsertA(A->Body.Arg[0]); for (Bs = 0; B->Tag == Tag; B = B->Body.Arg[1]) InsertB(B->Body.Arg[0]); if (A->ID > B->ID) C = A, InsertB(B); else C = B, InsertA(A); As--, Bs--; while (As >= 0 || Bs >= 0) { Diff = 0; if (As >= 0) A = AStack[As]; else Diff = -1; if (Bs >= 0) B = BStack[Bs]; else Diff = +1; if (Diff == 0) Diff = A->ID - B->ID; if (Diff <= 0) Bs--, D = B; else As--, D = A; if (Diff == 0 && Tag != ProdX) As--; if (Tag == OrX) { if (C->Tag == ZeroX) { C = D; continue; } if (D->Tag == ZeroX || D == C) continue; } else { if (D->Tag == ZeroX || C->Tag == OneX) { C = D; continue; } if (D->Tag == OneX || C->Tag == ZeroX) continue; if (Tag != ProdX && D == C) continue; } C = MakeExp(Tag, D, C); } return C; }
Exp Parse(void) { Lexical L; Symbol ID; Exp E;//, E0, E1; SP = Stack; L = Scan(); LHS: if (L == SymT) { ID = LastID; L = Scan(); if (L == EqualT) PUSH(EQU, 0), L = Scan(); else { PUSH(RULE, 0); E = MakeExp(SymX, ID); goto END; } } else PUSH(RULE, 0); EXP: switch (L) { case LParT: PUSH(PAR, 0); L = Scan(); goto EXP; case LBrT: PUSH(OPT, 0); L = Scan(); goto EXP; case ZeroT: E = MakeExp(ZeroX); L = Scan(); goto END; case OneT: E = MakeExp(OneX); L = Scan(); goto END; case SymT: E = MakeExp(SymX, LastID); L = Scan(); goto END; default: ERROR("Corrupt expression."); return 0; } END: switch (Action[TOP][L]) { case 'A': ERROR("Extra ','"); L = Scan(); goto END; case 'B': ERROR("Unmatched )."); L = Scan(); goto END; case 'C': ERROR("Unmatched ]."); L = Scan(); goto END; case 'D': ERROR("Unmatched (."); POP(); goto END; case 'E': ERROR("Unmatched [."); POP(); goto MakeOpt; case 'F': ERROR("Left-hand side of '=' must be symbol."); exit(1); case 'G': ERROR("Missing ','."); ID->Value = E; POP(); goto LHS; case '$': POP(); return E; case ',': ID->Value = E; POP(); L = Scan(); goto LHS; case ')': POP(); L = Scan(); goto END; case ']': POP(); case '?': L = Scan(); MakeOpt: E = MakeExp(OptX, E); goto END; case 'x': E = CatExp(POP(), E); goto END; case 'v': E = BinExp(OrX, POP(), E); goto END; case 'X': E = BinExp(ProdX, POP(), E); goto END; case '~': E = MakeExp(DiffX, POP(), E); goto END; case '%': E = BinExp(AndX, POP(), E); goto END; case '.': PUSH(CAT, E); goto EXP; case '|': PUSH(OR, E); L = Scan(); goto EXP; case '-': PUSH(DIFF, E); L = Scan(); goto EXP; case '&': PUSH(AND, E); L = Scan(); goto EXP; case '^': PUSH(PROD, E); L = Scan(); goto EXP; case '*': L = Scan(); E = MakeExp(StarX, E); goto END; case '+': L = Scan(); E = MakeExp(PlusX, E); goto END; } return NULL; }
Exp CatExp(Exp A, Exp B) { Exp E; for (As = 0; A->Tag == CatX; A = A->Body.Arg[1]) InsertA(A->Body.Arg[0]); InsertA(A); while (As-- > 0) { E = AStack[As]; if (E->Tag == ZeroX || B->Tag == OneX) B = E; else if (E->Tag == OneX || B->Tag == ZeroX) ; else B = MakeExp(CatX, E, B); } return B; }
void FormState(int Q) { int I, S, S1, X; int qX, Q1, Q2; int A, B; State SP; Exp E, E1; IBuf = NULL; IMax = 0; STab = NULL; Ss = 0; AddState(1, &Q); for (S = 0; S < Ss; S++) { SP = &STab[S]; for (Xs = 0, S1 = 0; S1 < SP->States; S1++) PushQ(SP->SList[S1]); for (SP->Empty = 0, Is = 0, X = 0; X < Xs; X++) { qX = XStack[X]; EVALUATE: E = EquTab[qX].Value; switch (E->Tag) { case SymX: AddBuf(E->Body.Leaf, MakeExp(-1, OneX)); break; case OneX: SP->Empty = 1; break; case ZeroX: break; case OptX: Q1 = E->Body.Arg[0]; MakeExp(qX, OrX, MakeExp(-1, OneX), E->Body.Arg[0]); goto EVALUATE; case PlusX: Q1 = E->Body.Arg[0]; MakeExp(qX, AndX, Q1, MakeExp(-1, StarX, Q1)); goto EVALUATE; case StarX: Q1 = E->Body.Arg[0]; MakeExp(qX, OrX, MakeExp(-1, OneX), MakeExp(-1, PlusX, Q1)); goto EVALUATE; case OrX: Q1 = E->Body.Arg[0]; Q2 = E->Body.Arg[1]; PushQ(Q1); PushQ(Q2); break; case AndX: Q1 = E->Body.Arg[0], Q2 = E->Body.Arg[1]; E1 = EquTab[Q1].Value; switch (E1->Tag) { case SymX: AddBuf(E1->Body.Leaf, Q2); break; case OneX: EquTab[qX].Value = EquTab[Q2].Value; goto EVALUATE; case ZeroX: MakeExp(qX, ZeroX); break; case OptX: A = E1->Body.Arg[0]; MakeExp(qX, OrX, Q2, MakeExp(-1, AndX, A, Q2)); goto EVALUATE; case PlusX: A = E1->Body.Arg[0]; MakeExp(qX, AndX, A, MakeExp(-1, OrX, Q2, qX)); goto EVALUATE; case StarX: A = E1->Body.Arg[0]; MakeExp(qX, OrX, Q2, MakeExp(-1, AndX, A, qX)); goto EVALUATE; case OrX: A = E1->Body.Arg[0], B = E1->Body.Arg[1]; MakeExp(qX, OrX, MakeExp(-1, AndX, A, Q2), MakeExp(-1, AndX, B, Q2)); goto EVALUATE; case AndX: A = E1->Body.Arg[0], B = E1->Body.Arg[1]; MakeExp(qX, AndX, A, MakeExp(-1, AndX, B, Q2)); goto EVALUATE; } } } while (Xs > 0) PopQ(); SP->Shifts = Is; SP->ShList = cl_malloc(sizeof *SP->ShList * Is); for (I = 0; I < Is; I++) { int rhs_state = -1; SP->ShList[I].LHS = IBuf[I].LHS; rhs_state = AddState(IBuf[I].Size, IBuf[I].RHS); SP = &STab[S]; /* AddState() might have reallocated state table -> update pointer */ SP->ShList[I].RHS = rhs_state; } } free(IBuf); IBuf = 0; Is = IMax = 0; }
/** the regex parser proper: private function */ int Parse(void) { Lexical L; Symbol ID = NULL; int RHS; int ignore_value; /* ignore value of POP() macro */ SP = Stack; LHS: /* get next symbol from the lexer */ L = LEX(); if (L == IdenT) { ID = LookUp(LastW); L = LEX(); if (L == EqualT) { PUSH(EQU, -1); L = LEX(); } else { PUSH(RULE, -1); RHS = MakeExp(-1, SymX, ID); goto END; } } else PUSH(RULE, -1); EXP: switch (L) { case LParT: PUSH(PAR, -1); L = LEX(); goto EXP; case LBrT: PUSH(OPT, -1); L = LEX(); goto EXP; case ZeroT: RHS = MakeExp(-1, ZeroX); L = LEX(); goto END; case OneT: RHS = MakeExp(-1, OneX); L = LEX(); goto END; case IdenT: RHS = MakeExp(-1, SymX, LookUp(LastW)); L = LEX(); goto END; default: REGEX2DFA_ERROR("Corrupt expression."); return -1; } END: switch (Action[TOP][L]) { case 'A': REGEX2DFA_ERROR("Extra ','"); rcqp_receive_error(1); case 'B': REGEX2DFA_ERROR("Unmatched )."); L = LEX(); goto END; case 'C': REGEX2DFA_ERROR("Unmatched ]."); L = LEX(); goto END; case 'D': REGEX2DFA_ERROR("Unmatched (."); ignore_value = POP(); goto END; case 'E': REGEX2DFA_ERROR("Unmatched [."); goto MakeOpt; case 'F': REGEX2DFA_ERROR("( ... ]."); ignore_value = POP(); L = LEX(); goto END; case 'G': REGEX2DFA_ERROR("[ ... )."); L = LEX(); goto MakeOpt; case 'H': REGEX2DFA_ERROR("Left-hand side of '=' must be symbol."); rcqp_receive_error(1); case 'I': REGEX2DFA_ERROR("Missing evaluation."); rcqp_receive_error(1); case '.': ignore_value = POP(); return RHS; case ')': ignore_value = POP(); L = LEX(); goto END; case ']': L = LEX(); MakeOpt: ignore_value = POP(); RHS = MakeExp(-1, OptX, RHS); goto END; case '=': Store(ID, RHS); ignore_value = POP(); goto LHS; case 'v': RHS = MakeExp(-1, OrX, POP(), RHS); goto END; case 'x': RHS = MakeExp(-1, AndX, POP(), RHS); goto END; case '*': RHS = MakeExp(-1, StarX, RHS); L = LEX(); goto END; case '+': RHS = MakeExp(-1, PlusX, RHS); L = LEX(); goto END; case '|': PUSH(OR, RHS); L = LEX(); goto EXP; case '&': PUSH(AND, RHS); goto EXP; } assert(0 && "Not reached"); return 0; }
void FormStates(Exp E) { int S, I, Diff; Exp A, B; int AX, BX; STab = 0, Ss = 0; AddState(MakeExp(ZeroX)); AddState(E); TList = 0, TMax = 0; for (S = 0; S < Ss; S++) { PushQ(STab[S]); while (Xs > 0) { E = XStack[Xs - 1]; if (E->Normal) { PopQ(); continue; } switch (E->Tag) { case ZeroX: case OneX: E->Terms = 0, E->Sum = 0, E->Normal = 1; PopQ(); break; case SymX: E->Terms = 1, E->Sum = Allocate(sizeof *E->Sum); E->Sum[0].X = E->Body.Leaf, E->Sum[0].Q = MakeExp(OneX); E->Normal = 1; PopQ(); break; case OptX: A = E->Body.Arg[0]; if (!A->Normal) { PushQ(A); continue; } E->Terms = A->Terms, E->Sum = A->Sum; E->Normal = 1; PopQ(); break; case StarX: case PlusX: A = E->Body.Arg[0]; if (!A->Normal) { PushQ(A); continue; } B = E->Unit? E: MakeExp(StarX, A); Catenate: E->Terms = A->Terms; E->Sum = Allocate(E->Terms * sizeof *E->Sum); for (I = 0; I < E->Terms; I++) E->Sum[I].X = A->Sum[I].X, E->Sum[I].Q = CatExp(A->Sum[I].Q, B); E->Normal = 1; PopQ(); break; case CatX: case OrX: case AndX: case DiffX: case ProdX: A = E->Body.Arg[0]; if (!A->Normal) { PushQ(A); continue; } B = E->Body.Arg[1]; if (E->Tag == CatX && !A->Unit) goto Catenate; if (!B->Normal) { PushQ(B); continue; } for (AX = BX = Ts = 0; AX < A->Terms || BX < B->Terms; ) { Exp dA, dB; Symbol xA, xB; Diff = 0; if (AX >= A->Terms) Diff = 1; else dA = A->Sum[AX].Q, xA = A->Sum[AX].X; if (BX >= B->Terms) Diff = -1; else dB = B->Sum[BX].Q, xB = B->Sum[BX].X; if (Diff == 0) Diff = strcmp(xA->Name, xB->Name); if (Diff <= 0) AX++; if (Diff >= 0) BX++; switch (E->Tag) { case AndX: if (Diff == 0) AddTerm(xA, BinExp(AndX, dA, dB)); break; case CatX: if (Diff <= 0) dA = CatExp(dA, B); goto Join; case ProdX: if (Diff <= 0) dA = BinExp(ProdX, dA, B); if (Diff >= 0) dB = BinExp(ProdX, dB, A); case OrX: Join: if (Diff < 0) AddTerm(xA, dA); else if (Diff > 0) AddTerm(xB, dB); else AddTerm(xA, BinExp(OrX, dA, dB)); break; case DiffX: if (Diff == 0) dA = MakeExp(DiffX, dA, dB); if (Diff <= 0) AddTerm(xA, dA); break; default: break; } } E->Terms = Ts; E->Sum = Allocate(E->Terms * sizeof *E->Sum); for (I = 0; I < Ts; I++) E->Sum[I] = TList[I]; E->Normal = 1; PopQ(); break; } } E = STab[S]; for (I = 0; I < E->Terms; I++) AddState(E->Sum[I].Q); } free(XStack), XMax = 0; free(TList), TMax = 0; }