Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1977 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
21 changed files with 2 additions and 11304 deletions
Binary file not shown.
@ -1,55 +0,0 @@ |
|||||||
-->begin |
|
||||||
/* |
|
||||||
Parser.frame file for NRefactory. |
|
||||||
*/ |
|
||||||
using System; |
|
||||||
using System.Reflection; |
|
||||||
|
|
||||||
-->namespace |
|
||||||
|
|
||||||
|
|
||||||
internal class Parser : AbstractParser |
|
||||||
{ |
|
||||||
-->constants |
|
||||||
const bool T = true; |
|
||||||
const bool x = false; |
|
||||||
|
|
||||||
-->declarations |
|
||||||
|
|
||||||
/* |
|
||||||
-->pragmas |
|
||||||
*/ |
|
||||||
|
|
||||||
-->productions |
|
||||||
public Parser(ILexer lexer) : base(lexer) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
public override void Parse() |
|
||||||
{ |
|
||||||
-->parseRoot |
|
||||||
} |
|
||||||
|
|
||||||
private bool StartOf(int s) |
|
||||||
{ |
|
||||||
return set[s, lexer.LookAhead.kind]; |
|
||||||
} |
|
||||||
|
|
||||||
static bool[,] set = { |
|
||||||
-->initialization |
|
||||||
}; |
|
||||||
|
|
||||||
protected override void SynErr(int line, int col, int errorNumber) |
|
||||||
{ |
|
||||||
errors.count++; |
|
||||||
string s; |
|
||||||
switch (errorNumber) { |
|
||||||
-->errors |
|
||||||
default: s = "error " + errorNumber; break; |
|
||||||
} |
|
||||||
this.Errors.Error(line, col, s); |
|
||||||
} |
|
||||||
|
|
||||||
} // end Parser |
|
||||||
|
|
||||||
$$$ |
|
||||||
@ -1,50 +0,0 @@ |
|||||||
/* |
|
||||||
Parser.frame file for NRefactory. |
|
||||||
*/ |
|
||||||
using System; |
|
||||||
using System.Reflection; |
|
||||||
|
|
||||||
-->namespace |
|
||||||
|
|
||||||
-->tokens |
|
||||||
|
|
||||||
partial class Parser : AbstractParser |
|
||||||
{ |
|
||||||
-->constants |
|
||||||
const bool T = true; |
|
||||||
const bool x = false; |
|
||||||
|
|
||||||
-->declarations |
|
||||||
|
|
||||||
/* |
|
||||||
-->pragmas |
|
||||||
*/ |
|
||||||
|
|
||||||
-->productions |
|
||||||
|
|
||||||
public override void Parse() |
|
||||||
{ |
|
||||||
-->parseRoot |
|
||||||
} |
|
||||||
|
|
||||||
protected override void SynErr(int line, int col, int errorNumber) |
|
||||||
{ |
|
||||||
string s; |
|
||||||
switch (errorNumber) { |
|
||||||
-->errors |
|
||||||
default: s = "error " + errorNumber; break; |
|
||||||
} |
|
||||||
this.Errors.Error(line, col, s); |
|
||||||
} |
|
||||||
|
|
||||||
private bool StartOf(int s) |
|
||||||
{ |
|
||||||
return set[s, lexer.LookAhead.kind]; |
|
||||||
} |
|
||||||
|
|
||||||
static bool[,] set = { |
|
||||||
-->initialization |
|
||||||
}; |
|
||||||
} // end Parser |
|
||||||
|
|
||||||
$$$ |
|
||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@ -1,14 +0,0 @@ |
|||||||
Modified version of Coco/R |
|
||||||
|
|
||||||
The original version can be found at: |
|
||||||
http://www.ssw.uni-linz.ac.at/Research/Projects/Coco/CSharp/ |
|
||||||
|
|
||||||
Changes |
|
||||||
|
|
||||||
+ Added #line pragmas for the generated parser |
|
||||||
+ Now Coco uses more enums than ints... |
|
||||||
+ no static method generation (now all is public) |
|
||||||
+ Error & Scanner are now fields inside the parser, no more static |
|
||||||
calling |
|
||||||
|
|
||||||
Mike |
|
||||||
@ -1,32 +0,0 @@ |
|||||||
using System.Reflection; |
|
||||||
using System.Runtime.CompilerServices; |
|
||||||
|
|
||||||
// Information about this assembly is defined by the following
|
|
||||||
// attributes.
|
|
||||||
//
|
|
||||||
// change them to the information which is associated with the assembly
|
|
||||||
// you compile.
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("")] |
|
||||||
[assembly: AssemblyDescription("")] |
|
||||||
[assembly: AssemblyConfiguration("")] |
|
||||||
[assembly: AssemblyCompany("")] |
|
||||||
[assembly: AssemblyProduct("")] |
|
||||||
[assembly: AssemblyCopyright("")] |
|
||||||
[assembly: AssemblyTrademark("")] |
|
||||||
[assembly: AssemblyCulture("")] |
|
||||||
|
|
||||||
// The assembly version has following format :
|
|
||||||
//
|
|
||||||
// Major.Minor.Build.Revision
|
|
||||||
//
|
|
||||||
// You can specify all values by your own or you can build default build and revision
|
|
||||||
// numbers with the '*' character (the default):
|
|
||||||
|
|
||||||
[assembly: AssemblyVersion("2.0.0.1")] |
|
||||||
|
|
||||||
// The following attributes specify the key for the sign of your assembly. See the
|
|
||||||
// .NET Framework documentation for more information about signing.
|
|
||||||
// This is not required, if you don't want signing let these attributes like they're.
|
|
||||||
[assembly: AssemblyDelaySign(false)] |
|
||||||
[assembly: AssemblyKeyFile("")] |
|
||||||
@ -1,461 +0,0 @@ |
|||||||
/*------------------------------------------------------------------------- |
|
||||||
Coco.ATG -- Attributed Grammar |
|
||||||
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. |
|
||||||
-------------------------------------------------------------------------*/ |
|
||||||
/*------------------------------------------------------------------------- |
|
||||||
compile with: |
|
||||||
Coco Coco.ATG -namespace at.jku.ssw.Coco |
|
||||||
-------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
using System.Collections; |
|
||||||
|
|
||||||
COMPILER Coco |
|
||||||
|
|
||||||
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 |
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
CHARACTERS |
|
||||||
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz". |
|
||||||
digit = "0123456789". |
|
||||||
cr = '\r'. |
|
||||||
lf = '\n'. |
|
||||||
tab = '\t'. |
|
||||||
stringCh = ANY - '"' - '\\' - cr - lf. |
|
||||||
charCh = ANY - '\'' - '\\' - cr - lf. |
|
||||||
printable = '\u0020' .. '\u007e'. |
|
||||||
hex = "0123456789abcdef". |
|
||||||
|
|
||||||
TOKENS |
|
||||||
ident = letter { letter | digit }. |
|
||||||
number = digit { digit }. |
|
||||||
string = '"' { stringCh | '\\' printable } '"'. |
|
||||||
badString = '"' { stringCh | '\\' printable } (cr | lf). |
|
||||||
char = '\'' ( charCh | '\\' printable { hex } ) '\''. |
|
||||||
|
|
||||||
PRAGMAS |
|
||||||
ddtSym = '$' { digit | letter }. (. Tab.SetDDT(la.val); .) |
|
||||||
|
|
||||||
COMMENTS FROM "/*" TO "*/" NESTED |
|
||||||
|
|
||||||
IGNORE cr + lf + tab |
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
PRODUCTIONS |
|
||||||
|
|
||||||
Coco (. Symbol sym; Graph g, g1, g2; string gramName; .) |
|
||||||
= |
|
||||||
[ UsingDecl<out ParserGen.usingPos> ] |
|
||||||
|
|
||||||
"COMPILER" (. genScanner = true; Tab.ignored = null; .) |
|
||||||
ident (. gramName = t.val; |
|
||||||
int beg = la.pos; |
|
||||||
.) |
|
||||||
{ ANY } (. Tab.semDeclPos = new Position(beg, la.pos-beg, 0); .) |
|
||||||
[ "IGNORECASE" (. DFA.ignoreCase = true; .) ] /* pdt */ |
|
||||||
[ "CHARACTERS" { SetDecl }] |
|
||||||
[ "TOKENS" { TokenDecl<Node.t> }] |
|
||||||
[ "PRAGMAS" { TokenDecl<Node.pr> }] |
|
||||||
{ "COMMENTS" (. bool nested = false; .) |
|
||||||
"FROM" TokenExpr<out g1> |
|
||||||
"TO" TokenExpr<out g2> |
|
||||||
[ "NESTED" (. nested = true; .) |
|
||||||
] (. new Comment(g1.l, g2.l, nested); .) |
|
||||||
} |
|
||||||
{ "IGNORE" |
|
||||||
Set<out Tab.ignored> (. Tab.ignored[' '] = true; /* ' ' is always ignored */ .) |
|
||||||
} |
|
||||||
|
|
||||||
SYNC |
|
||||||
"PRODUCTIONS" (. if (genScanner) DFA.MakeDeterministic(); |
|
||||||
Graph.DeleteNodes(); |
|
||||||
.) |
|
||||||
{ ident (. 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; |
|
||||||
.) |
|
||||||
[ AttrDecl<sym> ] (. if (!undef) |
|
||||||
if (noAttrs != (sym.attrPos == null)) |
|
||||||
SemErr("attribute mismatch between declaration and use of this symbol"); |
|
||||||
.) |
|
||||||
[ SemText<out sym.semPos> ] WEAK |
|
||||||
'=' |
|
||||||
Expression<out g> (. sym.graph = g.l; |
|
||||||
Graph.Finish(g); |
|
||||||
.) |
|
||||||
WEAK |
|
||||||
'.' |
|
||||||
} |
|
||||||
"END" ident (. 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(); |
|
||||||
.) |
|
||||||
'.' |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
SetDecl (. BitArray s; .) |
|
||||||
= |
|
||||||
ident (. string name = t.val; |
|
||||||
CharClass c = CharClass.Find(name); |
|
||||||
if (c != null) SemErr("name declared twice"); |
|
||||||
.) |
|
||||||
'=' Set<out s> (. if (Sets.Elements(s) == 0) SemErr("character set must not be empty"); |
|
||||||
c = new CharClass(name, s); |
|
||||||
.) |
|
||||||
'.' |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
Set<out BitArray s> (. BitArray s2; .) |
|
||||||
= |
|
||||||
SimSet<out s> |
|
||||||
{ '+' SimSet<out s2> (. s.Or(s2); .) |
|
||||||
| '-' SimSet<out s2> (. Sets.Subtract(s, s2); .) |
|
||||||
} |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
SimSet<out BitArray s> (. int n1, n2; .) |
|
||||||
= (. s = new BitArray(CharClass.charSetSize); .) |
|
||||||
( ident (. CharClass c = CharClass.Find(t.val); |
|
||||||
if (c == null) SemErr("undefined name"); else s.Or(c.set); |
|
||||||
.) |
|
||||||
| string (. string name = t.val; |
|
||||||
name = DFA.Unescape(name.Substring(1, name.Length-2)); |
|
||||||
foreach (char ch in name) |
|
||||||
if (DFA.ignoreCase) s[char.ToLower(ch)] = true; |
|
||||||
else s[ch] = true; .) |
|
||||||
| Char<out n1> (. s[n1] = true; .) |
|
||||||
[ ".." Char<out n2> (. for (int i = n1; i <= n2; i++) s[i] = true; .) |
|
||||||
] |
|
||||||
| "ANY" (. s = new BitArray(CharClass.charSetSize, true); .) |
|
||||||
) |
|
||||||
. |
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
Char<out int n> |
|
||||||
= |
|
||||||
char (. string name = t.val; n = 0; |
|
||||||
name = DFA.Unescape(name.Substring(1, name.Length-2)); |
|
||||||
int max = CharClass.charSetSize; |
|
||||||
if (name.Length == 1 && name[0] <= max-1) n = name[0] % max; |
|
||||||
else SemErr("unacceptable character value"); |
|
||||||
if (DFA.ignoreCase && (char)n >= 'A' && (char)n <= 'Z') n += 32; |
|
||||||
.) |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
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; |
|
||||||
.) |
|
||||||
SYNC |
|
||||||
( '=' TokenExpr<out g> '.' (. 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); |
|
||||||
} |
|
||||||
.) |
|
||||||
| (. if (kind == id) genScanner = false; |
|
||||||
else DFA.MatchLiteral(sym.name, sym); |
|
||||||
.) |
|
||||||
) |
|
||||||
[ SemText<out sym.semPos> (. if (typ != Node.pr) SemErr("semantic action not allowed here"); .) |
|
||||||
] |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
AttrDecl<Symbol sym> |
|
||||||
= |
|
||||||
'<' (. int beg = la.pos; int col = la.col; .) |
|
||||||
{ ANY |
|
||||||
| badString (. SemErr("bad string in attributes"); .) |
|
||||||
} |
|
||||||
'>' (. if (t.pos > beg) |
|
||||||
sym.attrPos = new Position(beg, t.pos - beg, col); .) |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
Expression<out Graph g> (. Graph g2; .) |
|
||||||
= |
|
||||||
Term<out g> (. bool first = true; .) |
|
||||||
{ WEAK |
|
||||||
'|' |
|
||||||
Term<out g2> (. if (first) { Graph.MakeFirstAlt(g); first = false; } |
|
||||||
Graph.MakeAlternative(g, g2); |
|
||||||
.) |
|
||||||
} |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
Term<out Graph g> (. Graph g2; Node rslv = null; g = null; .) |
|
||||||
= |
|
||||||
( [ (. rslv = new Node(Node.rslv, null, la.line); .) |
|
||||||
Resolver<out rslv.pos> (. g = new Graph(rslv); .) |
|
||||||
] |
|
||||||
Factor<out g2> (. if (rslv != null) Graph.MakeSequence(g, g2); |
|
||||||
else g = g2; |
|
||||||
.) |
|
||||||
{ Factor<out g2> (. Graph.MakeSequence(g, g2); .) |
|
||||||
} |
|
||||||
| (. g = new Graph(new Node(Node.eps, null, 0)); .) |
|
||||||
) (. if (g == null) // invalid start of Term |
|
||||||
g = new Graph(new Node(Node.eps, null, 0)); |
|
||||||
.) |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
Factor<out Graph g> (. string name; int kind; Position pos; bool weak = false; |
|
||||||
g = null; |
|
||||||
.) |
|
||||||
= |
|
||||||
( [ "WEAK" (. weak = true; .) |
|
||||||
] |
|
||||||
Sym<out name, out kind> (. Symbol sym = Symbol.Find(name); |
|
||||||
if (sym == null && kind == str) |
|
||||||
sym = Tab.literals[name] as Symbol; |
|
||||||
bool undef = sym == null; |
|
||||||
if (undef) { |
|
||||||
if (kind == id) |
|
||||||
sym = new Symbol(Node.nt, name, 0); // forward nt |
|
||||||
else if (genScanner) { |
|
||||||
sym = new Symbol(Node.t, name, t.line); |
|
||||||
DFA.MatchLiteral(sym.name, sym); |
|
||||||
} else { // undefined string in production |
|
||||||
SemErr("undefined string in production"); |
|
||||||
sym = Tab.eofSy; // dummy |
|
||||||
} |
|
||||||
} |
|
||||||
int typ = sym.typ; |
|
||||||
if (typ != Node.t && typ != Node.nt) |
|
||||||
SemErr("this symbol kind is not allowed in a production"); |
|
||||||
if (weak) |
|
||||||
if (typ == Node.t) typ = Node.wt; |
|
||||||
else SemErr("only terminals may be weak"); |
|
||||||
Node p = new Node(typ, sym, t.line); |
|
||||||
g = new Graph(p); |
|
||||||
.) |
|
||||||
[ Attribs<p> (. if (kind != id) SemErr("a literal must not have attributes"); .) |
|
||||||
] (. if (undef) |
|
||||||
sym.attrPos = p.pos; // dummy |
|
||||||
else if ((p.pos == null) != (sym.attrPos == null)) |
|
||||||
SemErr("attribute mismatch between declaration and use of this symbol"); |
|
||||||
.) |
|
||||||
| '(' Expression<out g> ')' |
|
||||||
| '[' Expression<out g> ']' (. Graph.MakeOption(g); .) |
|
||||||
| '{' Expression<out g> '}' (. Graph.MakeIteration(g); .) |
|
||||||
| SemText<out pos> (. Node p = new Node(Node.sem, null, 0); |
|
||||||
p.pos = pos; |
|
||||||
g = new Graph(p); |
|
||||||
.) |
|
||||||
| "ANY" (. Node p = new Node(Node.any, null, 0); // p.set is set in Tab.SetupAnys |
|
||||||
g = new Graph(p); |
|
||||||
.) |
|
||||||
| "SYNC" (. Node p = new Node(Node.sync, null, 0); |
|
||||||
g = new Graph(p); |
|
||||||
.) |
|
||||||
) (. if (g == null) // invalid start of Factor |
|
||||||
g = new Graph(new Node(Node.eps, null, 0)); |
|
||||||
.) |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
Resolver<out Position pos> |
|
||||||
= |
|
||||||
"IF" "(" (. int beg = la.pos; int col = la.col; .) |
|
||||||
Condition (. pos = new Position(beg, t.pos - beg, col); .) |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
Condition = { "(" Condition | ANY } ")" . |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
TokenExpr<out Graph g> (. Graph g2; .) |
|
||||||
= |
|
||||||
TokenTerm<out g> (. bool first = true; .) |
|
||||||
{ WEAK |
|
||||||
'|' |
|
||||||
TokenTerm<out g2> (. if (first) { Graph.MakeFirstAlt(g); first = false; } |
|
||||||
Graph.MakeAlternative(g, g2); |
|
||||||
.) |
|
||||||
} |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
TokenTerm<out Graph g> (. Graph g2; .) |
|
||||||
= |
|
||||||
TokenFactor<out g> |
|
||||||
{ TokenFactor<out g2> (. Graph.MakeSequence(g, g2); .) |
|
||||||
} |
|
||||||
[ "CONTEXT" |
|
||||||
'(' TokenExpr<out g2> (. Graph.SetContextTrans(g2.l); Graph.MakeSequence(g, g2); .) |
|
||||||
')' |
|
||||||
] |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
TokenFactor<out Graph g> (. string name; int kind; .) |
|
||||||
= |
|
||||||
(. g = null; .) |
|
||||||
( Sym<out name, out kind> (. if (kind == id) { |
|
||||||
CharClass c = CharClass.Find(name); |
|
||||||
if (c == null) { |
|
||||||
SemErr("undefined name"); |
|
||||||
c = new CharClass(name, new BitArray(CharClass.charSetSize)); |
|
||||||
} |
|
||||||
Node p = new Node(Node.clas, null, 0); p.val = c.n; |
|
||||||
g = new Graph(p); |
|
||||||
tokenString = noString; |
|
||||||
} else { // str |
|
||||||
g = Graph.StrToGraph(name); |
|
||||||
if (tokenString == null) tokenString = name; |
|
||||||
else tokenString = noString; |
|
||||||
} |
|
||||||
.) |
|
||||||
| '(' TokenExpr<out g> ')' |
|
||||||
| '[' TokenExpr<out g> ']' (. Graph.MakeOption(g); .) |
|
||||||
| '{' TokenExpr<out g> '}' (. Graph.MakeIteration(g); .) |
|
||||||
) (. if (g == null) // invalid start of TokenFactor |
|
||||||
g = new Graph(new Node(Node.eps, null, 0)); .) |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
Sym<out string name, out int kind> |
|
||||||
= (. name = "???"; kind = id; .) |
|
||||||
( ident (. kind = id; name = t.val; .) |
|
||||||
| (string (. name = t.val; .) |
|
||||||
| char (. name = "\"" + t.val.Substring(1, t.val.Length-2) + "\""; .) |
|
||||||
) (. kind = str; |
|
||||||
if (DFA.ignoreCase) name = name.ToLower(); |
|
||||||
if (name.IndexOf(' ') >= 0) |
|
||||||
SemErr("literal tokens must not contain blanks"); .) |
|
||||||
) |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
Attribs<Node p> |
|
||||||
= |
|
||||||
'<' (. int beg = la.pos; int col = la.col; .) |
|
||||||
{ Attribs<p> |
|
||||||
|ANY |
|
||||||
| badString (. SemErr("bad string in attributes"); .) |
|
||||||
} |
|
||||||
'>' (. if (t.pos > beg) p.pos = new Position(beg, t.pos - beg, col); .) |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
SemText<out Position pos> |
|
||||||
= |
|
||||||
"(." (. int beg = la.pos; int col = la.col; .) |
|
||||||
{ ANY |
|
||||||
| badString (. SemErr("bad string in semantic action"); .) |
|
||||||
| "(." (. SemErr("missing end of previous semantic action"); .) |
|
||||||
} |
|
||||||
".)" (. pos = new Position(beg, t.pos - beg, col); .) |
|
||||||
. |
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
UsingDecl<out Position pos> |
|
||||||
= |
|
||||||
"using" (. int beg = t.pos; .) |
|
||||||
{ ANY } ';' (. int end = t.pos; .) |
|
||||||
{ "using" { ANY } ';' (. end = t.pos; .) |
|
||||||
} (. pos = new Position(beg, end - beg + 1, 0); .) |
|
||||||
. |
|
||||||
|
|
||||||
END Coco. |
|
||||||
@ -1,97 +0,0 @@ |
|||||||
/*------------------------------------------------------------------------- |
|
||||||
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. |
|
||||||
-------------------------------------------------------------------------*/ |
|
||||||
/*------------------------------------------------------------------------- |
|
||||||
Trace output options |
|
||||||
0 | A: prints the states of the scanner automaton |
|
||||||
1 | F: prints the First and Follow sets of all nonterminals |
|
||||||
2 | G: prints the syntax graph of the productions |
|
||||||
3 | I: traces the computation of the First sets |
|
||||||
4 | J: prints the sets associated with ANYs and synchronisation sets |
|
||||||
6 | S: prints the symbol table (terminals, nonterminals, pragmas) |
|
||||||
7 | X: prints a cross reference list of all syntax symbols |
|
||||||
8 | P: prints statistics about the Coco run |
|
||||||
|
|
||||||
Trace output can be switched on by the pragma |
|
||||||
$ { digit | letter } |
|
||||||
in the attributed grammar or as a command-line option |
|
||||||
-------------------------------------------------------------------------*/ |
|
||||||
|
|
||||||
using System; |
|
||||||
using System.IO; |
|
||||||
|
|
||||||
namespace at.jku.ssw.Coco { |
|
||||||
|
|
||||||
public class Coco { |
|
||||||
|
|
||||||
public static void Main (string[] arg) { |
|
||||||
Console.WriteLine("Coco/R (Jun 28, 2004)"); |
|
||||||
string ATGName = null; |
|
||||||
for (int i = 0; i < arg.Length; i++) { |
|
||||||
if (arg[i] == "-namespace" && i < arg.Length - 1) Tab.nsName = arg[++i]; |
|
||||||
else if (arg[i] == "-frames" && i < arg.Length - 1) Tab.frameDir = arg[++i]; |
|
||||||
else if (arg[i] == "-trace" && i < arg.Length - 1) Tab.SetDDT(arg[++i]); |
|
||||||
else ATGName = arg[i]; |
|
||||||
} |
|
||||||
if (arg.Length > 0 && ATGName != null) { |
|
||||||
int pos = ATGName.LastIndexOf('/'); |
|
||||||
if (pos < 0) pos = ATGName.LastIndexOf('\\'); |
|
||||||
string file = ATGName; |
|
||||||
string dir = ATGName.Substring(0, pos+1); |
|
||||||
|
|
||||||
Scanner.Init(file); |
|
||||||
Trace.Init(dir); |
|
||||||
Tab.Init(); |
|
||||||
DFA.Init(file, dir); |
|
||||||
ParserGen.Init(file, dir); |
|
||||||
|
|
||||||
Parser.Parse(); |
|
||||||
|
|
||||||
Trace.Close(); |
|
||||||
Console.WriteLine("{0} errors detected", Errors.count); |
|
||||||
} else { |
|
||||||
Console.WriteLine("Usage: Coco Grammar.ATG {{Option}}{0}" + |
|
||||||
"Options:{0}" + |
|
||||||
" -namespace <namespaceName>{0}" + |
|
||||||
" -frames <frameFilesDirectory>{0}" + |
|
||||||
" -trace <traceString>{0}" + |
|
||||||
"Valid characters in the trace string:{0}" + |
|
||||||
" A trace automaton{0}" + |
|
||||||
" F list first/follow sets{0}" + |
|
||||||
" G print syntax graph{0}" + |
|
||||||
" I trace computation of first sets{0}" + |
|
||||||
" J list ANY and SYNC sets{0}" + |
|
||||||
" P print statistics{0}" + |
|
||||||
" S list symbol table{0}" + |
|
||||||
" X list cross reference table{0}" + |
|
||||||
"Scanner.frame and Parser.frame files needed in ATG directory{0}" + |
|
||||||
"or in a directory specified in the -frames option.", |
|
||||||
Environment.NewLine); |
|
||||||
} |
|
||||||
} |
|
||||||
} // end Coco
|
|
||||||
|
|
||||||
} // end namespace
|
|
||||||
@ -1,952 +0,0 @@ |
|||||||
/*------------------------------------------------------------------------- |
|
||||||
DFA.cs -- Generation of the Scanner Automaton |
|
||||||
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; |
|
||||||
using System.IO; |
|
||||||
using System.Collections; |
|
||||||
using System.Text; |
|
||||||
|
|
||||||
namespace at.jku.ssw.Coco { |
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// State
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
public class State { // state of finite automaton
|
|
||||||
public static int lastNr; // highest state number
|
|
||||||
public int nr; // state number
|
|
||||||
public Action firstAction;// to first action of this state
|
|
||||||
public Symbol endOf; // recognized token if state is final
|
|
||||||
public bool ctx; // true if state is reached via contextTrans
|
|
||||||
public State next; |
|
||||||
|
|
||||||
public State() { |
|
||||||
nr = ++lastNr; |
|
||||||
} |
|
||||||
|
|
||||||
public void AddAction(Action act) { |
|
||||||
Action lasta = null, a = firstAction; |
|
||||||
while (a != null && act.typ >= a.typ) {lasta = a; a = a.next;} |
|
||||||
// collecting classes at the beginning gives better performance
|
|
||||||
act.next = a; |
|
||||||
if (a==firstAction) firstAction = act; else lasta.next = act; |
|
||||||
} |
|
||||||
|
|
||||||
public void DetachAction(Action act) { |
|
||||||
Action lasta = null, a = firstAction; |
|
||||||
while (a != null && a != act) {lasta = a; a = a.next;} |
|
||||||
if (a != null) |
|
||||||
if (a == firstAction) firstAction = a.next; else lasta.next = a.next; |
|
||||||
} |
|
||||||
|
|
||||||
public Action TheAction(char ch) { |
|
||||||
BitArray s; |
|
||||||
for (Action a = firstAction; a != null; a = a.next) |
|
||||||
if (a.typ == Node.chr && ch == a.sym) return a; |
|
||||||
else if (a.typ == Node.clas) { |
|
||||||
s = CharClass.Set(a.sym); |
|
||||||
if (s[ch]) return a; |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
public void MeltWith(State s) { // copy actions of s to state
|
|
||||||
Action a; |
|
||||||
for (Action action = s.firstAction; action != null; action = action.next) { |
|
||||||
a = new Action(action.typ, action.sym, action.tc); |
|
||||||
a.AddTargets(action); |
|
||||||
AddAction(a); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Action
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
public class Action { // action of finite automaton
|
|
||||||
public int typ; // type of action symbol: clas, chr
|
|
||||||
public int sym; // action symbol
|
|
||||||
public int tc; // transition code: normalTrans, contextTrans
|
|
||||||
public Target target; // states reached from this action
|
|
||||||
public Action next; |
|
||||||
|
|
||||||
public Action(int typ, int sym, int tc) { |
|
||||||
this.typ = typ; this.sym = sym; this.tc = tc; |
|
||||||
} |
|
||||||
|
|
||||||
public void AddTarget(Target t) { // add t to the action.targets
|
|
||||||
Target last = null; |
|
||||||
Target p = target; |
|
||||||
while (p != null && t.state.nr >= p.state.nr) { |
|
||||||
if (t.state == p.state) return; |
|
||||||
last = p; p = p.next; |
|
||||||
} |
|
||||||
t.next = p; |
|
||||||
if (p == target) target = t; else last.next = t; |
|
||||||
} |
|
||||||
|
|
||||||
public void AddTargets(Action a) { // add copy of a.targets to action.targets
|
|
||||||
for (Target p = a.target; p != null; p = p.next) { |
|
||||||
Target t = new Target(p.state); |
|
||||||
AddTarget(t); |
|
||||||
} |
|
||||||
if (a.tc == Node.contextTrans) tc = Node.contextTrans; |
|
||||||
} |
|
||||||
|
|
||||||
public BitArray Symbols() { |
|
||||||
BitArray s; |
|
||||||
if (typ == Node.clas) |
|
||||||
s = (BitArray) CharClass.Set(sym).Clone(); |
|
||||||
else { |
|
||||||
s = new BitArray(CharClass.charSetSize); s[sym] = true; |
|
||||||
} |
|
||||||
return s; |
|
||||||
} |
|
||||||
|
|
||||||
public void ShiftWith(BitArray s) { |
|
||||||
if (Sets.Elements(s) == 1) { |
|
||||||
typ = Node.chr; sym = Sets.First(s); |
|
||||||
} else { |
|
||||||
CharClass c = CharClass.Find(s); |
|
||||||
if (c == null) c = new CharClass("#", s); // class with dummy name
|
|
||||||
typ = Node.clas; sym = c.n; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void GetTargetStates(out BitArray targets, out Symbol endOf, out bool ctx) { |
|
||||||
// compute the set of target states
|
|
||||||
targets = new BitArray(DFA.maxStates); endOf = null; |
|
||||||
ctx = false; |
|
||||||
for (Target t = target; t != null; t = t.next) { |
|
||||||
int stateNr = t.state.nr; |
|
||||||
if (stateNr <= DFA.lastSimState) targets[stateNr] = true; |
|
||||||
else targets.Or(Melted.Set(stateNr)); |
|
||||||
if (t.state.endOf != null) |
|
||||||
if (endOf == null || endOf == t.state.endOf) |
|
||||||
endOf = t.state.endOf; |
|
||||||
else { |
|
||||||
Console.WriteLine("Tokens {0} and {1} cannot be distinguished", endOf.name, t.state.endOf.name); |
|
||||||
Errors.count++; |
|
||||||
} |
|
||||||
if (t.state.ctx) { |
|
||||||
ctx = true; |
|
||||||
// The following check seems to be unnecessary. It reported an error
|
|
||||||
// if a symbol + context was the prefix of another symbol, e.g.
|
|
||||||
// s1 = "a" "b" "c".
|
|
||||||
// s2 = "a" CONTEXT("b").
|
|
||||||
// But this is ok.
|
|
||||||
// if (t.state.endOf != null) {
|
|
||||||
// Console.WriteLine("Ambiguous context clause");
|
|
||||||
// Errors.count++;
|
|
||||||
// }
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Target
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
public class Target { // set of states that are reached by an action
|
|
||||||
public State state; // target state
|
|
||||||
public Target next; |
|
||||||
|
|
||||||
public Target (State s) { |
|
||||||
state = s; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Melted
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
public class Melted { // info about melted states
|
|
||||||
public static Melted first; // head of melted state list
|
|
||||||
public BitArray set; // set of old states
|
|
||||||
public State state; // new state
|
|
||||||
public Melted next; |
|
||||||
|
|
||||||
public Melted(BitArray set, State state) { |
|
||||||
this.set = set; this.state = state; |
|
||||||
this.next = first; first = this; |
|
||||||
} |
|
||||||
|
|
||||||
public static BitArray Set(int nr) { |
|
||||||
Melted m = first; |
|
||||||
while (m != null) { |
|
||||||
if (m.state.nr == nr) return m.set; else m = m.next; |
|
||||||
} |
|
||||||
throw new Exception("-- compiler error in Melted.Set"); |
|
||||||
} |
|
||||||
|
|
||||||
public static Melted StateWithSet(BitArray s) { |
|
||||||
for (Melted m = first; m != null; m = m.next) |
|
||||||
if (Sets.Equals(s, m.set)) return m; |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Comment
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
public class Comment { // info about comment syntax
|
|
||||||
public static Comment first; // list of comments
|
|
||||||
public string start; |
|
||||||
public string stop; |
|
||||||
public bool nested; |
|
||||||
public Comment next; |
|
||||||
|
|
||||||
static string Str(Node p) { |
|
||||||
StringBuilder s = new StringBuilder(); |
|
||||||
while (p != null) { |
|
||||||
if (p.typ == Node.chr) { |
|
||||||
s.Append((char)p.val); |
|
||||||
} else if (p.typ == Node.clas) { |
|
||||||
BitArray set = CharClass.Set(p.val); |
|
||||||
if (Sets.Elements(set) != 1) Parser.SemErr("character set contains more than 1 character"); |
|
||||||
s.Append((char)Sets.First(set)); |
|
||||||
} else Parser.SemErr("comment delimiters may not be structured"); |
|
||||||
p = p.next; |
|
||||||
} |
|
||||||
if (s.Length == 0 || s.Length > 2) { |
|
||||||
Parser.SemErr("comment delimiters must be 1 or 2 characters long"); |
|
||||||
s = new StringBuilder("?"); |
|
||||||
} |
|
||||||
return s.ToString(); |
|
||||||
} |
|
||||||
|
|
||||||
public Comment(Node from, Node to, bool nested) { |
|
||||||
start = Str(from); |
|
||||||
stop = Str(to); |
|
||||||
this.nested = nested; |
|
||||||
this.next = first; first = this; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// DFA
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
public class DFA { |
|
||||||
public static int maxStates; |
|
||||||
public const int EOF = -1; |
|
||||||
|
|
||||||
public static State firstState; |
|
||||||
public static State lastState; // last allocated state
|
|
||||||
public static int lastSimState; // last non melted state
|
|
||||||
public static FileStream fram; // scanner frame input
|
|
||||||
public static StreamWriter gen; // generated scanner file
|
|
||||||
public static Symbol curSy; // current token to be recognized (in FindTrans)
|
|
||||||
public static Node curGraph; // start of graph for current token (in FindTrans)
|
|
||||||
public static bool ignoreCase; // true if input should be treated case-insensitively
|
|
||||||
public static bool dirtyDFA; // DFA may become nondeterministic in MatchLiteral
|
|
||||||
public static bool hasCtxMoves; // DFA has context transitions
|
|
||||||
static string srcName; // name of the attributed grammar file
|
|
||||||
static string srcDir; // directory of attributed grammar file
|
|
||||||
|
|
||||||
//---------- Output primitives
|
|
||||||
private static string Ch(char ch) { |
|
||||||
if (ch < ' ' || ch >= 127 || ch == '\'' || ch == '\\') return Convert.ToString((int)ch); |
|
||||||
else return String.Format("'{0}'", ch); |
|
||||||
} |
|
||||||
|
|
||||||
private static string ChCond(char ch) { |
|
||||||
return String.Format("ch == {0}", Ch(ch)); |
|
||||||
} |
|
||||||
|
|
||||||
private static void PutRange(BitArray s) { |
|
||||||
int[] lo = new int[32]; |
|
||||||
int[] hi = new int[32]; |
|
||||||
// fill lo and hi
|
|
||||||
int max = CharClass.charSetSize; |
|
||||||
int top = -1; |
|
||||||
int i = 0; |
|
||||||
while (i < max) { |
|
||||||
if (s[i]) { |
|
||||||
top++; lo[top] = i; i++; |
|
||||||
while (i < max && s[i]) i++; |
|
||||||
hi[top] = i-1; |
|
||||||
} else i++; |
|
||||||
} |
|
||||||
// print ranges
|
|
||||||
if (top == 1 && lo[0] == 0 && hi[1] == max-1 && hi[0]+2 == lo[1]) { |
|
||||||
BitArray s1 = new BitArray(max); s1[hi[0]+1] = true; |
|
||||||
gen.Write("!"); PutRange(s1); |
|
||||||
} else { |
|
||||||
gen.Write("("); |
|
||||||
for (i = 0; i <= top; i++) { |
|
||||||
if (hi[i] == lo[i]) gen.Write("ch == {0}", Ch((char)lo[i])); |
|
||||||
else if (lo[i] == 0) gen.Write("ch <= {0}", Ch((char)hi[i])); |
|
||||||
else if (hi[i] == max-1) gen.Write("ch >= {0}", Ch((char)lo[i])); |
|
||||||
else gen.Write("ch >= {0} && ch <= {1}", Ch((char)lo[i]), Ch((char)hi[i])); |
|
||||||
if (i < top) gen.Write(" || "); |
|
||||||
} |
|
||||||
gen.Write(")"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//---------- String handling
|
|
||||||
static char Hex2Char(string s) { |
|
||||||
int val = 0; |
|
||||||
for (int i = 0; i < s.Length; i++) { |
|
||||||
char ch = s[i]; |
|
||||||
if ('0' <= ch && ch <= '9') val = 16 * val + (ch - '0'); |
|
||||||
else if ('a' <= ch && ch <= 'f') val = 16 * val + (10 + ch - 'a'); |
|
||||||
else if ('A' <= ch && ch <= 'F') val = 16 * val + (10 + ch - 'A'); |
|
||||||
else Parser.SemErr("bad escape sequence in string or character"); |
|
||||||
} |
|
||||||
if (val > CharClass.charSetSize) /* pdt */ |
|
||||||
Parser.SemErr("bad escape sequence in string or character"); |
|
||||||
return (char) (val % CharClass.charSetSize); |
|
||||||
} |
|
||||||
|
|
||||||
static string Char2Hex(char ch) { |
|
||||||
StringWriter w = new StringWriter(); |
|
||||||
w.Write("\\u{0:x4}", (int)ch); |
|
||||||
return w.ToString(); |
|
||||||
} |
|
||||||
|
|
||||||
public static string Unescape (string s) { |
|
||||||
/* replaces escape sequences in s by their Unicode values. */ |
|
||||||
StringBuilder buf = new StringBuilder(); |
|
||||||
int i = 0; |
|
||||||
while (i < s.Length) { |
|
||||||
if (s[i] == '\\') { |
|
||||||
switch (s[i+1]) { |
|
||||||
case '\\': buf.Append('\\'); i += 2; break; |
|
||||||
case '\'': buf.Append('\''); i += 2; break; |
|
||||||
case '\"': buf.Append('\"'); i += 2; break; |
|
||||||
case 'r': buf.Append('\r'); i += 2; break; |
|
||||||
case 'n': buf.Append('\n'); i += 2; break; |
|
||||||
case 't': buf.Append('\t'); i += 2; break; |
|
||||||
case '0': buf.Append('\0'); i += 2; break; |
|
||||||
case 'a': buf.Append('\a'); i += 2; break; |
|
||||||
case 'b': buf.Append('\b'); i += 2; break; |
|
||||||
case 'f': buf.Append('\f'); i += 2; break; |
|
||||||
case 'v': buf.Append('\v'); i += 2; break; |
|
||||||
case 'u': case 'x': |
|
||||||
if (i + 6 <= s.Length) { |
|
||||||
buf.Append(Hex2Char(s.Substring(i+2, 4))); i += 6; break; |
|
||||||
} else { |
|
||||||
Parser.SemErr("bad escape sequence in string or character"); i = s.Length; break; |
|
||||||
} |
|
||||||
default: Parser.SemErr("bad escape sequence in string or character"); i += 2; break; |
|
||||||
} |
|
||||||
} else { |
|
||||||
buf.Append(s[i]); |
|
||||||
i++; |
|
||||||
} |
|
||||||
} |
|
||||||
return buf.ToString(); |
|
||||||
} |
|
||||||
|
|
||||||
public static string Escape (string s) { |
|
||||||
StringBuilder buf = new StringBuilder(); |
|
||||||
foreach (char ch in s) { |
|
||||||
switch(ch) { |
|
||||||
case '\\': buf.Append("\\\\"); break; |
|
||||||
case '\'': buf.Append("\\'"); break; |
|
||||||
case '\"': buf.Append("\\\""); break; |
|
||||||
case '\t': buf.Append("\\t"); break; |
|
||||||
case '\r': buf.Append("\\r"); break; |
|
||||||
case '\n': buf.Append("\\n"); break; |
|
||||||
default: |
|
||||||
if (ch < ' ' || ch > '\u007f') buf.Append(Char2Hex(ch)); |
|
||||||
else buf.Append(ch); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
return buf.ToString(); |
|
||||||
} |
|
||||||
|
|
||||||
//---------- State handling
|
|
||||||
static State NewState() { |
|
||||||
State s = new State(); |
|
||||||
if (firstState == null) firstState = s; else lastState.next = s; |
|
||||||
lastState = s; |
|
||||||
return s; |
|
||||||
} |
|
||||||
|
|
||||||
static void NewTransition(State from, State to, int typ, int sym, int tc) { |
|
||||||
if (to == firstState) Parser.SemErr("token must not start with an iteration"); |
|
||||||
Target t = new Target(to); |
|
||||||
Action a = new Action(typ, sym, tc); a.target = t; |
|
||||||
from.AddAction(a); |
|
||||||
if (typ == Node.clas) curSy.tokenKind = Symbol.classToken; |
|
||||||
} |
|
||||||
|
|
||||||
static void CombineShifts() { |
|
||||||
State state; |
|
||||||
Action a, b, c; |
|
||||||
BitArray seta, setb; |
|
||||||
for (state = firstState; state != null; state = state.next) { |
|
||||||
for (a = state.firstAction; a != null; a = a.next) { |
|
||||||
b = a.next; |
|
||||||
while (b != null) |
|
||||||
if (a.target.state == b.target.state && a.tc == b.tc) { |
|
||||||
seta = a.Symbols(); setb = b.Symbols(); |
|
||||||
seta.Or(setb); |
|
||||||
a.ShiftWith(seta); |
|
||||||
c = b; b = b.next; state.DetachAction(c); |
|
||||||
} else b = b.next; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void FindUsedStates(State state, BitArray used) { |
|
||||||
if (used[state.nr]) return; |
|
||||||
used[state.nr] = true; |
|
||||||
for (Action a = state.firstAction; a != null; a = a.next) |
|
||||||
FindUsedStates(a.target.state, used); |
|
||||||
} |
|
||||||
|
|
||||||
static void DeleteRedundantStates() { |
|
||||||
State[] newState = new State[State.lastNr + 1]; |
|
||||||
BitArray used = new BitArray(State.lastNr + 1); |
|
||||||
FindUsedStates(firstState, used); |
|
||||||
// combine equal final states
|
|
||||||
for (State s1 = firstState.next; s1 != null; s1 = s1.next) // firstState cannot be final
|
|
||||||
if (used[s1.nr] && s1.endOf != null && s1.firstAction == null && !s1.ctx) |
|
||||||
for (State s2 = s1.next; s2 != null; s2 = s2.next) |
|
||||||
if (used[s2.nr] && s1.endOf == s2.endOf && s2.firstAction == null & !s2.ctx) { |
|
||||||
used[s2.nr] = false; newState[s2.nr] = s1; |
|
||||||
} |
|
||||||
for (State state = firstState; state != null; state = state.next) |
|
||||||
if (used[state.nr]) |
|
||||||
for (Action a = state.firstAction; a != null; a = a.next) |
|
||||||
if (!used[a.target.state.nr]) |
|
||||||
a.target.state = newState[a.target.state.nr]; |
|
||||||
// delete unused states
|
|
||||||
lastState = firstState; State.lastNr = 0; // firstState has number 0
|
|
||||||
for (State state = firstState.next; state != null; state = state.next) |
|
||||||
if (used[state.nr]) {state.nr = ++State.lastNr; lastState = state;} |
|
||||||
else lastState.next = state.next; |
|
||||||
} |
|
||||||
|
|
||||||
static State TheState(Node p) { |
|
||||||
State state; |
|
||||||
if (p == null) {state = NewState(); state.endOf = curSy; return state;} |
|
||||||
else return p.state; |
|
||||||
} |
|
||||||
|
|
||||||
static void Step(State from, Node p, BitArray stepped) { |
|
||||||
if (p == null) return; |
|
||||||
stepped[p.n] = true; |
|
||||||
switch (p.typ) { |
|
||||||
case Node.clas: case Node.chr: { |
|
||||||
NewTransition(from, TheState(p.next), p.typ, p.val, p.code); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.alt: { |
|
||||||
Step(from, p.sub, stepped); Step(from, p.down, stepped); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.iter: case Node.opt: { |
|
||||||
if (p.next != null && !stepped[p.next.n]) Step(from, p.next, stepped); |
|
||||||
Step(from, p.sub, stepped); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void NumberNodes(Node p, State state) { |
|
||||||
/* Assigns a state n.state to every node n. There will be a transition from |
|
||||||
n.state to n.next.state triggered by n.val. All nodes in an alternative |
|
||||||
chain are represented by the same state. |
|
||||||
*/ |
|
||||||
if (p == null) return; |
|
||||||
if (p.state != null) return; // already visited;
|
|
||||||
if (state == null) state = NewState(); |
|
||||||
p.state = state; |
|
||||||
if (Node.DelGraph(p)) state.endOf = curSy; |
|
||||||
switch (p.typ) { |
|
||||||
case Node.clas: case Node.chr: { |
|
||||||
NumberNodes(p.next, null); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.opt: { |
|
||||||
NumberNodes(p.next, null); NumberNodes(p.sub, state); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.iter: { |
|
||||||
NumberNodes(p.next, state); NumberNodes(p.sub, state); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.alt: { |
|
||||||
NumberNodes(p.sub, state); NumberNodes(p.down, state); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void FindTrans (Node p, bool start, BitArray marked) { |
|
||||||
if (p == null || marked[p.n]) return; |
|
||||||
marked[p.n] = true; |
|
||||||
if (start) Step(p.state, p, new BitArray(Node.nodes.Count)); // start of group of equally numbered nodes
|
|
||||||
switch (p.typ) { |
|
||||||
case Node.clas: case Node.chr: { |
|
||||||
FindTrans(p.next, true, marked); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.opt: { |
|
||||||
FindTrans(p.next, true, marked); FindTrans(p.sub, false, marked); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.iter: { |
|
||||||
FindTrans(p.next, false, marked); FindTrans(p.sub, false, marked); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.alt: { |
|
||||||
FindTrans(p.sub, false, marked); FindTrans(p.down, false, marked); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void ConvertToStates(Node p, Symbol sym) { |
|
||||||
curGraph = p; curSy = sym; |
|
||||||
if (Node.DelGraph(curGraph)) Parser.SemErr("token might be empty"); |
|
||||||
NumberNodes(curGraph, firstState); |
|
||||||
FindTrans(curGraph, true, new BitArray(Node.nodes.Count)); |
|
||||||
} |
|
||||||
|
|
||||||
// match string against current automaton; store it either as a fixedToken or as a litToken
|
|
||||||
public static void MatchLiteral(string s, Symbol sym) { |
|
||||||
s = Unescape(s.Substring(1, s.Length-2)); |
|
||||||
int i, len = s.Length; |
|
||||||
State state = firstState; |
|
||||||
Action a = null; |
|
||||||
for (i = 0; i < len; i++) { // try to match s against existing DFA
|
|
||||||
a = state.TheAction(s[i]); |
|
||||||
if (a == null) break; |
|
||||||
state = a.target.state; |
|
||||||
} |
|
||||||
// if s was not totally consumed or leads to a non-final state => make new DFA from it
|
|
||||||
if (i != len || state.endOf == null) { |
|
||||||
state = firstState; i = 0; a = null; |
|
||||||
dirtyDFA = true; |
|
||||||
} |
|
||||||
for (; i < len; i++) { // make new DFA for s[i..len-1]
|
|
||||||
State to = NewState(); |
|
||||||
NewTransition(state, to, Node.chr, s[i], Node.normalTrans); |
|
||||||
state = to; |
|
||||||
} |
|
||||||
Symbol matchedSym = state.endOf; |
|
||||||
if (state.endOf == null) { |
|
||||||
state.endOf = sym; |
|
||||||
} else if (matchedSym.tokenKind == Symbol.fixedToken || (a != null && a.tc == Node.contextTrans)) { |
|
||||||
// s matched a token with a fixed definition or a token with an appendix that will be cut off
|
|
||||||
Parser.SemErr("tokens " + sym.name + " and " + matchedSym.name + " cannot be distinguished"); |
|
||||||
} else { // matchedSym == classToken || classLitToken
|
|
||||||
matchedSym.tokenKind = Symbol.classLitToken; |
|
||||||
sym.tokenKind = Symbol.litToken; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void SplitActions(State state, Action a, Action b) { |
|
||||||
Action c; BitArray seta, setb, setc; |
|
||||||
seta = a.Symbols(); setb = b.Symbols(); |
|
||||||
if (Sets.Equals(seta, setb)) { |
|
||||||
a.AddTargets(b); |
|
||||||
state.DetachAction(b); |
|
||||||
} else if (Sets.Includes(seta, setb)) { |
|
||||||
setc = (BitArray)seta.Clone(); Sets.Subtract(setc, setb); |
|
||||||
b.AddTargets(a); |
|
||||||
a.ShiftWith(setc); |
|
||||||
} else if (Sets.Includes(setb, seta)) { |
|
||||||
setc = (BitArray)setb.Clone(); Sets.Subtract(setc, seta); |
|
||||||
a.AddTargets(b); |
|
||||||
b.ShiftWith(setc); |
|
||||||
} else { |
|
||||||
setc = (BitArray)seta.Clone(); setc.And(setb); |
|
||||||
Sets.Subtract(seta, setc); |
|
||||||
Sets.Subtract(setb, setc); |
|
||||||
a.ShiftWith(seta); |
|
||||||
b.ShiftWith(setb); |
|
||||||
c = new Action(0, 0, Node.normalTrans); // typ and sym are set in ShiftWith
|
|
||||||
c.AddTargets(a); |
|
||||||
c.AddTargets(b); |
|
||||||
c.ShiftWith(setc); |
|
||||||
state.AddAction(c); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private static bool Overlap(Action a, Action b) { |
|
||||||
BitArray seta, setb; |
|
||||||
if (a.typ == Node.chr) |
|
||||||
if (b.typ == Node.chr) return a.sym == b.sym; |
|
||||||
else {setb = CharClass.Set(b.sym); return setb[a.sym];} |
|
||||||
else { |
|
||||||
seta = CharClass.Set(a.sym); |
|
||||||
if (b.typ ==Node.chr) return seta[b.sym]; |
|
||||||
else {setb = CharClass.Set(b.sym); return Sets.Intersect(seta, setb);} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static bool MakeUnique(State state) { // return true if actions were split
|
|
||||||
bool changed = false; |
|
||||||
for (Action a = state.firstAction; a != null; a = a.next) |
|
||||||
for (Action b = a.next; b != null; b = b.next) |
|
||||||
if (Overlap(a, b)) {SplitActions(state, a, b); changed = true;} |
|
||||||
return changed; |
|
||||||
} |
|
||||||
|
|
||||||
static void MeltStates(State state) { |
|
||||||
bool changed, ctx; |
|
||||||
BitArray targets; |
|
||||||
Symbol endOf; |
|
||||||
for (Action action = state.firstAction; action != null; action = action.next) { |
|
||||||
if (action.target.next != null) { |
|
||||||
action.GetTargetStates(out targets, out endOf, out ctx); |
|
||||||
Melted melt = Melted.StateWithSet(targets); |
|
||||||
if (melt == null) { |
|
||||||
State s = NewState(); s.endOf = endOf; s.ctx = ctx; |
|
||||||
for (Target targ = action.target; targ != null; targ = targ.next) |
|
||||||
s.MeltWith(targ.state); |
|
||||||
do {changed = MakeUnique(s);} while (changed); |
|
||||||
melt = new Melted(targets, s); |
|
||||||
} |
|
||||||
action.target.next = null; |
|
||||||
action.target.state = melt.state; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void FindCtxStates() { |
|
||||||
for (State state = firstState; state != null; state = state.next) |
|
||||||
for (Action a = state.firstAction; a != null; a = a.next) |
|
||||||
if (a.tc == Node.contextTrans) a.target.state.ctx = true; |
|
||||||
} |
|
||||||
|
|
||||||
public static void MakeDeterministic() { |
|
||||||
State state; |
|
||||||
bool changed; |
|
||||||
lastSimState = lastState.nr; |
|
||||||
maxStates = 2 * lastSimState; // heuristic for set size in Melted.set
|
|
||||||
FindCtxStates(); |
|
||||||
for (state = firstState; state != null; state = state.next) |
|
||||||
do {changed = MakeUnique(state);} while (changed); |
|
||||||
for (state = firstState; state != null; state = state.next) |
|
||||||
MeltStates(state); |
|
||||||
DeleteRedundantStates(); |
|
||||||
CombineShifts(); |
|
||||||
} |
|
||||||
|
|
||||||
public static void PrintStates() { |
|
||||||
Trace.WriteLine(); |
|
||||||
Trace.WriteLine("---------- states ----------"); |
|
||||||
for (State state = firstState; state != null; state = state.next) { |
|
||||||
bool first = true; |
|
||||||
if (state.endOf == null) Trace.Write(" "); |
|
||||||
else Trace.Write("E({0,12})", Node.Name(state.endOf.name)); |
|
||||||
Trace.Write("{0,3}:", state.nr); |
|
||||||
if (state.firstAction == null) Trace.WriteLine(); |
|
||||||
for (Action action = state.firstAction; action != null; action = action.next) { |
|
||||||
if (first) {Trace.Write(" "); first = false;} else Trace.Write(" "); |
|
||||||
if (action.typ == Node.clas) Trace.Write(((CharClass)CharClass.classes[action.sym]).name); |
|
||||||
else Trace.Write("{0, 3}", Ch((char)action.sym)); |
|
||||||
for (Target targ = action.target; targ != null; targ = targ.next) |
|
||||||
Trace.Write(" {0, 3}", targ.state.nr); |
|
||||||
if (action.tc == Node.contextTrans) Trace.WriteLine(" context"); else Trace.WriteLine(); |
|
||||||
} |
|
||||||
} |
|
||||||
Trace.WriteLine(); |
|
||||||
Trace.WriteLine("---------- character classes ----------"); |
|
||||||
CharClass.WriteClasses(); |
|
||||||
} |
|
||||||
|
|
||||||
static void GenComBody(Comment com) { |
|
||||||
gen.WriteLine( "\t\t\tfor(;;) {"); |
|
||||||
gen.Write ( "\t\t\t\tif ({0}) ", ChCond(com.stop[0])); gen.WriteLine("{"); |
|
||||||
if (com.stop.Length == 1) { |
|
||||||
gen.WriteLine("\t\t\t\t\tlevel--;"); |
|
||||||
gen.WriteLine("\t\t\t\t\tif (level == 0) { oldEols = line - line0; NextCh(); return true; }"); |
|
||||||
gen.WriteLine("\t\t\t\t\tNextCh();"); |
|
||||||
} else { |
|
||||||
gen.WriteLine("\t\t\t\t\tNextCh();"); |
|
||||||
gen.WriteLine("\t\t\t\t\tif ({0}) {{", ChCond(com.stop[1])); |
|
||||||
gen.WriteLine("\t\t\t\t\t\tlevel--;"); |
|
||||||
gen.WriteLine("\t\t\t\t\t\tif (level == 0) { oldEols = line - line0; NextCh(); return true; }"); |
|
||||||
gen.WriteLine("\t\t\t\t\t\tNextCh();"); |
|
||||||
gen.WriteLine("\t\t\t\t\t}"); |
|
||||||
} |
|
||||||
if (com.nested) { |
|
||||||
gen.Write ("\t\t\t\t}"); gen.Write(" else if ({0}) ", ChCond(com.start[0])); gen.WriteLine("{"); |
|
||||||
if (com.start.Length == 1) |
|
||||||
gen.WriteLine("\t\t\t\t\tlevel++; NextCh();"); |
|
||||||
else { |
|
||||||
gen.WriteLine("\t\t\t\t\tNextCh();"); |
|
||||||
gen.Write ("\t\t\t\t\tif ({0}) ", ChCond(com.start[1])); gen.WriteLine("{"); |
|
||||||
gen.WriteLine("\t\t\t\t\t\tlevel++; NextCh();"); |
|
||||||
gen.WriteLine("\t\t\t\t\t}"); |
|
||||||
} |
|
||||||
} |
|
||||||
gen.WriteLine( "\t\t\t\t} else if (ch == Buffer.EOF) return false;"); |
|
||||||
gen.WriteLine( "\t\t\t\telse NextCh();"); |
|
||||||
gen.WriteLine( "\t\t\t}"); |
|
||||||
} |
|
||||||
|
|
||||||
static void GenComment(Comment com, int i) { |
|
||||||
gen.WriteLine(); |
|
||||||
gen.Write ("\tstatic bool Comment{0}() ", i); gen.WriteLine("{"); |
|
||||||
gen.WriteLine("\t\tint level = 1, line0 = line, lineStart0 = lineStart;"); |
|
||||||
if (com.start.Length == 1) { |
|
||||||
gen.WriteLine("\t\tNextCh();"); |
|
||||||
GenComBody(com); |
|
||||||
} else { |
|
||||||
gen.WriteLine("\t\tNextCh();"); |
|
||||||
gen.Write ("\t\tif ({0}) ", ChCond(com.start[1])); gen.WriteLine("{"); |
|
||||||
gen.WriteLine("\t\t\tNextCh();"); |
|
||||||
GenComBody(com); |
|
||||||
gen.WriteLine("\t\t} else {"); |
|
||||||
gen.WriteLine("\t\t\tif (ch==EOL) {line--; lineStart = lineStart0;}"); |
|
||||||
gen.WriteLine("\t\t\tpos = pos - 2; Buffer.Pos = pos+1; NextCh();"); |
|
||||||
gen.WriteLine("\t\t}"); |
|
||||||
gen.WriteLine("\t\treturn false;"); |
|
||||||
} |
|
||||||
gen.WriteLine("\t}"); |
|
||||||
} |
|
||||||
|
|
||||||
static void CopyFramePart(string stop) { |
|
||||||
char startCh = stop[0]; |
|
||||||
int endOfStopString = stop.Length-1; |
|
||||||
int ch = fram.ReadByte(); |
|
||||||
while (ch != EOF) |
|
||||||
if (ch == startCh) { |
|
||||||
int i = 0; |
|
||||||
do { |
|
||||||
if (i == endOfStopString) return; // stop[0..i] found
|
|
||||||
ch = fram.ReadByte(); i++; |
|
||||||
} while (ch == stop[i]); |
|
||||||
// stop[0..i-1] found; continue with last read character
|
|
||||||
gen.Write(stop.Substring(0, i)); |
|
||||||
} else { |
|
||||||
gen.Write((char)ch); ch = fram.ReadByte(); |
|
||||||
} |
|
||||||
Errors.Exception(" -- incomplete or corrupt scanner frame file"); |
|
||||||
} |
|
||||||
|
|
||||||
static string SymName(Symbol sym) { |
|
||||||
if (Char.IsLetter(sym.name[0])) { // real name value is stored in Tab.literals
|
|
||||||
foreach (DictionaryEntry e in Tab.literals) |
|
||||||
if ((Symbol)e.Value == sym) return (string)e.Key; |
|
||||||
} |
|
||||||
return sym.name; |
|
||||||
} |
|
||||||
|
|
||||||
static void GenLiterals () { |
|
||||||
if (ignoreCase) { |
|
||||||
gen.WriteLine("\t\tswitch (t.val.ToLower()) {"); |
|
||||||
} else { |
|
||||||
gen.WriteLine("\t\tswitch (t.val) {"); |
|
||||||
} |
|
||||||
foreach (Symbol sym in Symbol.terminals) { |
|
||||||
if (sym.tokenKind == Symbol.litToken) { |
|
||||||
string name = SymName(sym); |
|
||||||
if (ignoreCase) name = name.ToLower(); |
|
||||||
// sym.name stores literals with quotes, e.g. "\"Literal\""
|
|
||||||
gen.WriteLine("\t\t\tcase {0}: t.kind = {1}; break;", name, sym.n); |
|
||||||
} |
|
||||||
} |
|
||||||
gen.WriteLine("\t\t\tdefault: break;"); |
|
||||||
gen.Write("\t\t}"); |
|
||||||
} |
|
||||||
|
|
||||||
static void WriteState(State state) { |
|
||||||
Symbol endOf = state.endOf; |
|
||||||
gen.WriteLine("\t\t\tcase {0}:", state.nr); |
|
||||||
bool ctxEnd = state.ctx; |
|
||||||
for (Action action = state.firstAction; action != null; action = action.next) { |
|
||||||
if (action == state.firstAction) gen.Write("\t\t\t\tif ("); |
|
||||||
else gen.Write("\t\t\t\telse if ("); |
|
||||||
if (action.typ == Node.chr) gen.Write(ChCond((char)action.sym)); |
|
||||||
else PutRange(CharClass.Set(action.sym)); |
|
||||||
gen.Write(") {"); |
|
||||||
if (action.tc == Node.contextTrans) { |
|
||||||
gen.Write("apx++; "); ctxEnd = false; |
|
||||||
} else if (state.ctx) |
|
||||||
gen.Write("apx = 0; "); |
|
||||||
if (ignoreCase) gen.Write("buf.Append(valCh); "); else gen.Write("buf.Append(ch); "); |
|
||||||
gen.Write("NextCh(); goto case {0};", action.target.state.nr); |
|
||||||
gen.WriteLine("}"); |
|
||||||
} |
|
||||||
if (state.firstAction == null) |
|
||||||
gen.Write("\t\t\t\t{"); |
|
||||||
else |
|
||||||
gen.Write("\t\t\t\telse {"); |
|
||||||
if (ctxEnd) { // final context state: cut appendix
|
|
||||||
gen.WriteLine(); |
|
||||||
gen.WriteLine("\t\t\t\t\tbuf.Length = buf.Length - apx;"); |
|
||||||
gen.WriteLine("\t\t\t\t\tpos = pos - apx - 1; line = t.line;"); |
|
||||||
gen.WriteLine("\t\t\t\t\tBuffer.Pos = pos+1; NextCh();"); |
|
||||||
gen.Write( "\t\t\t\t\t"); |
|
||||||
} |
|
||||||
if (endOf == null) { |
|
||||||
gen.WriteLine("t.kind = noSym; goto done;}"); |
|
||||||
} else { |
|
||||||
gen.Write("t.kind = {0}; ", endOf.n); |
|
||||||
if (endOf.tokenKind == Symbol.classLitToken) { |
|
||||||
gen.WriteLine("t.val = buf.ToString(); CheckLiteral(); return t;}"); |
|
||||||
} else { |
|
||||||
gen.WriteLine("goto done;}"); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void FillStartTab(int[] startTab) { |
|
||||||
for (Action action = firstState.firstAction; action != null; action = action.next) { |
|
||||||
int targetState = action.target.state.nr; |
|
||||||
if (action.typ == Node.chr) startTab[action.sym] = targetState; |
|
||||||
else { |
|
||||||
BitArray s = CharClass.Set(action.sym); |
|
||||||
for (int i = 0; i < s.Count; i++) |
|
||||||
if (s[i]) startTab[i] = targetState; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void OpenGen(bool backUp) { /* pdt */ |
|
||||||
try { |
|
||||||
string fn = srcDir + "Scanner.cs"; /* pdt */ |
|
||||||
if (File.Exists(fn) && backUp) File.Copy(fn, fn + ".old", true); |
|
||||||
gen = new StreamWriter(new FileStream(fn, FileMode.Create)); /* pdt */ |
|
||||||
} catch (IOException) { |
|
||||||
Errors.Exception("-- Cannot generate scanner file"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void WriteScanner() { |
|
||||||
int i, j; |
|
||||||
int[] startTab = new int[CharClass.charSetSize]; |
|
||||||
string fr = srcDir + "Scanner.frame"; /* pdt */ |
|
||||||
if (!File.Exists(fr)) { |
|
||||||
if (Tab.frameDir != null) fr = Tab.frameDir.Trim() + Path.DirectorySeparatorChar + "Scanner.frame"; |
|
||||||
if (!File.Exists(fr)) Errors.Exception("-- Cannot find Scanner.frame"); |
|
||||||
} |
|
||||||
try { |
|
||||||
fram = new FileStream(fr, FileMode.Open, FileAccess.Read, FileShare.Read); |
|
||||||
} catch (FileNotFoundException) { |
|
||||||
Errors.Exception("-- Cannot open Scanner.frame."); |
|
||||||
} |
|
||||||
OpenGen(true); /* pdt */ |
|
||||||
if (dirtyDFA) MakeDeterministic(); |
|
||||||
FillStartTab(startTab); |
|
||||||
CopyFramePart("-->begin"); |
|
||||||
if (!srcName.ToLower().EndsWith("coco.atg")) { |
|
||||||
gen.Close(); OpenGen(false); /* pdt */ |
|
||||||
} |
|
||||||
CopyFramePart("-->namespace"); |
|
||||||
/* AW add namespace, if it exists */ |
|
||||||
if (Tab.nsName != null && Tab.nsName.Length > 0) { |
|
||||||
gen.Write("namespace "); |
|
||||||
gen.Write(Tab.nsName); |
|
||||||
gen.Write(" {"); |
|
||||||
} |
|
||||||
CopyFramePart("-->declarations"); |
|
||||||
gen.WriteLine("\tconst int charSetSize = {0};", CharClass.charSetSize); |
|
||||||
gen.WriteLine("\tconst int maxT = {0};", Symbol.terminals.Count - 1); |
|
||||||
gen.WriteLine("\tconst int noSym = {0};", Tab.noSym.n); |
|
||||||
gen.WriteLine("\tstatic short[] start = {"); |
|
||||||
for (i = 0; i < CharClass.charSetSize / 16; i++) { |
|
||||||
gen.Write("\t"); |
|
||||||
for (j = 0; j < 16; j++) |
|
||||||
gen.Write("{0,3},", startTab[16*i+j]); |
|
||||||
gen.WriteLine(); |
|
||||||
} |
|
||||||
gen.WriteLine("\t -1};"); /* pdt */ |
|
||||||
if (ignoreCase) |
|
||||||
gen.Write("\tstatic char valCh; // current input character (for token.val)"); |
|
||||||
CopyFramePart("-->initialization"); |
|
||||||
gen.WriteLine("\t\tignore = new BitArray(charSetSize+1);"); /* pdt */ |
|
||||||
gen.Write("\t\t"); |
|
||||||
if (Tab.ignored == null) gen.Write("ignore[' '] = true;"); |
|
||||||
else { |
|
||||||
j = 0; |
|
||||||
for (i = 0; i < Tab.ignored.Count; i++) |
|
||||||
if (Tab.ignored[i]) { |
|
||||||
gen.Write("ignore[{0}] = true; ", i); |
|
||||||
if (++j % 4 == 0) { gen.WriteLine(); gen.Write("\t\t"); } |
|
||||||
} |
|
||||||
} |
|
||||||
CopyFramePart("-->casing"); |
|
||||||
if (ignoreCase) { |
|
||||||
gen.WriteLine("\t\tvalCh = ch;"); |
|
||||||
gen.Write ("\t\tif (ch != Buffer.EOF) ch = char.ToLower(ch);"); |
|
||||||
} |
|
||||||
CopyFramePart("-->comments"); |
|
||||||
Comment com = Comment.first; i = 0; |
|
||||||
while (com != null) { |
|
||||||
GenComment(com, i); |
|
||||||
com = com.next; i++; |
|
||||||
} |
|
||||||
CopyFramePart("-->literals"); GenLiterals(); |
|
||||||
CopyFramePart("-->scan1"); |
|
||||||
if (Comment.first!=null) { |
|
||||||
gen.Write("\t\tif ("); |
|
||||||
com = Comment.first; i = 0; |
|
||||||
while (com != null) { |
|
||||||
gen.Write(ChCond(com.start[0])); |
|
||||||
gen.Write(" && Comment{0}()", i); |
|
||||||
if (com.next != null) gen.Write(" ||"); |
|
||||||
com = com.next; i++; |
|
||||||
} |
|
||||||
gen.Write(") return NextToken();"); |
|
||||||
} |
|
||||||
if (hasCtxMoves) { gen.WriteLine(); gen.Write("\t\tint apx = 0;"); } /* pdt */ |
|
||||||
CopyFramePart("-->scan2"); |
|
||||||
if (ignoreCase) gen.Write("\t\tbuf.Append(valCh); NextCh();"); |
|
||||||
else gen.Write("\t\tbuf.Append(ch); NextCh();"); |
|
||||||
CopyFramePart("-->scan3"); |
|
||||||
for (State state = firstState.next; state != null; state = state.next) |
|
||||||
WriteState(state); |
|
||||||
CopyFramePart("$$$"); |
|
||||||
/* AW 12-20-02 close namespace, if it exists */ |
|
||||||
if (Tab.nsName != null && Tab.nsName.Length > 0) gen.Write("}"); |
|
||||||
gen.Close(); |
|
||||||
} |
|
||||||
|
|
||||||
public static void Init (string file, string dir) { |
|
||||||
srcName = file; |
|
||||||
srcDir = dir; |
|
||||||
firstState = null; lastState = null; State.lastNr = -1; |
|
||||||
firstState = NewState(); |
|
||||||
Melted.first = null; Comment.first = null; |
|
||||||
ignoreCase = false; |
|
||||||
dirtyDFA = false; |
|
||||||
hasCtxMoves = false; |
|
||||||
} |
|
||||||
|
|
||||||
} // end DFA
|
|
||||||
|
|
||||||
} // end namespace
|
|
||||||
@ -1,785 +0,0 @@ |
|||||||
/*---------------------------------------------------------------------- |
|
||||||
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); |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void SimSet(out BitArray s) { |
|
||||||
int n1, n2; |
|
||||||
s = new BitArray(CharClass.charSetSize); |
|
||||||
if (la.kind == 1) { |
|
||||||
Get(); |
|
||||||
CharClass c = CharClass.Find(t.val); |
|
||||||
if (c == null) SemErr("undefined name"); else s.Or(c.set); |
|
||||||
|
|
||||||
} else if (la.kind == 3) { |
|
||||||
Get(); |
|
||||||
string name = t.val; |
|
||||||
name = DFA.Unescape(name.Substring(1, name.Length-2)); |
|
||||||
foreach (char ch in name) |
|
||||||
if (DFA.ignoreCase) s[char.ToLower(ch)] = true; |
|
||||||
else s[ch] = true; |
|
||||||
} else if (la.kind == 5) { |
|
||||||
Char(out n1); |
|
||||||
s[n1] = true; |
|
||||||
if (la.kind == 22) { |
|
||||||
Get(); |
|
||||||
Char(out n2); |
|
||||||
for (int i = n1; i <= n2; i++) s[i] = true; |
|
||||||
} |
|
||||||
} else if (la.kind == 23) { |
|
||||||
Get(); |
|
||||||
s = new BitArray(CharClass.charSetSize, true); |
|
||||||
} else SynErr(45); |
|
||||||
} |
|
||||||
|
|
||||||
static void Char(out int n) { |
|
||||||
Expect(5); |
|
||||||
string name = t.val; n = 0; |
|
||||||
name = DFA.Unescape(name.Substring(1, name.Length-2)); |
|
||||||
int max = CharClass.charSetSize; |
|
||||||
if (name.Length == 1 && name[0] <= max-1) n = name[0] % max; |
|
||||||
else SemErr("unacceptable character value"); |
|
||||||
if (DFA.ignoreCase && (char)n >= 'A' && (char)n <= 'Z') n += 32; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
static void Sym(out string name, out int kind) { |
|
||||||
name = "???"; kind = id; |
|
||||||
if (la.kind == 1) { |
|
||||||
Get(); |
|
||||||
kind = id; name = t.val; |
|
||||||
} else if (la.kind == 3 || la.kind == 5) { |
|
||||||
if (la.kind == 3) { |
|
||||||
Get(); |
|
||||||
name = t.val; |
|
||||||
} else { |
|
||||||
Get(); |
|
||||||
name = "\"" + t.val.Substring(1, t.val.Length-2) + "\""; |
|
||||||
} |
|
||||||
kind = str; |
|
||||||
if (DFA.ignoreCase) name = name.ToLower(); |
|
||||||
if (name.IndexOf(' ') >= 0) |
|
||||||
SemErr("literal tokens must not contain blanks"); |
|
||||||
} else SynErr(46); |
|
||||||
} |
|
||||||
|
|
||||||
static void Term(out Graph g) { |
|
||||||
Graph g2; Node rslv = null; g = null; |
|
||||||
if (StartOf(15)) { |
|
||||||
if (la.kind == 35) { |
|
||||||
rslv = new Node(Node.rslv, null, la.line); |
|
||||||
Resolver(out rslv.pos); |
|
||||||
g = new Graph(rslv); |
|
||||||
} |
|
||||||
Factor(out g2); |
|
||||||
if (rslv != null) Graph.MakeSequence(g, g2); |
|
||||||
else g = g2; |
|
||||||
|
|
||||||
while (StartOf(16)) { |
|
||||||
Factor(out g2); |
|
||||||
Graph.MakeSequence(g, g2); |
|
||||||
} |
|
||||||
} else if (StartOf(17)) { |
|
||||||
g = new Graph(new Node(Node.eps, null, 0)); |
|
||||||
} else SynErr(47); |
|
||||||
if (g == null) // invalid start of Term
|
|
||||||
g = new Graph(new Node(Node.eps, null, 0)); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
static void Resolver(out Position pos) { |
|
||||||
Expect(35); |
|
||||||
Expect(28); |
|
||||||
int beg = la.pos; int col = la.col; |
|
||||||
Condition(); |
|
||||||
pos = new Position(beg, t.pos - beg, col); |
|
||||||
} |
|
||||||
|
|
||||||
static void Factor(out Graph g) { |
|
||||||
string name; int kind; Position pos; bool weak = false; |
|
||||||
g = null; |
|
||||||
|
|
||||||
switch (la.kind) { |
|
||||||
case 1: case 3: case 5: case 27: { |
|
||||||
if (la.kind == 27) { |
|
||||||
Get(); |
|
||||||
weak = true; |
|
||||||
} |
|
||||||
Sym(out name, out kind); |
|
||||||
Symbol sym = Symbol.Find(name); |
|
||||||
if (sym == null && kind == str) |
|
||||||
sym = Tab.literals[name] as Symbol; |
|
||||||
bool undef = sym == null; |
|
||||||
if (undef) { |
|
||||||
if (kind == id) |
|
||||||
sym = new Symbol(Node.nt, name, 0); // forward nt
|
|
||||||
else if (genScanner) { |
|
||||||
sym = new Symbol(Node.t, name, t.line); |
|
||||||
DFA.MatchLiteral(sym.name, sym); |
|
||||||
} else { // undefined string in production
|
|
||||||
SemErr("undefined string in production"); |
|
||||||
sym = Tab.eofSy; // dummy
|
|
||||||
} |
|
||||||
} |
|
||||||
int typ = sym.typ; |
|
||||||
if (typ != Node.t && typ != Node.nt) |
|
||||||
SemErr("this symbol kind is not allowed in a production"); |
|
||||||
if (weak) |
|
||||||
if (typ == Node.t) typ = Node.wt; |
|
||||||
else SemErr("only terminals may be weak"); |
|
||||||
Node p = new Node(typ, sym, t.line); |
|
||||||
g = new Graph(p); |
|
||||||
|
|
||||||
if (la.kind == 24) { |
|
||||||
Attribs(p); |
|
||||||
if (kind != id) SemErr("a literal must not have attributes"); |
|
||||||
} |
|
||||||
if (undef) |
|
||||||
sym.attrPos = p.pos; // dummy
|
|
||||||
else if ((p.pos == null) != (sym.attrPos == null)) |
|
||||||
SemErr("attribute mismatch between declaration and use of this symbol"); |
|
||||||
|
|
||||||
break; |
|
||||||
} |
|
||||||
case 28: { |
|
||||||
Get(); |
|
||||||
Expression(out g); |
|
||||||
Expect(29); |
|
||||||
break; |
|
||||||
} |
|
||||||
case 30: { |
|
||||||
Get(); |
|
||||||
Expression(out g); |
|
||||||
Expect(31); |
|
||||||
Graph.MakeOption(g); |
|
||||||
break; |
|
||||||
} |
|
||||||
case 32: { |
|
||||||
Get(); |
|
||||||
Expression(out g); |
|
||||||
Expect(33); |
|
||||||
Graph.MakeIteration(g); |
|
||||||
break; |
|
||||||
} |
|
||||||
case 37: { |
|
||||||
SemText(out pos); |
|
||||||
Node p = new Node(Node.sem, null, 0); |
|
||||||
p.pos = pos; |
|
||||||
g = new Graph(p); |
|
||||||
|
|
||||||
break; |
|
||||||
} |
|
||||||
case 23: { |
|
||||||
Get(); |
|
||||||
Node p = new Node(Node.any, null, 0); // p.set is set in Tab.SetupAnys
|
|
||||||
g = new Graph(p); |
|
||||||
|
|
||||||
break; |
|
||||||
} |
|
||||||
case 34: { |
|
||||||
Get(); |
|
||||||
Node p = new Node(Node.sync, null, 0); |
|
||||||
g = new Graph(p); |
|
||||||
|
|
||||||
break; |
|
||||||
} |
|
||||||
default: SynErr(48); break; |
|
||||||
} |
|
||||||
if (g == null) // invalid start of Factor
|
|
||||||
g = new Graph(new Node(Node.eps, null, 0)); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
static void Attribs(Node p) { |
|
||||||
Expect(24); |
|
||||||
int beg = la.pos; int col = la.col; |
|
||||||
while (StartOf(9)) { |
|
||||||
// CHANGES BY M.KRUEGER
|
|
||||||
if (la.kind == 24) { |
|
||||||
Attribs(p); |
|
||||||
} else |
|
||||||
// EOC
|
|
||||||
if (StartOf(10)) { |
|
||||||
Get(); |
|
||||||
} else { |
|
||||||
Get(); |
|
||||||
SemErr("bad string in attributes"); |
|
||||||
} |
|
||||||
} |
|
||||||
Expect(25); |
|
||||||
if (t.pos > beg) p.pos = new Position(beg, t.pos - beg, col); |
|
||||||
} |
|
||||||
|
|
||||||
static void Condition() { |
|
||||||
while (StartOf(18)) { |
|
||||||
if (la.kind == 28) { |
|
||||||
Get(); |
|
||||||
Condition(); |
|
||||||
} else { |
|
||||||
Get(); |
|
||||||
} |
|
||||||
} |
|
||||||
Expect(29); |
|
||||||
} |
|
||||||
|
|
||||||
static void TokenTerm(out Graph g) { |
|
||||||
Graph g2; |
|
||||||
TokenFactor(out g); |
|
||||||
while (StartOf(7)) { |
|
||||||
TokenFactor(out g2); |
|
||||||
Graph.MakeSequence(g, g2); |
|
||||||
} |
|
||||||
if (la.kind == 36) { |
|
||||||
Get(); |
|
||||||
Expect(28); |
|
||||||
TokenExpr(out g2); |
|
||||||
Graph.SetContextTrans(g2.l); Graph.MakeSequence(g, g2); |
|
||||||
Expect(29); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void TokenFactor(out Graph g) { |
|
||||||
string name; int kind; |
|
||||||
g = null; |
|
||||||
if (la.kind == 1 || la.kind == 3 || la.kind == 5) { |
|
||||||
Sym(out name, out kind); |
|
||||||
if (kind == id) { |
|
||||||
CharClass c = CharClass.Find(name); |
|
||||||
if (c == null) { |
|
||||||
SemErr("undefined name"); |
|
||||||
c = new CharClass(name, new BitArray(CharClass.charSetSize)); |
|
||||||
} |
|
||||||
Node p = new Node(Node.clas, null, 0); p.val = c.n; |
|
||||||
g = new Graph(p); |
|
||||||
tokenString = noString; |
|
||||||
} else { // str
|
|
||||||
g = Graph.StrToGraph(name); |
|
||||||
if (tokenString == null) tokenString = name; |
|
||||||
else tokenString = noString; |
|
||||||
} |
|
||||||
|
|
||||||
} else if (la.kind == 28) { |
|
||||||
Get(); |
|
||||||
TokenExpr(out g); |
|
||||||
Expect(29); |
|
||||||
} else if (la.kind == 30) { |
|
||||||
Get(); |
|
||||||
TokenExpr(out g); |
|
||||||
Expect(31); |
|
||||||
Graph.MakeOption(g); |
|
||||||
} else if (la.kind == 32) { |
|
||||||
Get(); |
|
||||||
TokenExpr(out g); |
|
||||||
Expect(33); |
|
||||||
Graph.MakeIteration(g); |
|
||||||
} else SynErr(49); |
|
||||||
if (g == null) // invalid start of TokenFactor
|
|
||||||
g = new Graph(new Node(Node.eps, null, 0)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void Parse() { |
|
||||||
la = new Token(); |
|
||||||
la.val = ""; |
|
||||||
Get(); |
|
||||||
Coco(); |
|
||||||
|
|
||||||
Expect(0); |
|
||||||
} |
|
||||||
|
|
||||||
static bool[,] set = { |
|
||||||
{T,T,x,T, x,T,x,x, x,x,T,T, x,x,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x}, |
|
||||||
{x,T,T,T, T,T,T,x, x,x,x,x, T,T,T,x, x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,x}, |
|
||||||
{T,T,x,T, x,T,x,x, x,x,T,T, x,x,x,T, T,T,T,x, x,x,x,T, x,x,T,T, T,x,T,x, T,x,T,T, x,T,x,x, x,x,x}, |
|
||||||
{T,T,x,T, x,T,x,x, x,x,T,T, x,x,x,T, T,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x}, |
|
||||||
{x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, x,T,x}, |
|
||||||
{T,T,x,T, x,T,x,x, x,x,T,T, x,x,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x}, |
|
||||||
{x,T,x,T, x,T,x,x, x,x,T,T, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x}, |
|
||||||
{x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,T,x, T,x,x,x, x,x,x,x, x,x,x}, |
|
||||||
{x,x,x,x, x,x,x,x, x,x,x,T, x,T,T,T, T,x,T,x, x,x,x,x, x,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x}, |
|
||||||
{x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,x,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,x}, |
|
||||||
{x,T,T,T, x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,x,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,x}, |
|
||||||
{x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,x,T, T,T,x}, |
|
||||||
{x,T,T,T, x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,x,x,T, T,T,x}, |
|
||||||
{x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,T, x,x,T,T, T,T,T,T, T,T,T,T, x,T,x,x, x,x,x}, |
|
||||||
{x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x}, |
|
||||||
{x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,T, T,x,T,x, T,x,T,T, x,T,x,x, x,x,x}, |
|
||||||
{x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,T, T,x,T,x, T,x,T,x, x,T,x,x, x,x,x}, |
|
||||||
{x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,T,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x}, |
|
||||||
{x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,x,T,T, T,T,T,T, T,T,T,T, T,T,x} |
|
||||||
|
|
||||||
}; |
|
||||||
} // end Parser
|
|
||||||
|
|
||||||
|
|
||||||
public class Errors { |
|
||||||
public static int count = 0; // number of errors detected
|
|
||||||
public static string errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
|
|
||||||
|
|
||||||
public static void SynErr (int line, int col, int n) { |
|
||||||
string s; |
|
||||||
switch (n) { |
|
||||||
case 0: s = "EOF expected"; break; |
|
||||||
case 1: s = "ident expected"; break; |
|
||||||
case 2: s = "number expected"; break; |
|
||||||
case 3: s = "string expected"; break; |
|
||||||
case 4: s = "badString expected"; break; |
|
||||||
case 5: s = "char expected"; break; |
|
||||||
case 6: s = "\"COMPILER\" expected"; break; |
|
||||||
case 7: s = "\"IGNORECASE\" expected"; break; |
|
||||||
case 8: s = "\"CHARACTERS\" expected"; break; |
|
||||||
case 9: s = "\"TOKENS\" expected"; break; |
|
||||||
case 10: s = "\"PRAGMAS\" expected"; break; |
|
||||||
case 11: s = "\"COMMENTS\" expected"; break; |
|
||||||
case 12: s = "\"FROM\" expected"; break; |
|
||||||
case 13: s = "\"TO\" expected"; break; |
|
||||||
case 14: s = "\"NESTED\" expected"; break; |
|
||||||
case 15: s = "\"IGNORE\" expected"; break; |
|
||||||
case 16: s = "\"PRODUCTIONS\" expected"; break; |
|
||||||
case 17: s = "\"=\" expected"; break; |
|
||||||
case 18: s = "\".\" expected"; break; |
|
||||||
case 19: s = "\"END\" expected"; break; |
|
||||||
case 20: s = "\"+\" expected"; break; |
|
||||||
case 21: s = "\"-\" expected"; break; |
|
||||||
case 22: s = "\"..\" expected"; break; |
|
||||||
case 23: s = "\"ANY\" expected"; break; |
|
||||||
case 24: s = "\"<\" expected"; break; |
|
||||||
case 25: s = "\">\" expected"; break; |
|
||||||
case 26: s = "\"|\" expected"; break; |
|
||||||
case 27: s = "\"WEAK\" expected"; break; |
|
||||||
case 28: s = "\"(\" expected"; break; |
|
||||||
case 29: s = "\")\" expected"; break; |
|
||||||
case 30: s = "\"[\" expected"; break; |
|
||||||
case 31: s = "\"]\" expected"; break; |
|
||||||
case 32: s = "\"{\" expected"; break; |
|
||||||
case 33: s = "\"}\" expected"; break; |
|
||||||
case 34: s = "\"SYNC\" expected"; break; |
|
||||||
case 35: s = "\"IF\" expected"; break; |
|
||||||
case 36: s = "\"CONTEXT\" expected"; break; |
|
||||||
case 37: s = "\"(.\" expected"; break; |
|
||||||
case 38: s = "\".)\" expected"; break; |
|
||||||
case 39: s = "\"using\" expected"; break; |
|
||||||
case 40: s = "\";\" expected"; break; |
|
||||||
case 41: s = "??? expected"; break; |
|
||||||
case 42: s = "this symbol not expected in Coco"; break; |
|
||||||
case 43: s = "this symbol not expected in TokenDecl"; break; |
|
||||||
case 44: s = "invalid TokenDecl"; break; |
|
||||||
case 45: s = "invalid SimSet"; break; |
|
||||||
case 46: s = "invalid Sym"; break; |
|
||||||
case 47: s = "invalid Term"; break; |
|
||||||
case 48: s = "invalid Factor"; break; |
|
||||||
case 49: s = "invalid TokenFactor"; break; |
|
||||||
|
|
||||||
default: s = "error " + n; break; |
|
||||||
} |
|
||||||
Console.WriteLine(Errors.errMsgFormat, line, col, s); |
|
||||||
count++; |
|
||||||
} |
|
||||||
|
|
||||||
public static void SemErr (int line, int col, int n) { |
|
||||||
Console.WriteLine(errMsgFormat, line, col, ("error " + n)); |
|
||||||
count++; |
|
||||||
} |
|
||||||
|
|
||||||
public static void Error (int line, int col, string s) { |
|
||||||
Console.WriteLine(errMsgFormat, line, col, s); |
|
||||||
count++; |
|
||||||
} |
|
||||||
|
|
||||||
public static void Exception (string s) { |
|
||||||
Console.WriteLine(s); |
|
||||||
System.Environment.Exit(1); |
|
||||||
} |
|
||||||
} // Errors
|
|
||||||
|
|
||||||
} |
|
||||||
@ -1,140 +0,0 @@ |
|||||||
/*---------------------------------------------------------------------- |
|
||||||
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. |
|
||||||
----------------------------------------------------------------------*/ |
|
||||||
-->begin |
|
||||||
using System; |
|
||||||
|
|
||||||
-->namespace |
|
||||||
|
|
||||||
public class Parser { |
|
||||||
-->constants |
|
||||||
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; |
|
||||||
|
|
||||||
-->declarations |
|
||||||
|
|
||||||
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; } |
|
||||||
-->pragmas |
|
||||||
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); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
-->productions |
|
||||||
|
|
||||||
public static void Parse() { |
|
||||||
la = new Token(); |
|
||||||
la.val = ""; |
|
||||||
Get(); |
|
||||||
-->parseRoot |
|
||||||
Expect(0); |
|
||||||
} |
|
||||||
|
|
||||||
static bool[,] set = { |
|
||||||
-->initialization |
|
||||||
}; |
|
||||||
} // end Parser |
|
||||||
|
|
||||||
|
|
||||||
public class Errors { |
|
||||||
public static int count = 0; // number of errors detected |
|
||||||
public static string errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text |
|
||||||
|
|
||||||
public static void SynErr (int line, int col, int n) { |
|
||||||
string s; |
|
||||||
switch (n) { |
|
||||||
-->errors |
|
||||||
default: s = "error " + n; break; |
|
||||||
} |
|
||||||
Console.WriteLine(Errors.errMsgFormat, line, col, s); |
|
||||||
count++; |
|
||||||
} |
|
||||||
|
|
||||||
public static void SemErr (int line, int col, int n) { |
|
||||||
Console.WriteLine(errMsgFormat, line, col, ("error " + n)); |
|
||||||
count++; |
|
||||||
} |
|
||||||
|
|
||||||
public static void Error (int line, int col, string s) { |
|
||||||
Console.WriteLine(errMsgFormat, line, col, s); |
|
||||||
count++; |
|
||||||
} |
|
||||||
|
|
||||||
public static void Exception (string s) { |
|
||||||
Console.WriteLine(s); |
|
||||||
System.Environment.Exit(1); |
|
||||||
} |
|
||||||
} // Errors |
|
||||||
|
|
||||||
$$$ |
|
||||||
@ -1,432 +0,0 @@ |
|||||||
/*------------------------------------------------------------------------- |
|
||||||
ParserGen.cs -- Generation of the Recursive Descent Parser |
|
||||||
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; |
|
||||||
using System.IO; |
|
||||||
using System.Collections; |
|
||||||
using System.Text; |
|
||||||
|
|
||||||
namespace at.jku.ssw.Coco { |
|
||||||
|
|
||||||
public class ParserGen { |
|
||||||
|
|
||||||
const int maxTerm = 3; // sets of size < maxTerm are enumerated
|
|
||||||
const char CR = '\r'; |
|
||||||
const char LF = '\n'; |
|
||||||
const int EOF = -1; |
|
||||||
|
|
||||||
const int tErr = 0; // error codes
|
|
||||||
const int altErr = 1; |
|
||||||
const int syncErr = 2; |
|
||||||
|
|
||||||
public static Position usingPos; // "using" definitions from the attributed grammar
|
|
||||||
// CHANGES BY M.KRUEGER
|
|
||||||
public static string productionModifiers = String.Empty; |
|
||||||
//EOC
|
|
||||||
|
|
||||||
static int errorNr; // highest parser error number
|
|
||||||
static Symbol curSy; // symbol whose production is currently generated
|
|
||||||
static FileStream fram; // parser frame file
|
|
||||||
static StreamWriter gen; // generated parser source file
|
|
||||||
static StringWriter err; // generated parser error messages
|
|
||||||
static string srcName; // name of attributed grammar file
|
|
||||||
static string srcDir; // directory of attributed grammar file
|
|
||||||
static ArrayList symSet = new ArrayList(); |
|
||||||
|
|
||||||
static void Indent (int n) { |
|
||||||
for (int i = 1; i <= n; i++) gen.Write('\t'); |
|
||||||
} |
|
||||||
|
|
||||||
// AW: use a switch if more than 5 alternatives and none starts with a resolver
|
|
||||||
static bool UseSwitch (Node p) { |
|
||||||
if (p.typ != Node.alt) return false; |
|
||||||
int nAlts = 0; |
|
||||||
while (p != null) { |
|
||||||
++nAlts; |
|
||||||
// must not optimize with switch-statement, if alt uses a resolver expression
|
|
||||||
if (p.sub.typ == Node.rslv) return false; |
|
||||||
p = p.down; |
|
||||||
} |
|
||||||
return nAlts > 5; |
|
||||||
} |
|
||||||
|
|
||||||
static void CopyFramePart (string stop) { |
|
||||||
char startCh = stop[0]; |
|
||||||
int endOfStopString = stop.Length-1; |
|
||||||
int ch = fram.ReadByte(); |
|
||||||
while (ch != EOF) |
|
||||||
if (ch == startCh) { |
|
||||||
int i = 0; |
|
||||||
do { |
|
||||||
if (i == endOfStopString) return; // stop[0..i] found
|
|
||||||
ch = fram.ReadByte(); i++; |
|
||||||
} while (ch == stop[i]); |
|
||||||
// stop[0..i-1] found; continue with last read character
|
|
||||||
gen.Write(stop.Substring(0, i)); |
|
||||||
} else { |
|
||||||
gen.Write((char)ch); ch = fram.ReadByte(); |
|
||||||
} |
|
||||||
Errors.Exception(" -- incomplete or corrupt parser frame file"); |
|
||||||
} |
|
||||||
|
|
||||||
static void CopySourcePart (Position pos, int indent) { |
|
||||||
// Copy text described by pos from atg to gen
|
|
||||||
int ch, nChars, i; |
|
||||||
if (pos != null) { |
|
||||||
Buffer.Pos = pos.beg; ch = Buffer.Read(); nChars = pos.len - 1; |
|
||||||
// CHANGES BY M.KRUEGER (#line pragma generation)
|
|
||||||
gen.WriteLine(); |
|
||||||
gen.WriteLine(String.Format("#line {0} \"{1}\" ", Buffer.CountLines(pos.beg) + 1, Scanner.fileName)); |
|
||||||
// EOC
|
|
||||||
Indent(indent); |
|
||||||
while (nChars >= 0) { |
|
||||||
while (ch == CR || ch == LF) { // eol is either CR or CRLF or LF
|
|
||||||
gen.WriteLine(); Indent(indent); |
|
||||||
if (ch == CR) { ch = Buffer.Read(); nChars--; } // skip CR
|
|
||||||
if (ch == LF) { ch = Buffer.Read(); nChars--; } // skip LF
|
|
||||||
for (i = 1; i <= pos.col && (ch == ' ' || ch == '\t'); i++) { |
|
||||||
// skip blanks at beginning of line
|
|
||||||
ch = Buffer.Read(); nChars--; |
|
||||||
} |
|
||||||
if (i <= pos.col) pos.col = i - 1; // heading TABs => not enough blanks
|
|
||||||
if (nChars < 0) goto done; |
|
||||||
} |
|
||||||
gen.Write((char)ch); |
|
||||||
ch = Buffer.Read(); nChars--; |
|
||||||
} |
|
||||||
done: |
|
||||||
if (indent > 0) gen.WriteLine(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void GenErrorMsg (int errTyp, Symbol sym) { |
|
||||||
errorNr++; |
|
||||||
err.Write("\t\t\tcase " + errorNr + ": s = \""); |
|
||||||
switch (errTyp) { |
|
||||||
case tErr: |
|
||||||
if (sym.name[0] == '"') err.Write(DFA.Escape(sym.name) + " expected"); |
|
||||||
else err.Write(sym.name + " expected"); |
|
||||||
break; |
|
||||||
case altErr: err.Write("invalid " + sym.name); break; |
|
||||||
case syncErr: err.Write("this symbol not expected in " + sym.name); break; |
|
||||||
} |
|
||||||
err.WriteLine("\"; break;"); |
|
||||||
} |
|
||||||
|
|
||||||
static int NewCondSet (BitArray s) { |
|
||||||
for (int i = 1; i < symSet.Count; i++) // skip symSet[0] (reserved for union of SYNC sets)
|
|
||||||
if (Sets.Equals(s, (BitArray)symSet[i])) return i; |
|
||||||
symSet.Add(s.Clone()); |
|
||||||
return symSet.Count - 1; |
|
||||||
} |
|
||||||
|
|
||||||
static void GenCond (BitArray s, Node p) { |
|
||||||
if (p.typ == Node.rslv) CopySourcePart(p.pos, 0); |
|
||||||
else { |
|
||||||
int n = Sets.Elements(s); |
|
||||||
if (n == 0) gen.Write("false"); // should never happen
|
|
||||||
else if (n <= maxTerm) |
|
||||||
foreach (Symbol sym in Symbol.terminals) { |
|
||||||
if (s[sym.n]) { |
|
||||||
gen.Write("la.kind == {0}", sym.n); |
|
||||||
--n; |
|
||||||
if (n > 0) gen.Write(" || "); |
|
||||||
} |
|
||||||
} |
|
||||||
else |
|
||||||
gen.Write("StartOf({0})", NewCondSet(s)); |
|
||||||
/* |
|
||||||
if (p.typ == Node.alt) { |
|
||||||
// for { ... | IF ... | ... } or [ ... | IF ... | ... ]
|
|
||||||
// check resolvers in addition to terminal start symbols of alternatives
|
|
||||||
Node q = p; |
|
||||||
while (q != null) { |
|
||||||
if (q.sub.typ == Node.rslv) { |
|
||||||
gen.Write(" || "); |
|
||||||
CopySourcePart(q.sub.pos, 0); |
|
||||||
} |
|
||||||
q = q.down; |
|
||||||
} |
|
||||||
} |
|
||||||
*/ |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void PutCaseLabels (BitArray s) { |
|
||||||
foreach (Symbol sym in Symbol.terminals) |
|
||||||
if (s[sym.n]) gen.Write("case {0}: ", sym.n); |
|
||||||
} |
|
||||||
|
|
||||||
static void GenCode (Node p, int indent, BitArray isChecked) { |
|
||||||
Node p2; |
|
||||||
BitArray s1, s2; |
|
||||||
while (p != null) { |
|
||||||
switch (p.typ) { |
|
||||||
case Node.nt: { |
|
||||||
Indent(indent); |
|
||||||
gen.Write(p.sym.name + "("); |
|
||||||
CopySourcePart(p.pos, 0); |
|
||||||
gen.WriteLine(");"); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.t: { |
|
||||||
Indent(indent); |
|
||||||
|
|
||||||
// CHANGES BY M.KRUEGER
|
|
||||||
//if (isChecked[p.sym.n]) gen.WriteLine("Get();");
|
|
||||||
if (isChecked[p.sym.n]) gen.WriteLine("lexer.NextToken();"); |
|
||||||
//EOC
|
|
||||||
else gen.WriteLine("Expect({0});", p.sym.n); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.wt: { |
|
||||||
Indent(indent); |
|
||||||
s1 = Tab.Expected(p.next, curSy); |
|
||||||
s1.Or(Tab.allSyncSets); |
|
||||||
gen.WriteLine("ExpectWeak({0}, {1});", p.sym.n, NewCondSet(s1)); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.any: { |
|
||||||
Indent(indent); |
|
||||||
// CHANGES BY M.KRUEGER
|
|
||||||
//gen.WriteLine("Get();");
|
|
||||||
gen.WriteLine("lexer.NextToken();"); |
|
||||||
//EOC
|
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.eps: break; // nothing
|
|
||||||
case Node.rslv: break; // nothing
|
|
||||||
case Node.sem: { |
|
||||||
CopySourcePart(p.pos, indent); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.sync: { |
|
||||||
Indent(indent); |
|
||||||
GenErrorMsg(syncErr, curSy); |
|
||||||
s1 = (BitArray)p.set.Clone(); |
|
||||||
gen.Write("while (!("); GenCond(s1, p); gen.Write(")) {"); |
|
||||||
// CHANGES BY M.KRUEGER
|
|
||||||
//gen.Write("SynErr({0}); Get();", errorNr);
|
|
||||||
gen.Write("SynErr({0}); lexer.NextToken(); ", errorNr); |
|
||||||
//EOC
|
|
||||||
gen.WriteLine("}"); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.alt: { |
|
||||||
s1 = Tab.First(p); |
|
||||||
bool equal = Sets.Equals(s1, isChecked); |
|
||||||
bool useSwitch = UseSwitch(p); |
|
||||||
if (useSwitch) { Indent(indent); gen.WriteLine("switch (la.kind) {"); } |
|
||||||
p2 = p; |
|
||||||
while (p2 != null) { |
|
||||||
s1 = Tab.Expected(p2.sub, curSy); |
|
||||||
Indent(indent); |
|
||||||
if (useSwitch) { |
|
||||||
PutCaseLabels(s1); gen.WriteLine("{"); |
|
||||||
} else if (p2 == p) { |
|
||||||
gen.Write("if ("); GenCond(s1, p2.sub); gen.WriteLine(") {"); |
|
||||||
} else if (p2.down == null && equal) { gen.WriteLine("} else {"); |
|
||||||
} else { |
|
||||||
gen.Write("} else if ("); GenCond(s1, p2.sub); gen.WriteLine(") {"); |
|
||||||
} |
|
||||||
s1.Or(isChecked); |
|
||||||
//if (p2.sub.typ == Node.rslv) GenCode(p2.sub.next, indent + 1, s1);
|
|
||||||
//else GenCode(p2.sub, indent + 1, s1);
|
|
||||||
GenCode(p2.sub, indent + 1, s1); |
|
||||||
if (useSwitch) { |
|
||||||
Indent(indent); gen.WriteLine("\tbreak;"); |
|
||||||
Indent(indent); gen.WriteLine("}"); |
|
||||||
} |
|
||||||
p2 = p2.down; |
|
||||||
} |
|
||||||
Indent(indent); |
|
||||||
if (equal) { |
|
||||||
gen.WriteLine("}"); |
|
||||||
} else { |
|
||||||
GenErrorMsg(altErr, curSy); |
|
||||||
if (useSwitch) { |
|
||||||
gen.WriteLine("default: SynErr({0}); break;", errorNr); |
|
||||||
Indent(indent); gen.WriteLine("}"); |
|
||||||
} else { |
|
||||||
gen.Write("} "); gen.WriteLine("else SynErr({0});", errorNr); |
|
||||||
} |
|
||||||
} |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.iter: { |
|
||||||
Indent(indent); |
|
||||||
p2 = p.sub; |
|
||||||
gen.Write("while ("); |
|
||||||
if (p2.typ == Node.wt) { |
|
||||||
s1 = Tab.Expected(p2.next, curSy); |
|
||||||
s2 = Tab.Expected(p.next, curSy); |
|
||||||
gen.Write("WeakSeparator({0},{1},{2}) ", p2.sym.n, NewCondSet(s1), NewCondSet(s2)); |
|
||||||
s1 = new BitArray(Symbol.terminals.Count); // for inner structure
|
|
||||||
if (p2.up || p2.next == null) p2 = null; else p2 = p2.next; |
|
||||||
} else { |
|
||||||
s1 = Tab.First(p2); |
|
||||||
GenCond(s1, p2); |
|
||||||
} |
|
||||||
gen.WriteLine(") {"); |
|
||||||
GenCode(p2, indent + 1, s1); |
|
||||||
Indent(indent); gen.WriteLine("}"); |
|
||||||
break; |
|
||||||
} |
|
||||||
case Node.opt: |
|
||||||
//if (p.sub.typ == Node.rslv) s1 = Tab.First(p.sub.next);
|
|
||||||
//else s1 = Tab.First(p.sub);
|
|
||||||
s1 = Tab.First(p.sub); |
|
||||||
Indent(indent); |
|
||||||
gen.Write("if ("); GenCond(s1, p.sub); gen.WriteLine(") {"); |
|
||||||
//if (p.sub.typ == Node.rslv) GenCode(p.sub.next, indent + 1, s1);
|
|
||||||
//else GenCode(p.sub, indent + 1, s1);
|
|
||||||
GenCode(p.sub, indent + 1, s1); |
|
||||||
Indent(indent); gen.WriteLine("}"); |
|
||||||
break; |
|
||||||
} |
|
||||||
if (p.typ != Node.eps && p.typ != Node.sem && p.typ != Node.sync) |
|
||||||
isChecked.SetAll(false); // = new BitArray(Symbol.terminals.Count);
|
|
||||||
if (p.up) break; |
|
||||||
p = p.next; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void GenTokens() { |
|
||||||
foreach (Symbol sym in Symbol.terminals) { |
|
||||||
if (Char.IsLetter(sym.name[0])) |
|
||||||
gen.WriteLine("\tconst int _{0} = {1};", sym.name, sym.n); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void GenCodePragmas() { |
|
||||||
foreach (Symbol sym in Symbol.pragmas) { |
|
||||||
gen.WriteLine("\t\t\t\tif (la.kind == {0}) {{", sym.n); |
|
||||||
CopySourcePart(sym.semPos, 4); |
|
||||||
gen.WriteLine("\t\t\t\t}"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void GenProductions() { |
|
||||||
foreach (Symbol sym in Symbol.nonterminals) { |
|
||||||
curSy = sym; |
|
||||||
// CHANGES BY M.KRUEGER
|
|
||||||
gen.Write("\t" + productionModifiers + " void {0}(", sym.name); |
|
||||||
// OLD VERSION: gen.Write("\tstatic void {0}(", sym.name);
|
|
||||||
//EOC
|
|
||||||
CopySourcePart(sym.attrPos, 0); |
|
||||||
gen.WriteLine(") {"); |
|
||||||
CopySourcePart(sym.semPos, 2); |
|
||||||
GenCode(sym.graph, 2, new BitArray(Symbol.terminals.Count)); |
|
||||||
gen.WriteLine("\t}"); gen.WriteLine(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void InitSets() { |
|
||||||
for (int i = 0; i < symSet.Count; i++) { |
|
||||||
BitArray s = (BitArray)symSet[i]; |
|
||||||
gen.Write("\t\t{"); |
|
||||||
int j = 0; |
|
||||||
foreach (Symbol sym in Symbol.terminals) { |
|
||||||
if (s[sym.n]) gen.Write("T,"); else gen.Write("x,"); |
|
||||||
++j; |
|
||||||
if (j%4 == 0) gen.Write(" "); |
|
||||||
} |
|
||||||
if (i == symSet.Count-1) gen.WriteLine("x}"); else gen.WriteLine("x},"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void OpenGen(bool backUp) { /* pdt */ |
|
||||||
try { |
|
||||||
string fn = srcDir + "Parser.cs"; /* pdt */ |
|
||||||
if (File.Exists(fn) && backUp) File.Copy(fn, fn + ".old", true); |
|
||||||
gen = new StreamWriter(new FileStream(fn, FileMode.Create)); /* pdt */ |
|
||||||
} catch (IOException) { |
|
||||||
Errors.Exception("-- Cannot generate parser file"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void WriteParser () { |
|
||||||
symSet.Add(Tab.allSyncSets); |
|
||||||
string fr = srcDir + "Parser.frame"; |
|
||||||
if (!File.Exists(fr)) { |
|
||||||
if (Tab.frameDir != null) fr = Tab.frameDir.Trim() + Path.DirectorySeparatorChar + "Parser.frame"; |
|
||||||
if (!File.Exists(fr)) Errors.Exception("-- Cannot find Parser.frame"); |
|
||||||
} |
|
||||||
try { |
|
||||||
fram = new FileStream(fr, FileMode.Open, FileAccess.Read, FileShare.Read); |
|
||||||
} catch (IOException) { |
|
||||||
Errors.Exception("-- Cannot open Parser.frame."); |
|
||||||
} |
|
||||||
OpenGen(true); /* pdt */ |
|
||||||
err = new StringWriter(); |
|
||||||
foreach (Symbol sym in Symbol.terminals) GenErrorMsg(tErr, sym); |
|
||||||
|
|
||||||
CopyFramePart("-->begin"); |
|
||||||
if (!srcName.ToLower().EndsWith("coco.atg")) { |
|
||||||
gen.Close(); OpenGen(false); /* pdt */ |
|
||||||
} |
|
||||||
if (usingPos != null) {CopySourcePart(usingPos, 0); gen.WriteLine();} |
|
||||||
CopyFramePart("-->namespace"); |
|
||||||
/* AW open namespace, if it exists */ |
|
||||||
if (Tab.nsName != null && Tab.nsName.Length > 0) { |
|
||||||
gen.WriteLine("namespace {0} {{", Tab.nsName); |
|
||||||
gen.WriteLine(); |
|
||||||
} |
|
||||||
CopyFramePart("-->constants"); |
|
||||||
GenTokens(); /* ML 2002/09/07 write the token kinds */ |
|
||||||
gen.WriteLine("\tconst int maxT = {0};", Symbol.terminals.Count-1); |
|
||||||
CopyFramePart("-->declarations"); CopySourcePart(Tab.semDeclPos, 0); |
|
||||||
CopyFramePart("-->pragmas"); GenCodePragmas(); |
|
||||||
CopyFramePart("-->productions"); GenProductions(); |
|
||||||
CopyFramePart("-->parseRoot"); gen.WriteLine("\t\t{0}();", Tab.gramSy.name); |
|
||||||
CopyFramePart("-->initialization"); InitSets(); |
|
||||||
CopyFramePart("-->errors"); gen.Write(err.ToString()); |
|
||||||
CopyFramePart("$$$"); |
|
||||||
/* AW 2002-12-20 close namespace, if it exists */ |
|
||||||
if (Tab.nsName != null && Tab.nsName.Length > 0) gen.Write("}"); |
|
||||||
gen.Close(); |
|
||||||
} |
|
||||||
|
|
||||||
public static void WriteStatistics () { |
|
||||||
Trace.WriteLine(); |
|
||||||
Trace.WriteLine("{0} terminals", Symbol.terminals.Count); |
|
||||||
Trace.WriteLine("{0} symbols", Symbol.terminals.Count + Symbol.pragmas.Count + |
|
||||||
Symbol.nonterminals.Count); |
|
||||||
Trace.WriteLine("{0} nodes", Node.nodes.Count); |
|
||||||
Trace.WriteLine("{0} sets", symSet.Count); |
|
||||||
} |
|
||||||
|
|
||||||
public static void Init (string file, string dir) { |
|
||||||
srcName = file; |
|
||||||
srcDir = dir; |
|
||||||
errorNr = -1; |
|
||||||
usingPos = null; |
|
||||||
} |
|
||||||
|
|
||||||
} // end ParserGen
|
|
||||||
|
|
||||||
} // end namespace
|
|
||||||
@ -1,358 +0,0 @@ |
|||||||
/*---------------------------------------------------------------------- |
|
||||||
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; |
|
||||||
using System.IO; |
|
||||||
using System.Collections; |
|
||||||
using System.Text; |
|
||||||
|
|
||||||
namespace at.jku.ssw.Coco { |
|
||||||
|
|
||||||
public class Token { |
|
||||||
public int kind; // token kind
|
|
||||||
public int pos; // token position in the source text (starting at 0)
|
|
||||||
public int col; // token column (starting at 0)
|
|
||||||
public int line; // token line (starting at 1)
|
|
||||||
public string val; // token value
|
|
||||||
public Token next; // AW 2003-03-07 Tokens are kept in linked list
|
|
||||||
} |
|
||||||
|
|
||||||
public class Buffer { |
|
||||||
public const char EOF = (char)256; |
|
||||||
static byte[] buf; |
|
||||||
static int bufLen; |
|
||||||
static int pos; |
|
||||||
|
|
||||||
// CHANGES by M.KRUEGER
|
|
||||||
public static int CountLines(int offset) |
|
||||||
{ |
|
||||||
int line = 0; |
|
||||||
for (int i = 0; i <= offset; ++i) { |
|
||||||
if (buf[i] == '\n') { |
|
||||||
++line; |
|
||||||
} |
|
||||||
} |
|
||||||
return line; |
|
||||||
} |
|
||||||
//EOC
|
|
||||||
|
|
||||||
public static void Fill (Stream s) { |
|
||||||
bufLen = (int) s.Length; |
|
||||||
buf = new byte[bufLen]; |
|
||||||
s.Read(buf, 0, bufLen); |
|
||||||
pos = 0; |
|
||||||
} |
|
||||||
|
|
||||||
public static int Read () { |
|
||||||
if (pos < bufLen) return buf[pos++]; |
|
||||||
else return EOF; /* pdt */ |
|
||||||
} |
|
||||||
|
|
||||||
public static int Peek () { |
|
||||||
if (pos < bufLen) return buf[pos]; |
|
||||||
else return EOF; /* pdt */ |
|
||||||
} |
|
||||||
|
|
||||||
/* AW 2003-03-10 moved this from ParserGen.cs */ |
|
||||||
public static string GetString (int beg, int end) { |
|
||||||
StringBuilder s = new StringBuilder(64); |
|
||||||
int oldPos = Buffer.Pos; |
|
||||||
Buffer.Pos = beg; |
|
||||||
while (beg < end) { s.Append((char)Buffer.Read()); beg++; } |
|
||||||
Buffer.Pos = oldPos; |
|
||||||
return s.ToString(); |
|
||||||
} |
|
||||||
|
|
||||||
public static int Pos { |
|
||||||
get { return pos; } |
|
||||||
set { |
|
||||||
if (value < 0) pos = 0; |
|
||||||
else if (value >= bufLen) pos = bufLen; |
|
||||||
else pos = value; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public class Scanner { |
|
||||||
const char EOL = '\n'; |
|
||||||
const int eofSym = 0; /* pdt */ |
|
||||||
const int charSetSize = 256; |
|
||||||
const int maxT = 41; |
|
||||||
const int noSym = 41; |
|
||||||
static short[] start = { |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 11, 0, 10, 0, 0, 5, 29, 20, 0, 14, 0, 15, 28, 0, |
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 27, 17, 13, 18, 0, |
|
||||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 0, 22, 0, 0, |
|
||||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 19, 24, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
-1}; |
|
||||||
|
|
||||||
|
|
||||||
static Token t; // current token
|
|
||||||
static char ch; // current input character
|
|
||||||
static int pos; // column number of current character
|
|
||||||
static int line; // line number of current character
|
|
||||||
static int lineStart; // start position of current line
|
|
||||||
static int oldEols; // EOLs that appeared in a comment;
|
|
||||||
static BitArray ignore; // set of characters to be ignored by the scanner
|
|
||||||
|
|
||||||
static Token tokens; // the complete input token stream
|
|
||||||
static Token pt; // current peek token
|
|
||||||
|
|
||||||
// CHANGES by M.KRUEGER
|
|
||||||
public static string fileName; |
|
||||||
// EOC
|
|
||||||
|
|
||||||
public static void Init (string fileName) { |
|
||||||
// CHANGES by M.KRUEGER
|
|
||||||
Scanner.fileName = fileName; |
|
||||||
// EOC
|
|
||||||
|
|
||||||
FileStream s = null; |
|
||||||
try { |
|
||||||
s = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); |
|
||||||
Init(s); |
|
||||||
} catch (IOException) { |
|
||||||
Console.WriteLine("--- Cannot open file {0}", fileName); |
|
||||||
System.Environment.Exit(1); |
|
||||||
} finally { |
|
||||||
if (s != null) s.Close(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void Init (Stream s) { |
|
||||||
Buffer.Fill(s); |
|
||||||
pos = -1; line = 1; lineStart = 0; |
|
||||||
oldEols = 0; |
|
||||||
NextCh(); |
|
||||||
ignore = new BitArray(charSetSize+1); |
|
||||||
ignore[9] = true; ignore[10] = true; ignore[13] = true; ignore[32] = true; |
|
||||||
|
|
||||||
//--- AW: fill token list
|
|
||||||
tokens = new Token(); // first token is a dummy
|
|
||||||
Token node = tokens; |
|
||||||
do { |
|
||||||
node.next = NextToken(); |
|
||||||
node = node.next; |
|
||||||
} while (node.kind != eofSym); |
|
||||||
node.next = node; |
|
||||||
node.val = "EOF"; |
|
||||||
t = pt = tokens; |
|
||||||
} |
|
||||||
|
|
||||||
static void NextCh() { |
|
||||||
if (oldEols > 0) { ch = EOL; oldEols--; } |
|
||||||
else { |
|
||||||
ch = (char)Buffer.Read(); pos++; |
|
||||||
// replace isolated '\r' by '\n' in order to make
|
|
||||||
// eol handling uniform across Windows, Unix and Mac
|
|
||||||
if (ch == '\r' && Buffer.Peek() != '\n') ch = EOL; |
|
||||||
if (ch == EOL) { line++; lineStart = pos + 1; } |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
static bool Comment0() { |
|
||||||
int level = 1, line0 = line, lineStart0 = lineStart; |
|
||||||
NextCh(); |
|
||||||
if (ch == '*') { |
|
||||||
NextCh(); |
|
||||||
for(;;) { |
|
||||||
if (ch == '*') { |
|
||||||
NextCh(); |
|
||||||
if (ch == '/') { |
|
||||||
level--; |
|
||||||
if (level == 0) { oldEols = line - line0; NextCh(); return true; } |
|
||||||
NextCh(); |
|
||||||
} |
|
||||||
} else if (ch == '/') { |
|
||||||
NextCh(); |
|
||||||
if (ch == '*') { |
|
||||||
level++; NextCh(); |
|
||||||
} |
|
||||||
} else if (ch == Buffer.EOF) return false; |
|
||||||
else NextCh(); |
|
||||||
} |
|
||||||
} else { |
|
||||||
if (ch==EOL) {line--; lineStart = lineStart0;} |
|
||||||
pos = pos - 2; Buffer.Pos = pos+1; NextCh(); |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
static void CheckLiteral() { |
|
||||||
switch (t.val) { |
|
||||||
case "COMPILER": t.kind = 6; break; |
|
||||||
case "IGNORECASE": t.kind = 7; break; |
|
||||||
case "CHARACTERS": t.kind = 8; break; |
|
||||||
case "TOKENS": t.kind = 9; break; |
|
||||||
case "PRAGMAS": t.kind = 10; break; |
|
||||||
case "COMMENTS": t.kind = 11; break; |
|
||||||
case "FROM": t.kind = 12; break; |
|
||||||
case "TO": t.kind = 13; break; |
|
||||||
case "NESTED": t.kind = 14; break; |
|
||||||
case "IGNORE": t.kind = 15; break; |
|
||||||
case "PRODUCTIONS": t.kind = 16; break; |
|
||||||
case "END": t.kind = 19; break; |
|
||||||
case "ANY": t.kind = 23; break; |
|
||||||
case "WEAK": t.kind = 27; break; |
|
||||||
case "SYNC": t.kind = 34; break; |
|
||||||
case "IF": t.kind = 35; break; |
|
||||||
case "CONTEXT": t.kind = 36; break; |
|
||||||
case "using": t.kind = 39; break; |
|
||||||
default: break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* AW Scan() renamed to NextToken() */ |
|
||||||
static Token NextToken() { |
|
||||||
while (ignore[ch]) NextCh(); |
|
||||||
if (ch == '/' && Comment0()) return NextToken(); |
|
||||||
t = new Token(); |
|
||||||
t.pos = pos; t.col = pos - lineStart + 1; t.line = line; |
|
||||||
int state = start[ch]; |
|
||||||
StringBuilder buf = new StringBuilder(16); |
|
||||||
buf.Append(ch); NextCh(); |
|
||||||
|
|
||||||
switch (state) { |
|
||||||
case -1: { t.kind = eofSym; goto done; } // NextCh already done /* pdt */
|
|
||||||
case 0: { t.kind = noSym; goto done; } // NextCh already done
|
|
||||||
case 1: |
|
||||||
if ((ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z')) {buf.Append(ch); NextCh(); goto case 1;} |
|
||||||
else {t.kind = 1; t.val = buf.ToString(); CheckLiteral(); return t;} |
|
||||||
case 2: |
|
||||||
if ((ch >= '0' && ch <= '9')) {buf.Append(ch); NextCh(); goto case 2;} |
|
||||||
else {t.kind = 2; goto done;} |
|
||||||
case 3: |
|
||||||
{t.kind = 3; goto done;} |
|
||||||
case 4: |
|
||||||
{t.kind = 4; goto done;} |
|
||||||
case 5: |
|
||||||
if ((ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '&' || ch >= '(' && ch <= '[' || ch >= ']')) {buf.Append(ch); NextCh(); goto case 6;} |
|
||||||
else if (ch == 92) {buf.Append(ch); NextCh(); goto case 7;} |
|
||||||
else {t.kind = noSym; goto done;} |
|
||||||
case 6: |
|
||||||
if (ch == 39) {buf.Append(ch); NextCh(); goto case 9;} |
|
||||||
else {t.kind = noSym; goto done;} |
|
||||||
case 7: |
|
||||||
if ((ch >= ' ' && ch <= '~')) {buf.Append(ch); NextCh(); goto case 8;} |
|
||||||
else {t.kind = noSym; goto done;} |
|
||||||
case 8: |
|
||||||
if ((ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'f')) {buf.Append(ch); NextCh(); goto case 8;} |
|
||||||
else if (ch == 39) {buf.Append(ch); NextCh(); goto case 9;} |
|
||||||
else {t.kind = noSym; goto done;} |
|
||||||
case 9: |
|
||||||
{t.kind = 5; goto done;} |
|
||||||
case 10: |
|
||||||
if ((ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z')) {buf.Append(ch); NextCh(); goto case 10;} |
|
||||||
else {t.kind = 42; goto done;} |
|
||||||
case 11: |
|
||||||
if ((ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']')) {buf.Append(ch); NextCh(); goto case 11;} |
|
||||||
else if ((ch == 10 || ch == 13)) {buf.Append(ch); NextCh(); goto case 4;} |
|
||||||
else if (ch == '"') {buf.Append(ch); NextCh(); goto case 3;} |
|
||||||
else if (ch == 92) {buf.Append(ch); NextCh(); goto case 12;} |
|
||||||
else {t.kind = noSym; goto done;} |
|
||||||
case 12: |
|
||||||
if ((ch >= ' ' && ch <= '~')) {buf.Append(ch); NextCh(); goto case 11;} |
|
||||||
else {t.kind = noSym; goto done;} |
|
||||||
case 13: |
|
||||||
{t.kind = 17; goto done;} |
|
||||||
case 14: |
|
||||||
{t.kind = 20; goto done;} |
|
||||||
case 15: |
|
||||||
{t.kind = 21; goto done;} |
|
||||||
case 16: |
|
||||||
{t.kind = 22; goto done;} |
|
||||||
case 17: |
|
||||||
{t.kind = 24; goto done;} |
|
||||||
case 18: |
|
||||||
{t.kind = 25; goto done;} |
|
||||||
case 19: |
|
||||||
{t.kind = 26; goto done;} |
|
||||||
case 20: |
|
||||||
{t.kind = 29; goto done;} |
|
||||||
case 21: |
|
||||||
{t.kind = 30; goto done;} |
|
||||||
case 22: |
|
||||||
{t.kind = 31; goto done;} |
|
||||||
case 23: |
|
||||||
{t.kind = 32; goto done;} |
|
||||||
case 24: |
|
||||||
{t.kind = 33; goto done;} |
|
||||||
case 25: |
|
||||||
{t.kind = 37; goto done;} |
|
||||||
case 26: |
|
||||||
{t.kind = 38; goto done;} |
|
||||||
case 27: |
|
||||||
{t.kind = 40; goto done;} |
|
||||||
case 28: |
|
||||||
if (ch == '.') {buf.Append(ch); NextCh(); goto case 16;} |
|
||||||
else if (ch == ')') {buf.Append(ch); NextCh(); goto case 26;} |
|
||||||
else {t.kind = 18; goto done;} |
|
||||||
case 29: |
|
||||||
if (ch == '.') {buf.Append(ch); NextCh(); goto case 25;} |
|
||||||
else {t.kind = 28; goto done;} |
|
||||||
|
|
||||||
} |
|
||||||
done: |
|
||||||
t.val = buf.ToString(); |
|
||||||
return t; |
|
||||||
} |
|
||||||
|
|
||||||
/* AW 2003-03-07 get the next token, move on and synch peek token with current */ |
|
||||||
public static Token Scan () { |
|
||||||
t = pt = t.next; |
|
||||||
return t; |
|
||||||
} |
|
||||||
|
|
||||||
/* AW 2003-03-07 get the next token, ignore pragmas */ |
|
||||||
public static Token Peek () { |
|
||||||
do { // skip pragmas while peeking
|
|
||||||
pt = pt.next; |
|
||||||
} while (pt.kind > maxT); |
|
||||||
return pt; |
|
||||||
} |
|
||||||
|
|
||||||
/* AW 2003-03-11 to make sure peek start at current scan position */ |
|
||||||
public static void ResetPeek () { pt = t; } |
|
||||||
|
|
||||||
} // end Scanner
|
|
||||||
|
|
||||||
} |
|
||||||
@ -1,202 +0,0 @@ |
|||||||
/*---------------------------------------------------------------------- |
|
||||||
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. |
|
||||||
-----------------------------------------------------------------------*/ |
|
||||||
-->begin |
|
||||||
using System; |
|
||||||
using System.IO; |
|
||||||
using System.Collections; |
|
||||||
using System.Text; |
|
||||||
|
|
||||||
-->namespace |
|
||||||
|
|
||||||
public class Token { |
|
||||||
public int kind; // token kind |
|
||||||
public int pos; // token position in the source text (starting at 0) |
|
||||||
public int col; // token column (starting at 0) |
|
||||||
public int line; // token line (starting at 1) |
|
||||||
public string val; // token value |
|
||||||
public Token next; // AW 2003-03-07 Tokens are kept in linked list |
|
||||||
} |
|
||||||
|
|
||||||
public class Buffer { |
|
||||||
public const char EOF = (char)256; |
|
||||||
static byte[] buf; |
|
||||||
static int bufLen; |
|
||||||
static int pos; |
|
||||||
// CHANGES by M.KRUEGER |
|
||||||
public static int CountLines(int offset) |
|
||||||
{ |
|
||||||
int line = 0; |
|
||||||
for (int i = 0; i <= offset; ++i) { |
|
||||||
if (buf[i] == '\n') { |
|
||||||
++line; |
|
||||||
} |
|
||||||
} |
|
||||||
return line; |
|
||||||
} |
|
||||||
//EOC |
|
||||||
public static void Fill (Stream s) { |
|
||||||
bufLen = (int) s.Length; |
|
||||||
buf = new byte[bufLen]; |
|
||||||
s.Read(buf, 0, bufLen); |
|
||||||
pos = 0; |
|
||||||
} |
|
||||||
|
|
||||||
public static int Read () { |
|
||||||
if (pos < bufLen) return buf[pos++]; |
|
||||||
else return EOF; /* pdt */ |
|
||||||
} |
|
||||||
|
|
||||||
public static int Peek () { |
|
||||||
if (pos < bufLen) return buf[pos]; |
|
||||||
else return EOF; /* pdt */ |
|
||||||
} |
|
||||||
|
|
||||||
/* AW 2003-03-10 moved this from ParserGen.cs */ |
|
||||||
public static string GetString (int beg, int end) { |
|
||||||
StringBuilder s = new StringBuilder(64); |
|
||||||
int oldPos = Buffer.Pos; |
|
||||||
Buffer.Pos = beg; |
|
||||||
while (beg < end) { s.Append((char)Buffer.Read()); beg++; } |
|
||||||
Buffer.Pos = oldPos; |
|
||||||
return s.ToString(); |
|
||||||
} |
|
||||||
|
|
||||||
public static int Pos { |
|
||||||
get { return pos; } |
|
||||||
set { |
|
||||||
if (value < 0) pos = 0; |
|
||||||
else if (value >= bufLen) pos = bufLen; |
|
||||||
else pos = value; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public class Scanner { |
|
||||||
const char EOL = '\n'; |
|
||||||
const int eofSym = 0; /* pdt */ |
|
||||||
-->declarations |
|
||||||
|
|
||||||
static Token t; // current token |
|
||||||
static char ch; // current input character |
|
||||||
static int pos; // column number of current character |
|
||||||
static int line; // line number of current character |
|
||||||
static int lineStart; // start position of current line |
|
||||||
static int oldEols; // EOLs that appeared in a comment; |
|
||||||
static BitArray ignore; // set of characters to be ignored by the scanner |
|
||||||
|
|
||||||
static Token tokens; // the complete input token stream |
|
||||||
static Token pt; // current peek token |
|
||||||
|
|
||||||
public static void Init (string fileName) { |
|
||||||
FileStream s = null; |
|
||||||
try { |
|
||||||
s = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); |
|
||||||
Init(s); |
|
||||||
} catch (IOException) { |
|
||||||
Console.WriteLine("--- Cannot open file {0}", fileName); |
|
||||||
System.Environment.Exit(1); |
|
||||||
} finally { |
|
||||||
if (s != null) s.Close(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void Init (Stream s) { |
|
||||||
Buffer.Fill(s); |
|
||||||
pos = -1; line = 1; lineStart = 0; |
|
||||||
oldEols = 0; |
|
||||||
NextCh(); |
|
||||||
-->initialization |
|
||||||
//--- AW: fill token list |
|
||||||
tokens = new Token(); // first token is a dummy |
|
||||||
Token node = tokens; |
|
||||||
do { |
|
||||||
node.next = NextToken(); |
|
||||||
node = node.next; |
|
||||||
} while (node.kind != eofSym); |
|
||||||
node.next = node; |
|
||||||
node.val = "EOF"; |
|
||||||
t = pt = tokens; |
|
||||||
} |
|
||||||
|
|
||||||
static void NextCh() { |
|
||||||
if (oldEols > 0) { ch = EOL; oldEols--; } |
|
||||||
else { |
|
||||||
ch = (char)Buffer.Read(); pos++; |
|
||||||
// replace isolated '\r' by '\n' in order to make |
|
||||||
// eol handling uniform across Windows, Unix and Mac |
|
||||||
if (ch == '\r' && Buffer.Peek() != '\n') ch = EOL; |
|
||||||
if (ch == EOL) { line++; lineStart = pos + 1; } |
|
||||||
} |
|
||||||
-->casing |
|
||||||
} |
|
||||||
|
|
||||||
-->comments |
|
||||||
|
|
||||||
static void CheckLiteral() { |
|
||||||
-->literals |
|
||||||
} |
|
||||||
|
|
||||||
/* AW Scan() renamed to NextToken() */ |
|
||||||
static Token NextToken() { |
|
||||||
while (ignore[ch]) NextCh(); |
|
||||||
-->scan1 |
|
||||||
t = new Token(); |
|
||||||
t.pos = pos; t.col = pos - lineStart + 1; t.line = line; |
|
||||||
int state = start[ch]; |
|
||||||
StringBuilder buf = new StringBuilder(16); |
|
||||||
-->scan2 |
|
||||||
|
|
||||||
switch (state) { |
|
||||||
case -1: { t.kind = eofSym; goto done; } // NextCh already done /* pdt */ |
|
||||||
case 0: { t.kind = noSym; goto done; } // NextCh already done |
|
||||||
-->scan3 |
|
||||||
} |
|
||||||
done: |
|
||||||
t.val = buf.ToString(); |
|
||||||
return t; |
|
||||||
} |
|
||||||
|
|
||||||
/* AW 2003-03-07 get the next token, move on and synch peek token with current */ |
|
||||||
public static Token Scan () { |
|
||||||
t = pt = t.next; |
|
||||||
return t; |
|
||||||
} |
|
||||||
|
|
||||||
/* AW 2003-03-07 get the next token, ignore pragmas */ |
|
||||||
public static Token Peek () { |
|
||||||
do { // skip pragmas while peeking |
|
||||||
pt = pt.next; |
|
||||||
} while (pt.kind > maxT); |
|
||||||
return pt; |
|
||||||
} |
|
||||||
|
|
||||||
/* AW 2003-03-11 to make sure peek start at current scan position */ |
|
||||||
public static void ResetPeek () { pt = t; } |
|
||||||
|
|
||||||
} // end Scanner |
|
||||||
|
|
||||||
$$$ |
|
||||||
@ -1,53 +0,0 @@ |
|||||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|
||||||
<PropertyGroup> |
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|
||||||
<ProductVersion>8.0.40607</ProductVersion> |
|
||||||
<SchemaVersion>2.0</SchemaVersion> |
|
||||||
<ProjectGuid>{b87ee2f4-80bd-476a-8d49-a0bb415b6021}</ProjectGuid> |
|
||||||
<RootNamespace>NewProject</RootNamespace> |
|
||||||
<AssemblyName>SharpCoco</AssemblyName> |
|
||||||
<OutputTarget>Exe</OutputTarget> |
|
||||||
<WarningLevel>4</WarningLevel> |
|
||||||
<NoStdLib>False</NoStdLib> |
|
||||||
<NoConfig>False</NoConfig> |
|
||||||
<RunPostBuildEvent>OnSuccessfulBuild</RunPostBuildEvent> |
|
||||||
</PropertyGroup> |
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|
||||||
<DebugSymbols>True</DebugSymbols> |
|
||||||
<Optimize>True</Optimize> |
|
||||||
<AllowUnsafeBlocks>False</AllowUnsafeBlocks> |
|
||||||
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow> |
|
||||||
<OutputPath>..\bin\Debug\</OutputPath> |
|
||||||
<TreatWarningsAsErrors>False</TreatWarningsAsErrors> |
|
||||||
</PropertyGroup> |
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|
||||||
<DebugSymbols>True</DebugSymbols> |
|
||||||
<Optimize>True</Optimize> |
|
||||||
<AllowUnsafeBlocks>False</AllowUnsafeBlocks> |
|
||||||
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow> |
|
||||||
<OutputPath>..\bin\Release\</OutputPath> |
|
||||||
<TreatWarningsAsErrors>False</TreatWarningsAsErrors> |
|
||||||
</PropertyGroup> |
|
||||||
<ItemGroup> |
|
||||||
<Reference Include="System" /> |
|
||||||
<Reference Include="System.Data" /> |
|
||||||
<Reference Include="System.Drawing" /> |
|
||||||
<Reference Include="System.Windows.Forms" /> |
|
||||||
<Reference Include="System.Xml" /> |
|
||||||
</ItemGroup> |
|
||||||
<ItemGroup> |
|
||||||
<Compile Include="Coco.cs" /> |
|
||||||
<Compile Include="AssemblyInfo.cs" /> |
|
||||||
<Compile Include="DFA.cs" /> |
|
||||||
<Compile Include="Parser.cs" /> |
|
||||||
<Compile Include="Scanner.cs" /> |
|
||||||
<Compile Include="Tab.cs" /> |
|
||||||
<Compile Include="Trace.cs" /> |
|
||||||
<Compile Include="ParserGen.cs" /> |
|
||||||
<None Include="Parser.frame" /> |
|
||||||
<None Include="Scanner.frame" /> |
|
||||||
<None Include="Coco.atg" /> |
|
||||||
</ItemGroup> |
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> |
|
||||||
</Project> |
|
||||||
@ -1,6 +0,0 @@ |
|||||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|
||||||
<StartArguments>CS.ATG</StartArguments> |
|
||||||
</PropertyGroup> |
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " /> |
|
||||||
</Project> |
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,69 +0,0 @@ |
|||||||
/*------------------------------------------------------------------------- |
|
||||||
Trace.cs -- Trace Output Class |
|
||||||
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; |
|
||||||
using System.IO; |
|
||||||
|
|
||||||
namespace at.jku.ssw.Coco { |
|
||||||
|
|
||||||
class Trace { |
|
||||||
static string fileName; /* pdt */ |
|
||||||
static StreamWriter trace; |
|
||||||
|
|
||||||
public static void Init (String dir) { |
|
||||||
fileName = dir + "trace.txt"; /* pdt */ |
|
||||||
try { |
|
||||||
trace = new StreamWriter(new FileStream(fileName, FileMode.Create)); |
|
||||||
} catch (IOException) { |
|
||||||
Errors.Exception("-- could not open " + fileName); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void Write (string s) { trace.Write(s); } |
|
||||||
|
|
||||||
public static void Write (string s, params object[] args) { |
|
||||||
trace.Write(s, args); |
|
||||||
} |
|
||||||
|
|
||||||
public static void WriteLine (string s) { trace.WriteLine(s); } |
|
||||||
|
|
||||||
public static void WriteLine (string s, params object[] args) { |
|
||||||
trace.WriteLine(s, args); |
|
||||||
} |
|
||||||
|
|
||||||
public static void WriteLine () { trace.WriteLine(); } |
|
||||||
|
|
||||||
public static void Close () { /* pdt */ |
|
||||||
trace.Close(); |
|
||||||
FileInfo f = new FileInfo(fileName); |
|
||||||
if (f.Length == 0) f.Delete(); |
|
||||||
else Console.WriteLine("trace output is in " + fileName); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
Loading…
Reference in new issue