IMPLEMENTATION MODULE M2cP; (* Parser generated by Coco/R - assuming ISO IO library will be available. *) IMPORT M2cS, FileIO; CONST maxT = 7; minErrDist = 2; (* minimal distance (good tokens) between two errors *) setsize = 16; (* sets are stored in 16 bits *) TYPE SymbolSet = ARRAY [0 .. maxT DIV setsize] OF BITSET; VAR symSet: ARRAY [0 .. 0] OF SymbolSet; (*symSet[0] = allSyncSyms*) errDist: CARDINAL; (* number of symbols recognized since last error *) sym: CARDINAL; (* current input symbol *) PROCEDURE SemError (errNo: INTEGER); BEGIN IF errDist >= minErrDist THEN M2cS.Error(errNo, M2cS.line, M2cS.col, M2cS.pos); END; errDist := 0; END SemError; PROCEDURE SynError (errNo: INTEGER); BEGIN IF errDist >= minErrDist THEN M2cS.Error(errNo, M2cS.nextLine, M2cS.nextCol, M2cS.nextPos); END; errDist := 0; END SynError; PROCEDURE Get; VAR s: ARRAY [0 .. 31] OF CHAR; BEGIN REPEAT M2cS.Get(sym); IF sym <= maxT THEN INC(errDist); ELSE END; UNTIL sym <= maxT END Get; PROCEDURE In (VAR s: SymbolSet; x: CARDINAL): BOOLEAN; BEGIN RETURN x MOD setsize IN s[x DIV setsize]; END In; PROCEDURE Expect (n: CARDINAL); BEGIN IF sym = n THEN Get ELSE SynError(n) END END Expect; PROCEDURE ExpectWeak (n, follow: CARDINAL); BEGIN IF sym = n THEN Get ELSE SynError(n); WHILE ~ In(symSet[follow], sym) DO Get END END END ExpectWeak; PROCEDURE WeakSeparator (n, syFol, repFol: CARDINAL): BOOLEAN; VAR s: SymbolSet; i: CARDINAL; BEGIN IF sym = n THEN Get; RETURN TRUE ELSIF In(symSet[repFol], sym) THEN RETURN FALSE ELSE i := 0; WHILE i <= maxT DIV setsize DO s[i] := symSet[0, i] + symSet[syFol, i] + symSet[repFol, i]; INC(i) END; SynError(n); WHILE ~ In(s, sym) DO Get END; RETURN In(symSet[syFol], sym) END END WeakSeparator; PROCEDURE LexName (VAR Lex: ARRAY OF CHAR); BEGIN M2cS.GetName(M2cS.pos, M2cS.len, Lex) END LexName; PROCEDURE LexString (VAR Lex: ARRAY OF CHAR); BEGIN M2cS.GetString(M2cS.pos, M2cS.len, Lex) END LexString; PROCEDURE LookAheadName (VAR Lex: ARRAY OF CHAR); BEGIN M2cS.GetName(M2cS.nextPos, M2cS.nextLen, Lex) END LookAheadName; PROCEDURE LookAheadString (VAR Lex: ARRAY OF CHAR); BEGIN M2cS.GetString(M2cS.nextPos, M2cS.nextLen, Lex) END LookAheadString; PROCEDURE Successful (): BOOLEAN; BEGIN RETURN M2cS.errors = 0 END Successful; (* ----- FORWARD not needed in multipass compilers PROCEDURE M2c; FORWARD; ----- *) PROCEDURE M2c; VAR m1, m2: ARRAY [0 .. 63] OF CHAR; i: CARDINAL; same: BOOLEAN; BEGIN Expect(2); Expect(1); LexName(m1);; Expect(3); IF (sym = 4) THEN Get; END; Expect(5); Expect(1); LexName(m2); i := 0; same := TRUE; WHILE same & ((m1[i] # 0C) OR (m2[i] # 0C)) DO IF m1[i] # m2[i] THEN same := FALSE END; INC(i) END; IF ~same THEN SemError(202) END;; Expect(6); END M2c; PROCEDURE Parse; BEGIN M2cS.Reset; Get; M2c; END Parse; BEGIN errDist := minErrDist; symSet[ 0, 0] := BITSET{0}; END M2cP.