📄 cr.atg
字号:
$LSC (*$ACFGILMOSXN*)
(* COCO/R for MS-DOS grammar used to generate COCO/R itself
as adapted by P.D. Terry, January 1992
version 1.48 last modified Mon 11-16-98 *)
COMPILER CR
(*---------------------- semantic declarations -----------------------*)
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;
(*--------------------------------------------------------------------*)
CHARACTERS
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_".
digit = "0123456789".
ctrl = CHR(1) .. CHR(31).
tab = CHR(9).
eol = CHR(13).
lf = CHR(10).
noQuote1 = ANY - '"' - ctrl.
noQuote2 = ANY - "'" - ctrl.
IGNORE tab + eol + lf
TOKENS
ident = letter {letter | digit}.
string = '"' {noQuote1} '"' | "'" {noQuote2} "'".
badstring = '"' {noQuote1} (eol | lf) | "'" {noQuote2} (eol | lf).
number = digit {digit}.
PRAGMAS
Options = "$" {letter | digit} .
(.CRS.GetName(CRS.nextPos, CRS.nextLen, s); SetOption(s); .)
COMMENTS FROM "(*" TO "*)" NESTED
COMMENTS FROM "/*" TO "*/"
PRODUCTIONS
CR (. VAR
ok, undef, hasAttrs: BOOLEAN;
unknownSy,
eofSy, gR: INTEGER;
gramLine, sp: INTEGER;
name, gramName: CRT.Name;
sn: CRT.SymbolNode; .)
=
"COMPILER"
(. gramLine := CRS.line;
eofSy := CRT.NewSym(CRT.t, "EOF", 0);
CRT.genScanner := TRUE; CRT.ignoreCase := FALSE;
Sets.Clear(CRT.ignored) .)
Ident <gramName> (. CRT.semDeclPos.beg := CRS.nextPos .)
{ ANY } (. CRT.semDeclPos.len := FileIO.INTL(CRS.nextPos - CRT.semDeclPos.beg);
CRT.semDeclPos.col := 0 .)
{ Declaration }
SYNC
"PRODUCTIONS" (. ok := Successful();
IF ok & CRT.genScanner THEN CRA.MakeDeterministic(ok) END;
IF ~ ok THEN SemError(127) END;
CRT.nNodes := 0 .)
{ Ident <name> (. sp := CRT.FindSym(name); undef := sp = CRT.noSym;
IF undef THEN
sp := CRT.NewSym(CRT.nt, name, CRS.line);
CRT.GetSym(sp, sn);
ELSE
CRT.GetSym(sp, sn);
IF sn.typ = CRT.nt THEN
IF sn.struct > 0 THEN SemError(107) END
ELSE SemError(108)
END;
sn.line := CRS.line
END;
hasAttrs := sn.attrPos.beg >= FileIO.Long0 .)
( Attribs <sn.attrPos> (. IF ~ undef & ~ hasAttrs THEN SemError(105) END;
CRT.PutSym(sp, sn) .)
| (. IF ~ undef & hasAttrs THEN SemError(105) END .)
)
[ SemText <sn.semPos>]
WEAK "="
Expression <sn.struct, gR> (. CRT.CompleteGraph(gR); CRT.PutSym(sp, sn) .)
WEAK "."
}
"END" Ident <name> (. sp := CRT.FindSym(gramName);
IF sp = CRT.noSym THEN SemError(111);
ELSE
CRT.GetSym(sp, sn);
IF sn.attrPos.beg >= FileIO.Long0 THEN SemError(112) END;
CRT.root := CRT.NewNode(CRT.nt, sp, gramLine);
END;
IF FileIO.Compare(name, gramName) # 0 THEN
SemError(117)
END .)
"." (. unknownSy := CRT.NewSym(CRT.t, "not", 0) .)
.
(*----------------------------------------------------------------------------*)
Declaration (. VAR
gL1, gR1, gL2, gR2: INTEGER;
nested: BOOLEAN; .)
= "CHARACTERS" { SetDecl }
| "TOKENS" { TokenDecl <CRT.t> }
| "NAMES" { NameDecl }
| "PRAGMAS" { TokenDecl <CRT.pr> }
| "COMMENTS"
"FROM" TokenExpr <gL1, gR1>
"TO" TokenExpr <gL2, gR2>
( "NESTED" (. nested := TRUE .)
| (. nested := FALSE .)
)
(. CRA.NewComment(gL1, gL2, nested) .)
| "IGNORE"
( "CASE" (. CRT.ignoreCase := TRUE .)
| Set <CRT.ignored> (. IF Sets.In(CRT.ignored, 0) THEN SemError(119) END .)
)
.
(*----------------------------------------------------------------------------*)
SetDecl (. VAR
c: INTEGER;
set: CRT.Set;
name: CRT.Name; .)
= Ident <name> (. c := CRT.ClassWithName(name);
IF c >= 0 THEN SemError(107) END .)
"=" Set <set> (. c := CRT.NewClass(name, set) .)
".".
(*----------------------------------------------------------------------------*)
Set <VAR set: CRT.Set> (. VAR
set2: CRT.Set; .)
= SimSet <set>
{ "+" SimSet <set2> (. Sets.Unite(set, set2) .)
| "-" SimSet <set2> (. Sets.Differ(set, set2) .)
}.
(*----------------------------------------------------------------------------*)
SimSet <VAR set: CRT.Set> (. VAR
i, n1, n2: CARDINAL;
c: INTEGER;
name: CRT.Name;
s: ARRAY [0 .. 127] OF CHAR; .)
= Ident <name> (. c := CRT.ClassWithName(name);
IF c < 0 THEN SemError(115); Sets.Clear(set)
ELSE CRT.GetClass(c, set)
END .)
| string (. CRS.GetName(CRS.pos, CRS.len, s);
Sets.Clear(set); i := 1;
WHILE s[i] # s[0] DO
IF CRT.ignoreCase THEN s[i] := CAP(s[i]) END;
Sets.Incl(set, ORD(s[i])); INC(i)
END .)
| SingleChar <n1>
(. Sets.Clear(set); Sets.Incl(set, n1) .)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -