📄 parser.cs
字号:
/*----------------------------------------------------------------------
Compiler Generator Coco/R,
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
extended by M. Loeberbauer & A. Woess, Univ. of Linz
with improvements by Pat Terry, Rhodes University
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
As an exception, it is allowed to write an extension of Coco/R that is
used as a plugin in non-free software.
If not otherwise stated, any source code generated by Coco/R (other than
Coco/R itself) does not fall under the GNU General Public License.
----------------------------------------------------------------------*/
using System.Collections;
using System;
namespace at.jku.ssw.Coco {
public class Parser {
const int _EOF = 0;
const int _ident = 1;
const int _number = 2;
const int _string = 3;
const int _badString = 4;
const int _char = 5;
const int maxT = 41;
const bool T = true;
const bool x = false;
const int minErrDist = 2;
public static Token t; // last recognized token
public static Token la; // lookahead token
static int errDist = minErrDist;
const int id = 0;
const int str = 1;
static bool genScanner;
static string tokenString; // used in declarations of literal tokens
static string noString = "-none-"; // used in declarations of literal tokens
/*-------------------------------------------------------------------------*/
static void SynErr (int n) {
if (errDist >= minErrDist) Errors.SynErr(la.line, la.col, n);
errDist = 0;
}
public static void SemErr (string msg) {
if (errDist >= minErrDist) Errors.Error(t.line, t.col, msg);
errDist = 0;
}
static void Get () {
for (;;) {
t = la;
la = Scanner.Scan();
if (la.kind <= maxT) { ++errDist; break; }
if (la.kind == 42) {
Tab.SetDDT(la.val);
}
la = t;
}
}
static void Expect (int n) {
if (la.kind==n) Get(); else { SynErr(n); }
}
static bool StartOf (int s) {
return set[s, la.kind];
}
static void ExpectWeak (int n, int follow) {
if (la.kind == n) Get();
else {
SynErr(n);
while (!StartOf(follow)) Get();
}
}
static bool WeakSeparator (int n, int syFol, int repFol) {
bool[] s = new bool[maxT+1];
if (la.kind == n) { Get(); return true; }
else if (StartOf(repFol)) return false;
else {
for (int i=0; i <= maxT; i++) {
s[i] = set[syFol, i] || set[repFol, i] || set[0, i];
}
SynErr(n);
while (!s[la.kind]) Get();
return StartOf(syFol);
}
}
static void Coco() {
Symbol sym; Graph g, g1, g2; string gramName;
if (la.kind == 39) {
UsingDecl(out ParserGen.usingPos);
}
Expect(6);
genScanner = true; Tab.ignored = null;
Expect(1);
gramName = t.val;
int beg = la.pos;
while (StartOf(1)) {
Get();
}
Tab.semDeclPos = new Position(beg, la.pos-beg, 0);
if (la.kind == 7) {
Get();
DFA.ignoreCase = true;
}
if (la.kind == 8) {
Get();
while (la.kind == 1) {
SetDecl();
}
}
if (la.kind == 9) {
Get();
while (la.kind == 1 || la.kind == 3 || la.kind == 5) {
TokenDecl(Node.t);
}
}
if (la.kind == 10) {
Get();
while (la.kind == 1 || la.kind == 3 || la.kind == 5) {
TokenDecl(Node.pr);
}
}
while (la.kind == 11) {
Get();
bool nested = false;
Expect(12);
TokenExpr(out g1);
Expect(13);
TokenExpr(out g2);
if (la.kind == 14) {
Get();
nested = true;
}
new Comment(g1.l, g2.l, nested);
}
while (la.kind == 15) {
Get();
Set(out Tab.ignored);
Tab.ignored[' '] = true; /* ' ' is always ignored */
}
while (!(la.kind == 0 || la.kind == 16)) {SynErr(42); Get();}
Expect(16);
if (genScanner) DFA.MakeDeterministic();
Graph.DeleteNodes();
while (la.kind == 1) {
Get();
sym = Symbol.Find(t.val);
bool undef = sym == null;
if (undef) sym = new Symbol(Node.nt, t.val, t.line);
else {
if (sym.typ == Node.nt) {
if (sym.graph != null) SemErr("name declared twice");
} else SemErr("this symbol kind not allowed on left side of production");
sym.line = t.line;
}
bool noAttrs = sym.attrPos == null;
sym.attrPos = null;
if (la.kind == 24) {
AttrDecl(sym);
}
if (!undef)
if (noAttrs != (sym.attrPos == null))
SemErr("attribute mismatch between declaration and use of this symbol");
if (la.kind == 37) {
SemText(out sym.semPos);
}
ExpectWeak(17, 2);
Expression(out g);
sym.graph = g.l;
Graph.Finish(g);
ExpectWeak(18, 3);
}
Expect(19);
Expect(1);
if (gramName != t.val)
SemErr("name does not match grammar name");
Tab.gramSy = Symbol.Find(gramName);
if (Tab.gramSy == null)
SemErr("missing production for grammar name");
else {
sym = Tab.gramSy;
if (sym.attrPos != null)
SemErr("grammar symbol must not have attributes");
}
Tab.noSym = new Symbol(Node.t, "???", 0); // noSym gets highest number
Tab.SetupAnys();
Tab.RenumberPragmas();
if (Tab.ddt[2]) Node.PrintNodes();
if (Errors.count == 0) {
Console.WriteLine("checking");
Tab.CompSymbolSets();
if (Tab.ddt[7]) Tab.XRef();
if (Tab.GrammarOk()) {
Console.Write("parser");
ParserGen.WriteParser();
if (genScanner) {
Console.Write(" + scanner");
DFA.WriteScanner();
if (Tab.ddt[0]) DFA.PrintStates();
}
Console.WriteLine(" generated");
if (Tab.ddt[8]) ParserGen.WriteStatistics();
}
}
if (Tab.ddt[6]) Tab.PrintSymbolTable();
Expect(18);
}
static void UsingDecl(out Position pos) {
Expect(39);
int beg = t.pos;
while (StartOf(4)) {
Get();
}
Expect(40);
int end = t.pos;
while (la.kind == 39) {
Get();
while (StartOf(4)) {
Get();
}
Expect(40);
end = t.pos;
}
pos = new Position(beg, end - beg + 1, 0);
}
static void SetDecl() {
BitArray s;
Expect(1);
string name = t.val;
CharClass c = CharClass.Find(name);
if (c != null) SemErr("name declared twice");
Expect(17);
Set(out s);
if (Sets.Elements(s) == 0) SemErr("character set must not be empty");
c = new CharClass(name, s);
Expect(18);
}
static void TokenDecl(int typ) {
string name; int kind; Symbol sym; Graph g;
Sym(out name, out kind);
sym = Symbol.Find(name);
if (sym != null) SemErr("name declared twice");
else {
sym = new Symbol(typ, name, t.line);
sym.tokenKind = Symbol.fixedToken;
}
tokenString = null;
while (!(StartOf(5))) {SynErr(43); Get();}
if (la.kind == 17) {
Get();
TokenExpr(out g);
Expect(18);
if (kind == str) SemErr("a literal must not be declared with a structure");
Graph.Finish(g);
if (tokenString == null || tokenString.Equals(noString))
DFA.ConvertToStates(g.l, sym);
else { // TokenExpr is a single string
if (Tab.literals[tokenString] != null)
SemErr("token string declared twice");
Tab.literals[tokenString] = sym;
DFA.MatchLiteral(tokenString, sym);
}
} else if (StartOf(6)) {
if (kind == id) genScanner = false;
else DFA.MatchLiteral(sym.name, sym);
} else SynErr(44);
if (la.kind == 37) {
SemText(out sym.semPos);
if (typ != Node.pr) SemErr("semantic action not allowed here");
}
}
static void TokenExpr(out Graph g) {
Graph g2;
TokenTerm(out g);
bool first = true;
while (WeakSeparator(26,7,8) ) {
TokenTerm(out g2);
if (first) { Graph.MakeFirstAlt(g); first = false; }
Graph.MakeAlternative(g, g2);
}
}
static void Set(out BitArray s) {
BitArray s2;
SimSet(out s);
while (la.kind == 20 || la.kind == 21) {
if (la.kind == 20) {
Get();
SimSet(out s2);
s.Or(s2);
} else {
Get();
SimSet(out s2);
Sets.Subtract(s, s2);
}
}
}
static void AttrDecl(Symbol sym) {
Expect(24);
int beg = la.pos; int col = la.col;
while (StartOf(9)) {
// CHANGES BY M.KRUEGER
if (la.kind == 24) {
AttrDecl(sym);
} else
// EOC
if (StartOf(10)) {
Get();
} else {
Get();
SemErr("bad string in attributes");
}
}
Expect(25);
if (t.pos > beg)
sym.attrPos = new Position(beg, t.pos - beg, col);
}
static void SemText(out Position pos) {
Expect(37);
int beg = la.pos; int col = la.col;
while (StartOf(11)) {
if (StartOf(12)) {
Get();
} else if (la.kind == 4) {
Get();
SemErr("bad string in semantic action");
} else {
Get();
SemErr("missing end of previous semantic action");
}
}
Expect(38);
pos = new Position(beg, t.pos - beg, col);
}
static void Expression(out Graph g) {
Graph g2;
Term(out g);
bool first = true;
while (WeakSeparator(26,13,14) ) {
Term(out g2);
if (first) { Graph.MakeFirstAlt(g); first = false; }
Graph.MakeAlternative(g, g2);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -