Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1980 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
16 changed files with 4847 additions and 0 deletions
Binary file not shown.
@ -0,0 +1,16 @@ |
|||||||
|
Microsoft Visual Studio Solution File, Format Version 9.00 |
||||||
|
# SharpDevelop 2.1.0.1913 |
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCoco", "src\SharpCoco.csproj", "{47D8A4A2-BBD9-4E24-85DC-A287383F7C42}" |
||||||
|
EndProject |
||||||
|
Global |
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
||||||
|
Debug|Any CPU = Debug|Any CPU |
||||||
|
Release|Any CPU = Release|Any CPU |
||||||
|
EndGlobalSection |
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
||||||
|
{47D8A4A2-BBD9-4E24-85DC-A287383F7C42}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||||
|
{47D8A4A2-BBD9-4E24-85DC-A287383F7C42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||||
|
{47D8A4A2-BBD9-4E24-85DC-A287383F7C42}.Release|Any CPU.Build.0 = Release|Any CPU |
||||||
|
{47D8A4A2-BBD9-4E24-85DC-A287383F7C42}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||||
|
EndGlobalSection |
||||||
|
EndGlobal |
||||||
@ -0,0 +1,14 @@ |
|||||||
|
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 |
||||||
@ -0,0 +1,32 @@ |
|||||||
|
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("1.0.*")] |
||||||
|
|
||||||
|
// 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("")] |
||||||
@ -0,0 +1,432 @@ |
|||||||
|
/* ------------------------------------------------------------------------ |
||||||
|
* Coco.ATG |
||||||
|
* Attributed grammer of Coco/R |
||||||
|
* by H. Moessenboeck, Univ. of Linz |
||||||
|
* extended by |
||||||
|
* M. Loeberbauer & A. Woess, Univ. of Linz |
||||||
|
* ------------------------------------------------------------------------*/ |
||||||
|
|
||||||
|
using System.Collections; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
COMPILER Coco |
||||||
|
|
||||||
|
const int id = 0; |
||||||
|
const int str = 1; |
||||||
|
|
||||||
|
static bool genScanner; |
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/ |
||||||
|
|
||||||
|
CHARACTERS |
||||||
|
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz". |
||||||
|
digit = "0123456789". |
||||||
|
cr = '\r'. |
||||||
|
lf = '\n'. |
||||||
|
tab = '\t'. |
||||||
|
stringCh = ANY - '"' - '\\' - cr - lf. |
||||||
|
charCh = ANY - '\'' - '\\' - cr - lf. |
||||||
|
printable = '\u0020' .. '\u007e'. |
||||||
|
hex = "0123456789abcdef". |
||||||
|
|
||||||
|
IGNORE cr + lf + tab |
||||||
|
|
||||||
|
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 |
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/ |
||||||
|
|
||||||
|
PRODUCTIONS |
||||||
|
|
||||||
|
Coco (. Symbol sym; Graph g; string gramName; .) |
||||||
|
= |
||||||
|
[ UsingDecl<out ParserGen.usingPos> ] |
||||||
|
|
||||||
|
"COMPILER" (. int gramLine = t.line; |
||||||
|
genScanner = true; |
||||||
|
bool ok = true; |
||||||
|
Tab.ignored = null; |
||||||
|
.) |
||||||
|
ident (. gramName = t.val; |
||||||
|
int beg = la.pos; |
||||||
|
.) |
||||||
|
{ ANY } (. Tab.semDeclPos = new Position(beg, la.pos-beg, 0); .) |
||||||
|
{ Declaration } |
||||||
|
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(); |
||||||
|
ok = ok && Tab.GrammarOk(); |
||||||
|
if (Tab.ddt[7]) Tab.XRef(); |
||||||
|
if (ok) { |
||||||
|
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(); |
||||||
|
.) |
||||||
|
'.' |
||||||
|
. |
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------------*/ |
||||||
|
|
||||||
|
Declaration (. Graph g1, g2; bool nested = false; .) |
||||||
|
= |
||||||
|
"CHARACTERS" { SetDecl } |
||||||
|
| "TOKENS" { TokenDecl<Node.t> } |
||||||
|
| "PRAGMAS" { TokenDecl<Node.pr> } |
||||||
|
| "COMMENTS" |
||||||
|
"FROM" TokenExpr<out g1> |
||||||
|
"TO" TokenExpr<out g2> |
||||||
|
( "NESTED" (. nested = true; .) |
||||||
|
| (. nested = false; .) |
||||||
|
) (. new Comment(g1.l, g2.l, nested); .) |
||||||
|
| "IGNORE" Set<out Tab.ignored> (. Tab.ignored[' '] = true; /* ' ' is always ignored */ |
||||||
|
if (Tab.ignored[0]) SemErr("may not ignore \'\\0\'"); .) |
||||||
|
| "TOKENNAMES" (. Symbol.tokenNames = new Hashtable(); .) |
||||||
|
{ ( string | ident ) (. string key = t.val; .) |
||||||
|
"=" ident (. string val = t.val; Symbol.tokenNames.Add(key, val); .) |
||||||
|
} |
||||||
|
. |
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------------*/ |
||||||
|
|
||||||
|
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) 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); |
||||||
|
s[0] = false; |
||||||
|
.) |
||||||
|
) |
||||||
|
. |
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------*/ |
||||||
|
|
||||||
|
Char<out int n> |
||||||
|
= |
||||||
|
char (. string name = t.val; |
||||||
|
name = DFA.Unescape(name.Substring(1, name.Length-2)); |
||||||
|
int max = CharClass.charSetSize; |
||||||
|
if (name.Length != 1 || name[0] > max-1) SemErr("unacceptable character value"); |
||||||
|
n = name[0] % max; |
||||||
|
.) |
||||||
|
. |
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------------*/ |
||||||
|
|
||||||
|
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.classToken; |
||||||
|
} |
||||||
|
.) |
||||||
|
SYNC |
||||||
|
( '=' TokenExpr<out g> '.' (. if (kind != id) SemErr("a literal must not be declared with a structure"); |
||||||
|
Graph.Finish(g); |
||||||
|
DFA.ConvertToStates(g.l, sym); |
||||||
|
.) |
||||||
|
| '.' (. if (typ != Node.rslv) SemErr("resolver is only allowed in RESOLVERS section"); .) /* ML-AW */ |
||||||
|
| (. if (kind == id) genScanner = false; |
||||||
|
else DFA.MatchLiteral(sym); |
||||||
|
.) |
||||||
|
) |
||||||
|
( SemText<out sym.semPos> (. if (typ == Node.t) SemErr("semantic action not allowed here"); .) |
||||||
|
| (. if (typ == Node.rslv) SemErr("resolvers must have a semantic action"); .) /* ML-AW */ |
||||||
|
) |
||||||
|
. |
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------------*/ |
||||||
|
|
||||||
|
AttrDecl<Symbol sym> |
||||||
|
= |
||||||
|
'<' (. int beg = la.pos; int col = la.col; .) |
||||||
|
{ ANY |
||||||
|
| badString (. SemErr("bad string in semantic action"); .) |
||||||
|
} |
||||||
|
'>' (. 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; Position pos; Node rslv = null; |
||||||
|
g = null; |
||||||
|
.) |
||||||
|
= [ (. rslv = new Node(Node.rslv, null, la.line); .) |
||||||
|
ResolveExpr<out pos> (. rslv.pos = 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)); .) |
||||||
|
. |
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------------*/ |
||||||
|
|
||||||
|
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); |
||||||
|
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); |
||||||
|
} 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 && typ != Node.rslv) /* ML */ |
||||||
|
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); |
||||||
|
.) |
||||||
|
. |
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------------*/ |
||||||
|
|
||||||
|
ResolveExpr<out Position pos> |
||||||
|
= |
||||||
|
"IF" "(" (. int beg = la.pos; int col = la.col; .) |
||||||
|
( ("=" | "!=") CondPart /* indicate the beginning of a syntax snippet. |
||||||
|
The condition is true if the actual input matches |
||||||
|
the given syntax snippet (or does not match for "!=") |
||||||
|
*/ |
||||||
|
| "(" CondPart ")" |
||||||
|
| ANY CondPart |
||||||
|
) (. pos = new Position(beg, t.pos - beg, col); .) |
||||||
|
. |
||||||
|
|
||||||
|
/* ConPart exists to guarantee an equal number of opening and * |
||||||
|
* closing parentheses inside the conditional expression. */ |
||||||
|
CondPart = { "(" CondPart | 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 = new Graph(); .) |
||||||
|
( 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); |
||||||
|
} else g = Graph.StrToGraph(name); // str |
||||||
|
.) |
||||||
|
| '(' TokenExpr<out g> ')' |
||||||
|
| '[' TokenExpr<out g> ']' (. Graph.MakeOption(g); .) |
||||||
|
| '{' TokenExpr<out g> '}' (. Graph.MakeIteration(g); .) |
||||||
|
) |
||||||
|
. |
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------------*/ |
||||||
|
|
||||||
|
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; .) |
||||||
|
) |
||||||
|
. |
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------------*/ |
||||||
|
|
||||||
|
Attribs<Node p> |
||||||
|
= |
||||||
|
'<' (. int beg = la.pos; int col = la.col; .) |
||||||
|
{ ANY |
||||||
|
| badString (. SemErr("bad string in attributes"); .) |
||||||
|
} |
||||||
|
'>' (. 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. |
||||||
@ -0,0 +1,71 @@ |
|||||||
|
/*------------------------------------------------------------------------- |
||||||
|
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 (Aug 4, 2003)"); |
||||||
|
string ATGName = null; |
||||||
|
for (int i = 0; i < arg.Length; i++) { |
||||||
|
if (arg[i] == "-nonamespace") Tab.nsName = null; |
||||||
|
else if (arg[i] == "-namespace") Tab.nsName = arg[++i]; |
||||||
|
else if (arg[i] == "-trace") 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(dir); |
||||||
|
ParserGen.Init(file, dir); |
||||||
|
|
||||||
|
Parser.Parse(); |
||||||
|
|
||||||
|
Trace.Close(); |
||||||
|
Console.WriteLine(); |
||||||
|
Console.WriteLine("{0} errors detected", Errors.count); |
||||||
|
} else { |
||||||
|
Console.WriteLine("Usage: Coco {{Option}} Grammar.ATG {{Option}}{0}" + |
||||||
|
"Options:{0}" + |
||||||
|
" -nonamespace{0}" + |
||||||
|
" -namespace <packageName>{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}" + |
||||||
|
" 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 referenced by the environment variable CRFRAMES.", |
||||||
|
Environment.NewLine); |
||||||
|
} |
||||||
|
} |
||||||
|
} // end Coco
|
||||||
|
|
||||||
|
} // end namespace
|
||||||
@ -0,0 +1,889 @@ |
|||||||
|
// DFA.cs Scaner automaton gnerated by Coco/R H.Moessenboeck, Univ. of Linz
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
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 const char CR = '\r'; |
||||||
|
public const char LF = '\n'; |
||||||
|
|
||||||
|
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
|
||||||
|
static string srcDir; // directory of attributed grammar 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 dirtyDFA; // DFA may become nondeterministic in MatchedDFA
|
||||||
|
public static bool hasCtxMoves; // DFA has context transitions
|
||||||
|
|
||||||
|
//---------- 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 <= 'Z') val = 16 * val + (10 + ch - 'A'); |
||||||
|
else Parser.SemErr("bad escape sequence in string or character"); |
||||||
|
} |
||||||
|
return (char)val; |
||||||
|
} |
||||||
|
|
||||||
|
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) { |
||||||
|
if (ch == '\\') buf.Append("\\\\"); |
||||||
|
else if (ch == '"') buf.Append("\\\""); |
||||||
|
else if (ch < ' ' || ch > '\u007f') buf.Append(Char2Hex(ch)); |
||||||
|
else buf.Append(ch); |
||||||
|
} |
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
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)); |
||||||
|
} |
||||||
|
|
||||||
|
static Symbol MatchedDFA(string s, Symbol sym) { |
||||||
|
int i, len = s.Length; |
||||||
|
bool weakMatch = false; |
||||||
|
// s has no quotes
|
||||||
|
State state = firstState; |
||||||
|
for (i = 0; i < len; i++) { // try to match s against existing DFA
|
||||||
|
Action a = state.TheAction(s[i]); |
||||||
|
if (a == null) break; |
||||||
|
if (a.typ == Node.clas) weakMatch = true; |
||||||
|
state = a.target.state; |
||||||
|
} |
||||||
|
// don't execute the following block if s was totally consumed and the DFA is in a final state
|
||||||
|
if (weakMatch && (i != len || state.endOf == null)) { |
||||||
|
state = firstState; i = 0; |
||||||
|
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; |
||||||
|
return matchedSym; |
||||||
|
} |
||||||
|
|
||||||
|
public static void MatchLiteral(Symbol sym) { // store string either as token or as literal
|
||||||
|
string name = Unescape(sym.name.Substring(1, sym.name.Length-2)); |
||||||
|
if (name.IndexOf('\0') >= 0) Parser.SemErr("\\0 not allowed here. Used as eof character"); |
||||||
|
Symbol matchedSym = MatchedDFA(name, sym); |
||||||
|
if (matchedSym == null) |
||||||
|
sym.tokenKind = Symbol.classToken; |
||||||
|
else { |
||||||
|
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("\n---------- 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("\n---------- 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 == EOF) return false;"); |
||||||
|
gen.WriteLine( "\t\t\t\telse NextCh();"); |
||||||
|
gen.WriteLine( "\t\t\t}"); |
||||||
|
} |
||||||
|
|
||||||
|
static void GenComment(Comment com, int i) { |
||||||
|
gen.Write ("\n\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 void GenLiterals () { |
||||||
|
foreach (Symbol sym in Symbol.terminals) { |
||||||
|
if (sym.tokenKind == Symbol.litToken) { |
||||||
|
// sym.name stores literals with quotes, e.g. "\"Literal\"",
|
||||||
|
// therefore do NOT place any quotes around {0} after the case
|
||||||
|
// or you'll get: case ""Literal"": t.kind = ..., which causes an error
|
||||||
|
gen.WriteLine("\t\t\tcase {0}: t.kind = {1}; break;", sym.name, sym.n); |
||||||
|
} |
||||||
|
} |
||||||
|
gen.WriteLine("\t\t\tdefault: break;"); |
||||||
|
} |
||||||
|
|
||||||
|
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; "); |
||||||
|
gen.Write("buf.Append(ch); 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) { |
||||||
|
startTab[0] = State.lastNr + 1; // eof
|
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void WriteScanner() { |
||||||
|
int i, j; |
||||||
|
int[] startTab = new int[CharClass.charSetSize]; |
||||||
|
string dir = System.Environment.CurrentDirectory; |
||||||
|
string fr = dir + "\\Scanner.frame"; |
||||||
|
if (!File.Exists(fr)) { |
||||||
|
string frameDir = Environment.GetEnvironmentVariable("crframes"); |
||||||
|
if (frameDir != null) fr = frameDir.Trim() + "\\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."); |
||||||
|
} |
||||||
|
try { |
||||||
|
string fn = dir + "\\Scanner.cs"; |
||||||
|
if (File.Exists(fn)) File.Copy(fn, fn+".old", true); |
||||||
|
FileStream s = new FileStream(fn, FileMode.Create); |
||||||
|
gen = new StreamWriter(s); |
||||||
|
} catch (IOException) { |
||||||
|
Errors.Exception("-- Cannot generate scanner file."); |
||||||
|
} |
||||||
|
if (dirtyDFA) MakeDeterministic(); |
||||||
|
FillStartTab(startTab); |
||||||
|
|
||||||
|
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("-->constants"); |
||||||
|
gen.WriteLine("\tconst int maxT = {0};", Symbol.terminals.Count - 1); |
||||||
|
CopyFramePart("-->declarations"); |
||||||
|
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 0};"); |
||||||
|
CopyFramePart("-->initialization"); |
||||||
|
gen.WriteLine("\t\tignore = new BitArray({0});", CharClass.charSetSize); |
||||||
|
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("-->comment"); |
||||||
|
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("\t\tint apx = 0;"); |
||||||
|
CopyFramePart("-->scan2"); |
||||||
|
for (State state = firstState.next; state != null; state = state.next) |
||||||
|
WriteState(state); |
||||||
|
gen.Write("\t\t\tcase "+(State.lastNr+1)+": {t.kind = 0; goto done;}"); |
||||||
|
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 dir) { |
||||||
|
srcDir = dir; |
||||||
|
firstState = null; lastState = null; State.lastNr = -1; |
||||||
|
firstState = NewState(); |
||||||
|
Melted.first = null; Comment.first = null; |
||||||
|
dirtyDFA = false; |
||||||
|
hasCtxMoves = false; |
||||||
|
} |
||||||
|
|
||||||
|
} // end DFA
|
||||||
|
|
||||||
|
} // end namespace
|
||||||
@ -0,0 +1,764 @@ |
|||||||
|
using System.Collections; |
||||||
|
using System.Text; |
||||||
|
using System; |
||||||
|
using System.Reflection; |
||||||
|
|
||||||
|
namespace at.jku.ssw.Coco { |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class Parser { |
||||||
|
const int maxT = 42; |
||||||
|
|
||||||
|
const bool T = true; |
||||||
|
const bool x = false; |
||||||
|
const int minErrDist = 2; |
||||||
|
const string errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
|
||||||
|
|
||||||
|
static Token t; // last recognized token
|
||||||
|
static Token la; // lookahead token
|
||||||
|
static int errDist = minErrDist; |
||||||
|
|
||||||
|
const int id = 0; |
||||||
|
const int str = 1; |
||||||
|
|
||||||
|
static bool genScanner; |
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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; } /* ML return changed to break */ |
||||||
|
if (la.kind == 43) { |
||||||
|
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; string gramName; |
||||||
|
if (la.kind == 40) { |
||||||
|
UsingDecl(out ParserGen.usingPos); |
||||||
|
} |
||||||
|
Expect(6); |
||||||
|
int gramLine = t.line; |
||||||
|
genScanner = true; |
||||||
|
bool ok = 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); |
||||||
|
while (StartOf(2)) { |
||||||
|
Declaration(); |
||||||
|
} |
||||||
|
while (!(la.kind == 0 || la.kind == 7)) {SynErr(43); Get();} |
||||||
|
Expect(7); |
||||||
|
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 == 38) { |
||||||
|
SemText(out sym.semPos); |
||||||
|
} |
||||||
|
ExpectWeak(8, 3); |
||||||
|
Expression(out g); |
||||||
|
sym.graph = g.l; |
||||||
|
Graph.Finish(g); |
||||||
|
|
||||||
|
ExpectWeak(9, 4); |
||||||
|
} |
||||||
|
Expect(10); |
||||||
|
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(); |
||||||
|
ok = ok && Tab.GrammarOk(); |
||||||
|
if (Tab.ddt[7]) Tab.XRef(); |
||||||
|
if (ok) { |
||||||
|
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(9); |
||||||
|
} |
||||||
|
|
||||||
|
static void UsingDecl(out Position pos) { |
||||||
|
Expect(40); |
||||||
|
int beg = t.pos; |
||||||
|
while (StartOf(5)) { |
||||||
|
Get(); |
||||||
|
} |
||||||
|
Expect(41); |
||||||
|
int end = t.pos; |
||||||
|
while (la.kind == 40) { |
||||||
|
Get(); |
||||||
|
while (StartOf(5)) { |
||||||
|
Get(); |
||||||
|
} |
||||||
|
Expect(41); |
||||||
|
end = t.pos; |
||||||
|
} |
||||||
|
pos = new Position(beg, end - beg + 1, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void Declaration() { |
||||||
|
Graph g1, g2; bool nested = false; |
||||||
|
switch (la.kind) { |
||||||
|
case 11: { |
||||||
|
Get(); |
||||||
|
while (la.kind == 1) { |
||||||
|
SetDecl(); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
case 12: { |
||||||
|
Get(); |
||||||
|
while (la.kind == 1 || la.kind == 3 || la.kind == 5) { |
||||||
|
TokenDecl(Node.t); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
case 13: { |
||||||
|
Get(); |
||||||
|
while (la.kind == 1 || la.kind == 3 || la.kind == 5) { |
||||||
|
TokenDecl(Node.pr); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
case 14: { |
||||||
|
Get(); |
||||||
|
Expect(15); |
||||||
|
TokenExpr(out g1); |
||||||
|
Expect(16); |
||||||
|
TokenExpr(out g2); |
||||||
|
if (la.kind == 17) { |
||||||
|
Get(); |
||||||
|
nested = true; |
||||||
|
} else if (StartOf(6)) { |
||||||
|
nested = false; |
||||||
|
} else SynErr(44); |
||||||
|
new Comment(g1.l, g2.l, nested); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 18: { |
||||||
|
Get(); |
||||||
|
Set(out Tab.ignored); |
||||||
|
Tab.ignored[' '] = true; /* ' ' is always ignored */ |
||||||
|
if (Tab.ignored[0]) SemErr("may not ignore \'\\0\'"); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 19: { |
||||||
|
Get(); |
||||||
|
Symbol.tokenNames = new Hashtable(); |
||||||
|
while (la.kind == 1 || la.kind == 3) { |
||||||
|
if (la.kind == 3) { |
||||||
|
Get(); |
||||||
|
} else { |
||||||
|
Get(); |
||||||
|
} |
||||||
|
string key = t.val; |
||||||
|
Expect(8); |
||||||
|
Expect(1); |
||||||
|
string val = t.val; Symbol.tokenNames.Add(key, val); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
default: SynErr(45); break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void AttrDecl(Symbol sym) { |
||||||
|
Expect(24); |
||||||
|
int beg = la.pos; int col = la.col; |
||||||
|
while (StartOf(7)) { |
||||||
|
if (la.kind == 24) { |
||||||
|
AttrDecl(sym); |
||||||
|
} else if (StartOf(8)) { |
||||||
|
Get(); |
||||||
|
} else { |
||||||
|
Get(); |
||||||
|
SemErr("bad string in semantic action"); |
||||||
|
} |
||||||
|
} |
||||||
|
Expect(25); |
||||||
|
sym.attrPos = new Position(beg, t.pos - beg, col); |
||||||
|
} |
||||||
|
|
||||||
|
static void SemText(out Position pos) { |
||||||
|
Expect(38); |
||||||
|
int beg = la.pos; int col = la.col; |
||||||
|
while (StartOf(9)) { |
||||||
|
if (StartOf(10)) { |
||||||
|
Get(); |
||||||
|
} else if (la.kind == 4) { |
||||||
|
Get(); |
||||||
|
SemErr("bad string in semantic action"); |
||||||
|
} else { |
||||||
|
Get(); |
||||||
|
SemErr("missing end of previous semantic action"); |
||||||
|
} |
||||||
|
} |
||||||
|
Expect(39); |
||||||
|
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,11,12) ) { |
||||||
|
Term(out g2); |
||||||
|
if (first) { Graph.MakeFirstAlt(g); first = false; } |
||||||
|
Graph.MakeAlternative(g, g2); |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void SetDecl() { |
||||||
|
BitArray s; |
||||||
|
Expect(1); |
||||||
|
string name = t.val; |
||||||
|
CharClass c = CharClass.Find(name); |
||||||
|
if (c != null) SemErr("name declared twice"); |
||||||
|
|
||||||
|
Expect(8); |
||||||
|
Set(out s); |
||||||
|
if (Sets.Elements(s) == 0) SemErr("character set must not be empty"); |
||||||
|
c = new CharClass(name, s); |
||||||
|
|
||||||
|
Expect(9); |
||||||
|
} |
||||||
|
|
||||||
|
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.classToken; |
||||||
|
} |
||||||
|
|
||||||
|
while (!(StartOf(13))) {SynErr(46); Get();} |
||||||
|
if (la.kind == 8) { |
||||||
|
Get(); |
||||||
|
TokenExpr(out g); |
||||||
|
Expect(9); |
||||||
|
if (kind != id) SemErr("a literal must not be declared with a structure"); |
||||||
|
Graph.Finish(g); |
||||||
|
DFA.ConvertToStates(g.l, sym); |
||||||
|
|
||||||
|
} else if (la.kind == 9) { |
||||||
|
Get(); |
||||||
|
if (typ != Node.rslv) SemErr("resolver is only allowed in RESOLVERS section"); |
||||||
|
} else if (StartOf(14)) { |
||||||
|
if (kind == id) genScanner = false; |
||||||
|
else DFA.MatchLiteral(sym); |
||||||
|
|
||||||
|
} else SynErr(47); |
||||||
|
if (la.kind == 38) { |
||||||
|
SemText(out sym.semPos); |
||||||
|
if (typ == Node.t) SemErr("semantic action not allowed here"); |
||||||
|
} else if (StartOf(15)) { |
||||||
|
if (typ == Node.rslv) SemErr("resolvers must have a semantic action"); |
||||||
|
} else SynErr(48); |
||||||
|
} |
||||||
|
|
||||||
|
static void TokenExpr(out Graph g) { |
||||||
|
Graph g2; |
||||||
|
TokenTerm(out g); |
||||||
|
bool first = true; |
||||||
|
while (WeakSeparator(26,16,17) ) { |
||||||
|
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 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) 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); |
||||||
|
s[0] = false; |
||||||
|
|
||||||
|
} else SynErr(49); |
||||||
|
} |
||||||
|
|
||||||
|
static void Char(out int n) { |
||||||
|
Expect(5); |
||||||
|
string name = t.val; |
||||||
|
name = DFA.Unescape(name.Substring(1, name.Length-2)); |
||||||
|
int max = CharClass.charSetSize; |
||||||
|
if (name.Length != 1 || name[0] > max-1) SemErr("unacceptable character value"); |
||||||
|
n = name[0] % max; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
} else SynErr(50); |
||||||
|
} |
||||||
|
|
||||||
|
static void Term(out Graph g) { |
||||||
|
Graph g2; Position pos; Node rslv = null; |
||||||
|
g = null; |
||||||
|
|
||||||
|
if (StartOf(18)) { |
||||||
|
if (la.kind == 35) { |
||||||
|
rslv = new Node(Node.rslv, null, la.line); |
||||||
|
ResolveExpr(out pos); |
||||||
|
rslv.pos = pos; |
||||||
|
g = new Graph(rslv); |
||||||
|
|
||||||
|
} |
||||||
|
Factor(out g2); |
||||||
|
if (rslv != null) Graph.MakeSequence(g, g2); |
||||||
|
else g = g2; |
||||||
|
|
||||||
|
while (StartOf(19)) { |
||||||
|
Factor(out g2); |
||||||
|
Graph.MakeSequence(g, g2); |
||||||
|
} |
||||||
|
} else if (StartOf(20)) { |
||||||
|
g = new Graph(new Node(Node.eps, null, 0)); |
||||||
|
} else SynErr(51); |
||||||
|
} |
||||||
|
|
||||||
|
static void ResolveExpr(out Position pos) { |
||||||
|
Expect(35); |
||||||
|
Expect(28); |
||||||
|
int beg = la.pos; int col = la.col; |
||||||
|
if (la.kind == 8 || la.kind == 36) { |
||||||
|
if (la.kind == 8) { |
||||||
|
Get(); |
||||||
|
} else { |
||||||
|
Get(); |
||||||
|
} |
||||||
|
CondPart(); |
||||||
|
} else if (la.kind == 28) { |
||||||
|
Get(); |
||||||
|
CondPart(); |
||||||
|
Expect(29); |
||||||
|
} else if (StartOf(21)) { |
||||||
|
Get(); |
||||||
|
CondPart(); |
||||||
|
} else SynErr(52); |
||||||
|
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); |
||||||
|
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); |
||||||
|
} 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 && typ != Node.rslv) /* ML */ |
||||||
|
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 38: { |
||||||
|
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(53); break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void Attribs(Node p) |
||||||
|
{ |
||||||
|
Expect(24); |
||||||
|
int beg = la.pos; int col = la.col; |
||||||
|
while (StartOf(7)) { |
||||||
|
if (StartOf(8)) { |
||||||
|
Get(); |
||||||
|
} else { |
||||||
|
Get(); |
||||||
|
SemErr("bad string in attributes"); |
||||||
|
} |
||||||
|
} |
||||||
|
Expect(25); |
||||||
|
p.pos = new Position(beg, t.pos - beg, col); |
||||||
|
} |
||||||
|
|
||||||
|
static void CondPart() { |
||||||
|
while (StartOf(22)) { |
||||||
|
if (la.kind == 28) { |
||||||
|
Get(); |
||||||
|
CondPart(); |
||||||
|
} else { |
||||||
|
Get(); |
||||||
|
} |
||||||
|
} |
||||||
|
Expect(29); |
||||||
|
} |
||||||
|
|
||||||
|
static void TokenTerm(out Graph g) { |
||||||
|
Graph g2; |
||||||
|
TokenFactor(out g); |
||||||
|
while (StartOf(16)) { |
||||||
|
TokenFactor(out g2); |
||||||
|
Graph.MakeSequence(g, g2); |
||||||
|
} |
||||||
|
if (la.kind == 37) { |
||||||
|
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 = new Graph(); |
||||||
|
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); |
||||||
|
} else g = Graph.StrToGraph(name); // str
|
||||||
|
|
||||||
|
} 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(54); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void Parse() { |
||||||
|
Errors.SynErr = new ErrorCodeProc(SynErr); |
||||||
|
la = new Token(); |
||||||
|
la.val = ""; |
||||||
|
Get(); |
||||||
|
Coco(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
static void SynErr (int line, int col, int n) { |
||||||
|
Errors.count++; |
||||||
|
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 = "\"PRODUCTIONS\" expected"; break; |
||||||
|
case 8: s = "\"=\" expected"; break; |
||||||
|
case 9: s = "\".\" expected"; break; |
||||||
|
case 10: s = "\"END\" expected"; break; |
||||||
|
case 11: s = "\"CHARACTERS\" expected"; break; |
||||||
|
case 12: s = "\"TOKENS\" expected"; break; |
||||||
|
case 13: s = "\"PRAGMAS\" expected"; break; |
||||||
|
case 14: s = "\"COMMENTS\" expected"; break; |
||||||
|
case 15: s = "\"FROM\" expected"; break; |
||||||
|
case 16: s = "\"TO\" expected"; break; |
||||||
|
case 17: s = "\"NESTED\" expected"; break; |
||||||
|
case 18: s = "\"IGNORE\" expected"; break; |
||||||
|
case 19: s = "\"TOKENNAMES\" 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 = "\"!=\" expected"; break; |
||||||
|
case 37: s = "\"CONTEXT\" expected"; break; |
||||||
|
case 38: s = "\"(.\" expected"; break; |
||||||
|
case 39: s = "\".)\" expected"; break; |
||||||
|
case 40: s = "\"using\" expected"; break; |
||||||
|
case 41: s = "\";\" expected"; break; |
||||||
|
case 42: s = "??? expected"; break; |
||||||
|
case 43: s = "this symbol not expected in Coco"; break; |
||||||
|
case 44: s = "invalid Declaration"; break; |
||||||
|
case 45: s = "invalid Declaration"; break; |
||||||
|
case 46: s = "this symbol not expected in TokenDecl"; break; |
||||||
|
case 47: s = "invalid TokenDecl"; break; |
||||||
|
case 48: s = "invalid TokenDecl"; break; |
||||||
|
case 49: s = "invalid SimSet"; break; |
||||||
|
case 50: s = "invalid Sym"; break; |
||||||
|
case 51: s = "invalid Term"; break; |
||||||
|
case 52: s = "invalid ResolveExpr"; break; |
||||||
|
case 53: s = "invalid Factor"; break; |
||||||
|
case 54: s = "invalid TokenFactor"; break; |
||||||
|
|
||||||
|
default: s = "error " + n; break; |
||||||
|
} |
||||||
|
Console.WriteLine(errMsgFormat, line, col, s); |
||||||
|
} |
||||||
|
|
||||||
|
static bool[,] set = { |
||||||
|
{T,T,x,T, x,T,x,T, T,T,x,T, T,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,T,x, x,x,x,x}, |
||||||
|
{x,T,T,T, T,T,T,x, T,T,T,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,x}, |
||||||
|
{x,x,x,x, x,x,x,x, x,x,x,T, T,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, x,x,x,x}, |
||||||
|
{T,T,x,T, x,T,x,T, T,T,x,T, T,T,T,x, x,x,T,T, x,x,x,T, x,x,T,T, T,x,T,x, T,x,T,T, x,x,T,x, x,x,x,x}, |
||||||
|
{T,T,x,T, x,T,x,T, T,T,T,T, T,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,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, T,x,T,x}, |
||||||
|
{x,x,x,x, x,x,x,T, x,x,x,T, T,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, 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,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,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,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,T,x,x, T,T,T,x}, |
||||||
|
{x,T,x,T, x,T,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,T,T, T,T,T,T, T,T,T,T, x,x,T,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, 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,x,T, x,T,x,T, T,T,x,T, T,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,T,x, x,x,x,x}, |
||||||
|
{x,T,x,T, x,T,x,T, x,x,x,T, T,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,T,x, x,x,x,x}, |
||||||
|
{x,T,x,T, x,T,x,T, x,x,x,T, T,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, 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,T, x,T,x,T, T,T,T,x, T,T,T,T, 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,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,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,x,T,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, x,x,x,x, x,x,T,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x}, |
||||||
|
{x,T,T,T, T,T,T,T, x,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, x,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,x,T,T, T,T,T,T, T,T,T,T, T,T,T,x} |
||||||
|
|
||||||
|
}; |
||||||
|
} // end Parser
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,120 @@ |
|||||||
|
using System; |
||||||
|
using System.Reflection; |
||||||
|
|
||||||
|
-->namespace |
||||||
|
|
||||||
|
-->tokens |
||||||
|
|
||||||
|
public class Parser |
||||||
|
{ |
||||||
|
-->constants |
||||||
|
const bool T = true; |
||||||
|
const bool x = false; |
||||||
|
const int minErrDist = 2; |
||||||
|
const string errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text |
||||||
|
int errDist = minErrDist; |
||||||
|
Errors errors; |
||||||
|
Lexer lexer; |
||||||
|
|
||||||
|
public Errors Errors { |
||||||
|
get { |
||||||
|
return errors; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
-->declarations |
||||||
|
|
||||||
|
/* |
||||||
|
-->pragmas |
||||||
|
*/ |
||||||
|
void SynErr(int n) |
||||||
|
{ |
||||||
|
if (errDist >= minErrDist) { |
||||||
|
errors.SynErr(lexer.LookAhead.line, lexer.LookAhead.col, n); |
||||||
|
} |
||||||
|
errDist = 0; |
||||||
|
} |
||||||
|
|
||||||
|
public void SemErr(string msg) |
||||||
|
{ |
||||||
|
if (errDist >= minErrDist) { |
||||||
|
errors.Error(lexer.Token.line, lexer.Token.col, msg); |
||||||
|
} |
||||||
|
errDist = 0; |
||||||
|
} |
||||||
|
|
||||||
|
void Expect(int n) |
||||||
|
{ |
||||||
|
if (lexer.LookAhead.kind == n) { |
||||||
|
lexer.NextToken(); |
||||||
|
} else { |
||||||
|
SynErr(n); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool StartOf(int s) |
||||||
|
{ |
||||||
|
return set[s, lexer.LookAhead.kind]; |
||||||
|
} |
||||||
|
|
||||||
|
void ExpectWeak(int n, int follow) |
||||||
|
{ |
||||||
|
if (lexer.LookAhead.kind == n) { |
||||||
|
lexer.NextToken(); |
||||||
|
} else { |
||||||
|
SynErr(n); |
||||||
|
while (!StartOf(follow)) { |
||||||
|
lexer.NextToken(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool WeakSeparator(int n, int syFol, int repFol) |
||||||
|
{ |
||||||
|
bool[] s = new bool[maxT + 1]; |
||||||
|
|
||||||
|
if (lexer.LookAhead.kind == n) { |
||||||
|
lexer.NextToken(); |
||||||
|
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[lexer.LookAhead.kind]) { |
||||||
|
lexer.NextToken(); |
||||||
|
} |
||||||
|
return StartOf(syFol); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
-->productions |
||||||
|
|
||||||
|
public void Parse(Lexer lexer) |
||||||
|
{ |
||||||
|
this.errors = lexer.Errors; |
||||||
|
this.lexer = lexer; |
||||||
|
errors.SynErr = new ErrorCodeProc(SynErr); |
||||||
|
lexer.NextToken(); |
||||||
|
-->parseRoot |
||||||
|
} |
||||||
|
|
||||||
|
void SynErr(int line, int col, int errorNumber) |
||||||
|
{ |
||||||
|
errors.count++; |
||||||
|
string s; |
||||||
|
switch (errorNumber) { |
||||||
|
-->errors |
||||||
|
default: s = "error " + errorNumber; break; |
||||||
|
} |
||||||
|
errors.Error(line, col, s); |
||||||
|
} |
||||||
|
|
||||||
|
static bool[,] set = { |
||||||
|
-->initialization |
||||||
|
}; |
||||||
|
} // end Parser |
||||||
|
|
||||||
|
$$$ |
||||||
@ -0,0 +1,430 @@ |
|||||||
|
// ParserGen.cs Parser generator of Coco/R H.Moessenboeck, Univ. of Linz
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
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 char TAB = '\t'; |
||||||
|
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
|
||||||
|
|
||||||
|
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: this replaces the method int Alternatives (Node p) */ |
||||||
|
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, Buffer.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 <= ' '; 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 { |
||||||
|
GenCond(s); |
||||||
|
if (p.typ == Node.alt) { |
||||||
|
// for { ... | IF ... | ... } or [ ... | IF ... | ... ]
|
||||||
|
// generate conditions: StartOf(...) || IF
|
||||||
|
Node q = p; |
||||||
|
while (q != null) { |
||||||
|
if (q.sub.typ == Node.rslv) { |
||||||
|
gen.Write(" || "); |
||||||
|
CopySourcePart(q.sub.pos, 0); |
||||||
|
} |
||||||
|
q = q.down; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void GenCond (BitArray s) { |
||||||
|
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)); |
||||||
|
} |
||||||
|
|
||||||
|
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); |
||||||
|
// M.Krueger: changed Get() to lexer.NextToken();
|
||||||
|
if (isChecked[p.sym.n]) gen.WriteLine("lexer.NextToken();"); |
||||||
|
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); |
||||||
|
// M.Krueger: changed Get() to lexer.NextToken();
|
||||||
|
gen.WriteLine("lexer.NextToken();"); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Node.eps: 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); gen.Write(")) {"); |
||||||
|
// M.Krueger: changed Get() to lexer.NextToken();
|
||||||
|
gen.Write("SynErr({0}); lexer.NextToken(); ", errorNr); 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, 1); |
||||||
|
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, indent + 1, s1); |
||||||
|
else GenCode(p2.sub.next, 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); |
||||||
|
else s1 = Tab.First(p.sub.next); |
||||||
|
if (!Sets.Equals(isChecked, s1)) { |
||||||
|
Indent(indent); |
||||||
|
gen.Write("if ("); GenCond(s1, p.sub); gen.WriteLine(") {"); |
||||||
|
if (p.sub.typ != Node.rslv) GenCode(p.sub, indent + 1, s1); |
||||||
|
else GenCode(p.sub.next, indent + 1, s1); |
||||||
|
Indent(indent); gen.WriteLine("}"); |
||||||
|
} else GenCode(p.sub, indent, isChecked); |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* ML 2002-09-07 Generates the class "Tokens" * |
||||||
|
* which maps the token number to meaningfully named integer constants, * |
||||||
|
* as specified in the NAMES section. */ |
||||||
|
static void GenTokens() { |
||||||
|
if (Symbol.tokenNames != null && Symbol.tokenNames.Count > 0) { |
||||||
|
|
||||||
|
gen.WriteLine("public class Tokens {"); |
||||||
|
|
||||||
|
foreach (DictionaryEntry entry in Symbol.tokenNames) { |
||||||
|
string token = entry.Key as string; |
||||||
|
string name = entry.Value as string; |
||||||
|
if (IsCSharpKW(name)) { |
||||||
|
Parser.SemErr(name + " is a C# keyword." + |
||||||
|
"Use another name for the token " + token); |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
Symbol sym = Symbol.Find(token); |
||||||
|
if (sym != null && (sym.typ == Node.t || sym.typ == Node.wt)) |
||||||
|
gen.WriteLine("\tpublic const int {0} = {1};", name, sym.n); |
||||||
|
} |
||||||
|
|
||||||
|
gen.WriteLine("}"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* AW 03-01-20 to generate token name: * |
||||||
|
* a C# keyword must not be used as an identifier */ |
||||||
|
static bool IsCSharpKW (string name) { |
||||||
|
return Array.BinarySearch(csKeywords, name) >= 0; |
||||||
|
} |
||||||
|
|
||||||
|
static string[] csKeywords = new string[] { |
||||||
|
"abstract", "as", "base", "bool", "break", "byte", |
||||||
|
"case", "catch", "char", "checked", "class", "const", |
||||||
|
"continue", "decimal", "default", "delegate", "do", "double", |
||||||
|
"else", "enum", "event", "explicit", "extern", "false", |
||||||
|
"finally", "fixed", "float", "for", "foreach", "goto", |
||||||
|
"if", "implicit", "in", "int", "interface", "internal", |
||||||
|
"is", "lock", "long", "namespace", "new", "null", |
||||||
|
"object", "operator", "out", "override", "params", "private", |
||||||
|
"protected", "public", "readonly", "ref", "return", "sbyte", |
||||||
|
"sealed", "short", "sizeof", "stackalloc", "static", "string", |
||||||
|
"struct", "switch", "this", "throw", "true", "try", |
||||||
|
"typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", |
||||||
|
"using", "virtual", "void", "volatile", "while" |
||||||
|
}; |
||||||
|
|
||||||
|
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; |
||||||
|
gen.Write("\tvoid {0}(", sym.name); |
||||||
|
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{"); |
||||||
|
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},"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void WriteParser () { |
||||||
|
FileStream s; |
||||||
|
symSet.Add(Tab.allSyncSets); |
||||||
|
string fr = srcDir + "Parser.frame"; |
||||||
|
if (!File.Exists(fr)) { |
||||||
|
string frameDir = Environment.GetEnvironmentVariable("crframes"); |
||||||
|
if (frameDir != null) fr = frameDir.Trim() + "\\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."); |
||||||
|
} |
||||||
|
try { |
||||||
|
string fn = srcDir + "Parser.cs"; |
||||||
|
if (File.Exists(fn)) File.Copy(fn, fn.Replace(".cs", ".old.cs"), true); |
||||||
|
s = new FileStream(fn, FileMode.Create); |
||||||
|
gen = new StreamWriter(s); |
||||||
|
} catch (IOException) { |
||||||
|
Errors.Exception("-- Cannot generate parser file"); |
||||||
|
} |
||||||
|
err = new StringWriter(); |
||||||
|
foreach (Symbol sym in Symbol.terminals) GenErrorMsg(tErr, sym); |
||||||
|
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.Write("namespace "); |
||||||
|
gen.Write(Tab.nsName); |
||||||
|
gen.Write(" {"); |
||||||
|
} |
||||||
|
CopyFramePart("-->tokens"); GenTokens(); /* ML 2002/09/07 write the tokenkinds */ |
||||||
|
CopyFramePart("-->constants"); |
||||||
|
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("-->errors"); gen.Write(err.ToString()); |
||||||
|
CopyFramePart("-->initialization"); InitSets(); |
||||||
|
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
|
||||||
@ -0,0 +1,688 @@ |
|||||||
|
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 Token () { } |
||||||
|
|
||||||
|
public Token (int kind) { this.kind = kind; } |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class Buffer { |
||||||
|
|
||||||
|
public const int eof = '\uffff'; |
||||||
|
|
||||||
|
static byte[] buf; |
||||||
|
static int bufLen; |
||||||
|
static int pos; |
||||||
|
public static string fileName; |
||||||
|
|
||||||
|
public static int CountLines(int offset) |
||||||
|
{ |
||||||
|
int line = 0; |
||||||
|
for (int i = 0; i <= offset; ++i) { |
||||||
|
if (buf[i] == '\n') { |
||||||
|
++line; |
||||||
|
} |
||||||
|
} |
||||||
|
return line; |
||||||
|
} |
||||||
|
|
||||||
|
public static void Fill (string fileName) { |
||||||
|
Buffer.fileName = fileName; |
||||||
|
FileStream s = null; |
||||||
|
try { |
||||||
|
s = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); |
||||||
|
bufLen = (int) s.Length; |
||||||
|
buf = new byte[bufLen]; |
||||||
|
s.Read(buf, 0, bufLen); |
||||||
|
pos = 0; |
||||||
|
|
||||||
|
} catch (IOException) { |
||||||
|
|
||||||
|
Console.WriteLine("--- Cannot open file {0}", fileName); |
||||||
|
|
||||||
|
System.Environment.Exit(0); |
||||||
|
|
||||||
|
} finally { |
||||||
|
|
||||||
|
if (s != null) s.Close(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static int Read () { |
||||||
|
|
||||||
|
if (pos < bufLen) return buf[pos++]; |
||||||
|
|
||||||
|
else return 0; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static int Peek () { |
||||||
|
|
||||||
|
if (pos < bufLen) return buf[pos]; |
||||||
|
|
||||||
|
else return 0; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 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 EOF = '\0'; |
||||||
|
|
||||||
|
const char EOL = '\n'; |
||||||
|
|
||||||
|
const int maxT = 42; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const int noSym = 42; |
||||||
|
|
||||||
|
static short[] start = { |
||||||
|
|
||||||
|
32, 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, 27, 11, 0, 10, 0, 0, 5, 21, 22, 0, 15, 0, 16, 14, 0, |
||||||
|
|
||||||
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 31, 18, 13, 19, 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, 0, 24, 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, 25, 20, 26, 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, |
||||||
|
|
||||||
|
0}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ML ----- begin */ |
||||||
|
|
||||||
|
static Token tokens; // the complete input token stream
|
||||||
|
|
||||||
|
static Token pt; // current peek token
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int peekCount = 0; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static int PeekCount { get { return peekCount; } } |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void Init (String fileName) { |
||||||
|
|
||||||
|
Buffer.Fill(fileName); |
||||||
|
|
||||||
|
pos = -1; line = 1; lineStart = 0; |
||||||
|
|
||||||
|
oldEols = 0; |
||||||
|
|
||||||
|
NextCh(); |
||||||
|
|
||||||
|
ignore = new BitArray(256); |
||||||
|
|
||||||
|
ignore[9] = true; ignore[10] = true; ignore[13] = true; ignore[32] = true; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AW 2003-03-07 fill token list */ |
||||||
|
|
||||||
|
tokens = new Token(); // first token is a dummy
|
||||||
|
|
||||||
|
Token node = tokens; |
||||||
|
|
||||||
|
do { |
||||||
|
|
||||||
|
node.next = NextToken(); |
||||||
|
|
||||||
|
node = node.next; |
||||||
|
|
||||||
|
} while (node.kind != 0); /* AW: 0 => 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; |
||||||
|
|
||||||
|
else if (ch > '\u007f') ch = '?'; |
||||||
|
|
||||||
|
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 == 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 "PRODUCTIONS": t.kind = 7; break; |
||||||
|
|
||||||
|
case "END": t.kind = 10; break; |
||||||
|
|
||||||
|
case "CHARACTERS": t.kind = 11; break; |
||||||
|
|
||||||
|
case "TOKENS": t.kind = 12; break; |
||||||
|
|
||||||
|
case "PRAGMAS": t.kind = 13; break; |
||||||
|
|
||||||
|
case "COMMENTS": t.kind = 14; break; |
||||||
|
|
||||||
|
case "FROM": t.kind = 15; break; |
||||||
|
|
||||||
|
case "TO": t.kind = 16; break; |
||||||
|
|
||||||
|
case "NESTED": t.kind = 17; break; |
||||||
|
|
||||||
|
case "IGNORE": t.kind = 18; break; |
||||||
|
|
||||||
|
case "TOKENNAMES": 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 = 37; break; |
||||||
|
|
||||||
|
case "using": t.kind = 40; 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 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 >= 1 && 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 = 43; goto done;} |
||||||
|
|
||||||
|
case 11: |
||||||
|
|
||||||
|
if ((ch >= 1 && 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 = 8; goto done;} |
||||||
|
|
||||||
|
case 14: |
||||||
|
|
||||||
|
if (ch == '.') {buf.Append(ch); NextCh(); goto case 17;} |
||||||
|
|
||||||
|
else if (ch == ')') {buf.Append(ch); NextCh(); goto case 30;} |
||||||
|
|
||||||
|
else {t.kind = 9; goto done;} |
||||||
|
|
||||||
|
case 15: |
||||||
|
|
||||||
|
{t.kind = 20; goto done;} |
||||||
|
|
||||||
|
case 16: |
||||||
|
|
||||||
|
{t.kind = 21; goto done;} |
||||||
|
|
||||||
|
case 17: |
||||||
|
|
||||||
|
{t.kind = 22; goto done;} |
||||||
|
|
||||||
|
case 18: |
||||||
|
|
||||||
|
{t.kind = 24; goto done;} |
||||||
|
|
||||||
|
case 19: |
||||||
|
|
||||||
|
{t.kind = 25; goto done;} |
||||||
|
|
||||||
|
case 20: |
||||||
|
|
||||||
|
{t.kind = 26; goto done;} |
||||||
|
|
||||||
|
case 21: |
||||||
|
|
||||||
|
if (ch == '.') {buf.Append(ch); NextCh(); goto case 29;} |
||||||
|
|
||||||
|
else {t.kind = 28; goto done;} |
||||||
|
|
||||||
|
case 22: |
||||||
|
|
||||||
|
{t.kind = 29; goto done;} |
||||||
|
|
||||||
|
case 23: |
||||||
|
|
||||||
|
{t.kind = 30; goto done;} |
||||||
|
|
||||||
|
case 24: |
||||||
|
|
||||||
|
{t.kind = 31; goto done;} |
||||||
|
|
||||||
|
case 25: |
||||||
|
|
||||||
|
{t.kind = 32; goto done;} |
||||||
|
|
||||||
|
case 26: |
||||||
|
|
||||||
|
{t.kind = 33; goto done;} |
||||||
|
|
||||||
|
case 27: |
||||||
|
|
||||||
|
if (ch == '=') {buf.Append(ch); NextCh(); goto case 28;} |
||||||
|
|
||||||
|
else {t.kind = noSym; goto done;} |
||||||
|
|
||||||
|
case 28: |
||||||
|
|
||||||
|
{t.kind = 36; goto done;} |
||||||
|
|
||||||
|
case 29: |
||||||
|
|
||||||
|
{t.kind = 38; goto done;} |
||||||
|
|
||||||
|
case 30: |
||||||
|
|
||||||
|
{t.kind = 39; goto done;} |
||||||
|
|
||||||
|
case 31: |
||||||
|
|
||||||
|
{t.kind = 41; goto done;} |
||||||
|
|
||||||
|
case 32: {t.kind = 0; 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 != null && pt.kind > maxT); |
||||||
|
|
||||||
|
return pt; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AW 2003-03-11 to make sure peek start at current scan position */ |
||||||
|
|
||||||
|
public static void StartPeek () { pt = t; } |
||||||
|
|
||||||
|
} // end Scanner
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public delegate void ErrorCodeProc (int line, int col, int n); |
||||||
|
|
||||||
|
public delegate void ErrorMsgProc (int line, int col, string msg); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class Errors { |
||||||
|
|
||||||
|
public static int count = 0; // number of errors detected
|
||||||
|
|
||||||
|
public static ErrorCodeProc SynErr = new ErrorCodeProc(DefaultCodeError); // syntactic errors
|
||||||
|
|
||||||
|
public static ErrorCodeProc SemErr = new ErrorCodeProc(DefaultCodeError); // semantic errors
|
||||||
|
|
||||||
|
public static ErrorMsgProc Error = new ErrorMsgProc(DefaultMsgError); // user defined string based errors
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void Exception (string s) { |
||||||
|
|
||||||
|
Console.WriteLine(s); |
||||||
|
|
||||||
|
System.Environment.Exit(0); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void DefaultCodeError (int line, int col, int n) { |
||||||
|
|
||||||
|
Console.WriteLine("-- line {0} col {1}: error {2}", line, col, n); |
||||||
|
|
||||||
|
count++; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void DefaultMsgError (int line, int col, string s) { |
||||||
|
|
||||||
|
Console.WriteLine("-- line {0} col {1}: {2}", line, col, s); |
||||||
|
|
||||||
|
count++; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} // Errors
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,222 @@ |
|||||||
|
using System; |
||||||
|
using System.Drawing; |
||||||
|
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 Point Location { |
||||||
|
get { |
||||||
|
return new Point(line, col); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Token () { } |
||||||
|
public Token (int kind) { this.kind = kind; } |
||||||
|
} |
||||||
|
|
||||||
|
public class Buffer { |
||||||
|
public const int eof = '\uffff'; |
||||||
|
|
||||||
|
static byte[] buf; |
||||||
|
static int bufLen; |
||||||
|
static int pos; |
||||||
|
|
||||||
|
public static void Fill (string fileName) { |
||||||
|
FileStream s = null; |
||||||
|
try { |
||||||
|
s = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); |
||||||
|
Fill(s); |
||||||
|
} catch (IOException) { |
||||||
|
Console.WriteLine("--- Cannot open file {0}", fileName); |
||||||
|
System.Environment.Exit(0); |
||||||
|
} finally { |
||||||
|
if (s != null) s.Close(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
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 0; |
||||||
|
} |
||||||
|
|
||||||
|
public static int Peek () { |
||||||
|
if (pos < bufLen) return buf[pos]; |
||||||
|
else return 0; |
||||||
|
} |
||||||
|
|
||||||
|
/* 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 EOF = '\0'; |
||||||
|
const char EOL = '\n'; |
||||||
|
const char CR = '\n'; |
||||||
|
|
||||||
|
-->constants |
||||||
|
|
||||||
|
-->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 |
||||||
|
|
||||||
|
/* ML ----- begin */ |
||||||
|
static Token tokens; // the complete input token stream |
||||||
|
static Token pt; // current peek token |
||||||
|
|
||||||
|
static int peekCount = 0; |
||||||
|
|
||||||
|
public static int PeekCount { get { return peekCount; } } |
||||||
|
|
||||||
|
static void Init() |
||||||
|
{ |
||||||
|
pos = -1; line = 1; lineStart = 0; |
||||||
|
oldEols = 0; |
||||||
|
NextCh(); |
||||||
|
-->initialization |
||||||
|
|
||||||
|
/* AW 2003-03-07 fill token list */ |
||||||
|
tokens = new Token(); // first token is a dummy |
||||||
|
Token node = tokens; |
||||||
|
do { |
||||||
|
node.next = NextToken(); |
||||||
|
node = node.next; |
||||||
|
} while (node.kind != 0); /* AW: 0 => EOF */ |
||||||
|
t = pt = tokens; |
||||||
|
} |
||||||
|
|
||||||
|
public static void Init(String fileName) { |
||||||
|
Buffer.Fill(fileName); |
||||||
|
Init(); |
||||||
|
} |
||||||
|
|
||||||
|
public static void Init(Stream s) { |
||||||
|
Buffer.Fill(s); |
||||||
|
Init(); |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
else if (ch > '\u007f') ch = '?'; |
||||||
|
if (ch == EOL) { line++; lineStart = pos + 1; } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
-->comment |
||||||
|
|
||||||
|
static void CheckLiteral() { |
||||||
|
switch (t.val) { |
||||||
|
-->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); |
||||||
|
buf.Append(ch); NextCh(); |
||||||
|
|
||||||
|
switch (state) { |
||||||
|
case 0: { t.kind = noSym; goto done; } // NextCh already done |
||||||
|
-->scan2 |
||||||
|
} |
||||||
|
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 != null && pt.kind > maxT); |
||||||
|
return pt; |
||||||
|
} |
||||||
|
|
||||||
|
/* AW 2003-03-11 to make sure peek start at current scan position */ |
||||||
|
public static void StartPeek () { pt = t; } |
||||||
|
} // end Scanner |
||||||
|
|
||||||
|
|
||||||
|
public delegate void ErrorCodeProc (int line, int col, int n); |
||||||
|
public delegate void ErrorMsgProc (int line, int col, string msg); |
||||||
|
|
||||||
|
public class Errors { |
||||||
|
public static int count = 0; // number of errors detected |
||||||
|
public static ErrorCodeProc SynErr = new ErrorCodeProc(DefaultCodeError); // syntactic errors |
||||||
|
public static ErrorCodeProc SemErr = new ErrorCodeProc(DefaultCodeError); // semantic errors |
||||||
|
public static ErrorMsgProc Error = new ErrorMsgProc(DefaultMsgError); // user defined string based errors |
||||||
|
public static StringBuilder errorText = new StringBuilder(); |
||||||
|
|
||||||
|
public static void Exception (string s) { |
||||||
|
Console.WriteLine(s); |
||||||
|
System.Environment.Exit(0); |
||||||
|
} |
||||||
|
|
||||||
|
static void DefaultCodeError (int line, int col, int n) { |
||||||
|
errorText.Append(String.Format("-- line {0} col {1}: error {2}", line, col, n)); |
||||||
|
errorText.Append("\n"); |
||||||
|
count++; |
||||||
|
} |
||||||
|
|
||||||
|
static void DefaultMsgError (int line, int col, string s) { |
||||||
|
errorText.Append(String.Format("-- line {0} col {1}: {2}", line, col, s)); |
||||||
|
errorText.Append("\n"); |
||||||
|
count++; |
||||||
|
} |
||||||
|
} // Errors |
||||||
|
|
||||||
|
$$$ |
||||||
@ -0,0 +1,59 @@ |
|||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||||
|
<PropertyGroup> |
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
||||||
|
<SchemaVersion>2.0</SchemaVersion> |
||||||
|
<ProjectGuid>{47D8A4A2-BBD9-4E24-85DC-A287383F7C42}</ProjectGuid> |
||||||
|
<RootNamespace>NewProject</RootNamespace> |
||||||
|
<AssemblyName>SharpCoco</AssemblyName> |
||||||
|
<OutputType>Exe</OutputType> |
||||||
|
<WarningLevel>4</WarningLevel> |
||||||
|
<RunPostBuildEvent>OnSuccessfulBuild</RunPostBuildEvent> |
||||||
|
<NoStdLib>False</NoStdLib> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
||||||
|
<DebugSymbols>true</DebugSymbols> |
||||||
|
<Optimize>True</Optimize> |
||||||
|
<AllowUnsafeBlocks>False</AllowUnsafeBlocks> |
||||||
|
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow> |
||||||
|
<OutputPath>..\bin\Debug\</OutputPath> |
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> |
||||||
|
<DebugType>Full</DebugType> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
||||||
|
<DebugSymbols>True</DebugSymbols> |
||||||
|
<Optimize>True</Optimize> |
||||||
|
<AllowUnsafeBlocks>False</AllowUnsafeBlocks> |
||||||
|
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow> |
||||||
|
<OutputPath>..\bin\Release\</OutputPath> |
||||||
|
<TreatWarningsAsErrors>True</TreatWarningsAsErrors> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' "> |
||||||
|
<RegisterForComInterop>False</RegisterForComInterop> |
||||||
|
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies> |
||||||
|
<BaseAddress>4194304</BaseAddress> |
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget> |
||||||
|
<FileAlignment>4096</FileAlignment> |
||||||
|
</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> |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
||||||
|
<StartArguments>CS.ATG</StartArguments> |
||||||
|
</PropertyGroup> |
||||||
|
</Project> |
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,37 @@ |
|||||||
|
using System; |
||||||
|
using System.IO; |
||||||
|
|
||||||
|
namespace at.jku.ssw.Coco { |
||||||
|
|
||||||
|
class Trace { |
||||||
|
const string FILENAME = "trace.txt"; |
||||||
|
static StreamWriter trace; |
||||||
|
|
||||||
|
public static void Init (String dir) { |
||||||
|
FileStream s; |
||||||
|
try { |
||||||
|
s = new FileStream(dir + FILENAME, FileMode.Create); /* AW use FILENAME */ |
||||||
|
trace = new StreamWriter(s); |
||||||
|
} catch (IOException) { |
||||||
|
Errors.Exception("-- could not open trace file"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
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 () { trace.Close(); } |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue