crp.mod
来自「一个Modula-2语言分析器」· MOD 代码 · 共 820 行 · 第 1/2 页
MOD
820 行
IMPLEMENTATION MODULE CRP;
(* Parser generated by Coco/R - assuming FileIO library will be available. *)
IMPORT FileIO, CRS;
IMPORT CRT, CRA, Sets;
CONST
ident = 0; string = 1; (* symbol kind *)
TYPE
INT32 = FileIO.INT32;
PROCEDURE FixString (VAR name: ARRAY OF CHAR; len: CARDINAL);
VAR
double, spaces: BOOLEAN;
i: CARDINAL;
BEGIN
IF len = 2 THEN SemError(129); RETURN END;
IF CRT.ignoreCase THEN (* force uppercase *)
FOR i := 1 TO len - 2 DO name[i] := CAP(name[i]) END
END;
double := FALSE; spaces := FALSE;
FOR i := 1 TO len - 2 DO (* search for interior " or spaces *)
IF name[i] = '"' THEN double := TRUE END;
IF name[i] <= ' ' THEN spaces := TRUE END;
END;
IF ~ double THEN (* force delimiters to be " quotes *)
name[0] := '"'; name[len-1] := '"'
END;
IF spaces THEN SemError(124) END;
END FixString;
PROCEDURE MatchLiteral (sp: INTEGER);
(* store string either as token or as literal *)
VAR
sn, sn1: CRT.SymbolNode;
matchedSp: INTEGER;
BEGIN
CRT.GetSym(sp, sn);
CRA.MatchDFA(sn.name, sp, matchedSp);
IF matchedSp # CRT.noSym THEN
CRT.GetSym(matchedSp, sn1);
sn1.struct := CRT.classLitToken;
CRT.PutSym(matchedSp, sn1);
sn.struct := CRT.litToken
ELSE sn.struct := CRT.classToken;
END;
CRT.PutSym(sp, sn)
END MatchLiteral;
PROCEDURE SetCtx (gp: INTEGER);
(* set transition code to CRT.contextTrans *)
VAR
gn: CRT.GraphNode;
BEGIN
WHILE gp > 0 DO
CRT.GetNode(gp, gn);
IF (gn.typ = CRT.char) OR (gn.typ = CRT.class) THEN
gn.p2 := CRT.contextTrans; CRT.PutNode(gp, gn)
ELSIF (gn.typ = CRT.opt) OR (gn.typ = CRT.iter) THEN SetCtx(gn.p1)
ELSIF gn.typ = CRT.alt THEN SetCtx(gn.p1); SetCtx(gn.p2)
END;
gp := gn.next
END
END SetCtx;
PROCEDURE SetOption (s: ARRAY OF CHAR);
VAR
i: CARDINAL;
BEGIN
i := 1;
WHILE s[i] # 0C DO
s[i] := CAP(s[i]);
IF (s[i] >= "A") AND (s[i] <= "Z") THEN CRT.ddt[s[i]] := TRUE END;
INC(i);
END;
END SetOption;
(*--------------------------------------------------------------------*)
CONST
maxT = 41;
maxP = 42;
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 .. 18] 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
CRS.Error(errNo, CRS.line, CRS.col, CRS.pos);
END;
errDist := 0;
END SemError;
PROCEDURE SynError (errNo: INTEGER);
BEGIN
IF errDist >= minErrDist THEN
CRS.Error(errNo, CRS.nextLine, CRS.nextCol, CRS.nextPos);
END;
errDist := 0;
END SynError;
PROCEDURE Get;
VAR
s: ARRAY [0 .. 31] OF CHAR;
BEGIN
REPEAT
CRS.Get(sym);
IF sym <= maxT THEN
INC(errDist);
ELSE
CASE sym OF
42: CRS.GetName(CRS.nextPos, CRS.nextLen, s); SetOption(s);
END;
CRS.nextPos := CRS.pos;
CRS.nextCol := CRS.col;
CRS.nextLine := CRS.line;
CRS.nextLen := CRS.len;
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
CRS.GetName(CRS.pos, CRS.len, Lex)
END LexName;
PROCEDURE LexString (VAR Lex: ARRAY OF CHAR);
BEGIN
CRS.GetString(CRS.pos, CRS.len, Lex)
END LexString;
PROCEDURE LookAheadName (VAR Lex: ARRAY OF CHAR);
BEGIN
CRS.GetName(CRS.nextPos, CRS.nextLen, Lex)
END LookAheadName;
PROCEDURE LookAheadString (VAR Lex: ARRAY OF CHAR);
BEGIN
CRS.GetString(CRS.nextPos, CRS.nextLen, Lex)
END LookAheadString;
PROCEDURE Successful (): BOOLEAN;
BEGIN
RETURN CRS.errors = 0
END Successful;
(* ----- FORWARD not needed in multipass compilers
PROCEDURE TokenFactor (VAR gL, gR: INTEGER); FORWARD;
PROCEDURE TokenTerm (VAR gL, gR: INTEGER); FORWARD;
PROCEDURE Factor (VAR gL, gR: INTEGER); FORWARD;
PROCEDURE Term (VAR gL, gR: INTEGER); FORWARD;
PROCEDURE Symbol (VAR name: CRT.Name; VAR kind: INTEGER); FORWARD;
PROCEDURE SingleChar (VAR n: CARDINAL); FORWARD;
PROCEDURE SimSet (VAR set: CRT.Set); FORWARD;
PROCEDURE Set (VAR set: CRT.Set); FORWARD;
PROCEDURE TokenExpr (VAR gL, gR: INTEGER); FORWARD;
PROCEDURE NameDecl; FORWARD;
PROCEDURE TokenDecl (typ: INTEGER); FORWARD;
PROCEDURE SetDecl; FORWARD;
PROCEDURE Expression (VAR gL, gR: INTEGER); FORWARD;
PROCEDURE SemText (VAR semPos: CRT.Position); FORWARD;
PROCEDURE Attribs (VAR attrPos: CRT.Position); FORWARD;
PROCEDURE Declaration; FORWARD;
PROCEDURE Ident (VAR name: CRT.Name); FORWARD;
PROCEDURE CR; FORWARD;
----- *)
PROCEDURE TokenFactor (VAR gL, gR: INTEGER);
VAR
kind, c: INTEGER;
set: CRT.Set;
name: CRT.Name;
BEGIN
gL :=0; gR := 0;
IF (sym = 1) OR (sym = 2) THEN
Symbol(name, kind);
IF kind = ident THEN
c := CRT.ClassWithName(name);
IF c < 0 THEN
SemError(115);
Sets.Clear(set); c := CRT.NewClass(name, set)
END;
gL := CRT.NewNode(CRT.class, c, 0); gR := gL
ELSE (* string *)
CRT.StrToGraph(name, gL, gR)
END;
ELSIF (sym = 25) THEN
Get;
TokenExpr(gL, gR);
Expect(26);
ELSIF (sym = 29) THEN
Get;
TokenExpr(gL, gR);
Expect(30);
CRT.MakeOption(gL, gR);
ELSIF (sym = 31) THEN
Get;
TokenExpr(gL, gR);
Expect(32);
CRT.MakeIteration(gL, gR);
ELSE SynError(42);
END;
END TokenFactor;
PROCEDURE TokenTerm (VAR gL, gR: INTEGER);
VAR
gL2, gR2: INTEGER;
BEGIN
TokenFactor(gL, gR);
WHILE (sym = 1) OR (sym = 2) OR (sym = 25) OR (sym = 29) OR (sym = 31) DO
TokenFactor(gL2, gR2);
CRT.ConcatSeq(gL, gR, gL2, gR2);
END;
IF (sym = 34) THEN
Get;
Expect(25);
TokenExpr(gL2, gR2);
SetCtx(gL2); CRT.ConcatSeq(gL, gR, gL2, gR2);
Expect(26);
END;
END TokenTerm;
PROCEDURE Factor (VAR gL, gR: INTEGER);
VAR
sp, kind: INTEGER;
name: CRT.Name;
gn: CRT.GraphNode;
sn: CRT.SymbolNode;
set: CRT.Set;
undef, weak: BOOLEAN;
pos: CRT.Position;
BEGIN
gL :=0; gR := 0; weak := FALSE;
CASE sym OF
1, 2, 28 :
IF (sym = 28) THEN
Get;
weak := TRUE;
END;
Symbol(name, kind);
sp := CRT.FindSym(name); undef := sp = CRT.noSym;
IF undef THEN
IF kind = ident THEN (* forward nt *)
sp := CRT.NewSym(CRT.nt, name, 0)
ELSIF CRT.genScanner THEN
sp := CRT.NewSym(CRT.t, name, CRS.line);
MatchLiteral(sp)
ELSE (* undefined string in production *)
SemError(106); sp := 0
END
END;
CRT.GetSym(sp, sn);
IF (sn.typ # CRT.t) & (sn.typ # CRT.nt) THEN SemError(104) END;
IF weak THEN
IF sn.typ = CRT.t THEN sn.typ := CRT.wt
ELSE SemError(123)
END
END;
gL := CRT.NewNode(sn.typ, sp, CRS.line); gR := gL;
IF (sym = 35) OR (sym = 37) THEN
Attribs(pos);
CRT.GetNode(gL, gn); gn.pos := pos;
CRT.PutNode(gL, gn);
CRT.GetSym(sp, sn);
IF sn.typ # CRT.nt THEN SemError(103) END;
IF undef THEN
sn.attrPos := pos; CRT.PutSym(sp, sn)
ELSIF sn.attrPos.beg < FileIO.Long0 THEN SemError(105)
END;
ELSIF In(symSet[1], sym) THEN
CRT.GetSym(sp, sn);
IF sn.attrPos.beg >= FileIO.Long0 THEN SemError(105) END;
ELSE SynError(43);
END;
| 25 :
Get;
Expression(gL, gR);
Expect(26);
| 29 :
Get;
Expression(gL, gR);
Expect(30);
CRT.MakeOption(gL, gR);
| 31 :
Get;
Expression(gL, gR);
Expect(32);
CRT.MakeIteration(gL, gR);
| 39 :
SemText(pos);
gL := CRT.NewNode(CRT.sem, 0, 0); gR := gL;
CRT.GetNode(gL, gn);
gn.pos := pos;
CRT.PutNode(gL, gn);
| 23 :
Get;
Sets.Fill(set); Sets.Excl(set, CRT.eofSy);
gL := CRT.NewNode(CRT.any, CRT.NewSet(set), 0); gR := gL;
| 33 :
Get;
gL := CRT.NewNode(CRT.sync, 0, 0); gR := gL;
ELSE SynError(44);
END;
END Factor;
PROCEDURE Term (VAR gL, gR: INTEGER);
VAR
gL2, gR2: INTEGER;
BEGIN
gL := 0; gR := 0;
IF In(symSet[2], sym) THEN
Factor(gL, gR);
WHILE In(symSet[2], sym) DO
Factor(gL2, gR2);
CRT.ConcatSeq(gL, gR, gL2, gR2);
END;
ELSIF (sym = 8) OR (sym = 26) OR (sym = 27) OR (sym = 30) OR (sym = 32) THEN
gL := CRT.NewNode(CRT.eps, 0, 0); gR := gL;
ELSE SynError(45);
END;
END Term;
PROCEDURE Symbol (VAR name: CRT.Name; VAR kind: INTEGER);
BEGIN
IF (sym = 1) THEN
Ident(name);
kind := ident;
ELSIF (sym = 2) THEN
Get;
CRS.GetName(CRS.pos, CRS.len, name); kind := string;
FixString(name, CRS.len);
ELSE SynError(46);
END;
END Symbol;
PROCEDURE SingleChar (VAR n: CARDINAL);
VAR
i: CARDINAL;
s: ARRAY [0 .. 127] OF CHAR;
BEGIN
Expect(24);
Expect(25);
Expect(4);
CRS.GetName(CRS.pos, CRS.len, s);
n := 0; i := 0;
WHILE s[i] # 0C DO
n := 10 * n + ORD(s[i]) - ORD("0"); INC(i)
END;
IF n > 255 THEN SemError(118); n := n MOD 256 END;
IF CRT.ignoreCase THEN n := ORD(CAP(CHR(n))) END;
Expect(26);
END SingleChar;
PROCEDURE SimSet (VAR set: CRT.Set);
VAR
i, n1, n2: CARDINAL;
c: INTEGER;
name: CRT.Name;
s: ARRAY [0 .. 127] OF CHAR;
BEGIN
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?