Browse Source

added SharpCoco source code

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1980 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Markus Palme 19 years ago
parent
commit
9b8e8de67b
  1. BIN
      src/Libraries/NRefactory/Project/Src/Parser/Frames/SharpCoco.exe
  2. 16
      src/Tools/SharpCoco/SharpCoco.sln
  3. 14
      src/Tools/SharpCoco/readme.txt
  4. 32
      src/Tools/SharpCoco/src/AssemblyInfo.cs
  5. 432
      src/Tools/SharpCoco/src/Coco.atg
  6. 71
      src/Tools/SharpCoco/src/Coco.cs
  7. 889
      src/Tools/SharpCoco/src/DFA.cs
  8. 764
      src/Tools/SharpCoco/src/Parser.cs
  9. 120
      src/Tools/SharpCoco/src/Parser.frame
  10. 430
      src/Tools/SharpCoco/src/ParserGen.cs
  11. 688
      src/Tools/SharpCoco/src/Scanner.cs
  12. 222
      src/Tools/SharpCoco/src/Scanner.frame
  13. 59
      src/Tools/SharpCoco/src/SharpCoco.csproj
  14. 5
      src/Tools/SharpCoco/src/SharpCoco.csproj.user
  15. 1068
      src/Tools/SharpCoco/src/Tab.cs
  16. 37
      src/Tools/SharpCoco/src/Trace.cs

BIN
src/Libraries/NRefactory/Project/Src/Parser/Frames/SharpCoco.exe

Binary file not shown.

16
src/Tools/SharpCoco/SharpCoco.sln

@ -0,0 +1,16 @@ @@ -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

14
src/Tools/SharpCoco/readme.txt

@ -0,0 +1,14 @@ @@ -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

32
src/Tools/SharpCoco/src/AssemblyInfo.cs

@ -0,0 +1,32 @@ @@ -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("")]

432
src/Tools/SharpCoco/src/Coco.atg

@ -0,0 +1,432 @@ @@ -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.

71
src/Tools/SharpCoco/src/Coco.cs

@ -0,0 +1,71 @@ @@ -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

889
src/Tools/SharpCoco/src/DFA.cs

@ -0,0 +1,889 @@ @@ -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

764
src/Tools/SharpCoco/src/Parser.cs

@ -0,0 +1,764 @@ @@ -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
}

120
src/Tools/SharpCoco/src/Parser.frame

@ -0,0 +1,120 @@ @@ -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
$$$

430
src/Tools/SharpCoco/src/ParserGen.cs

@ -0,0 +1,430 @@ @@ -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

688
src/Tools/SharpCoco/src/Scanner.cs

@ -0,0 +1,688 @@ @@ -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
}

222
src/Tools/SharpCoco/src/Scanner.frame

@ -0,0 +1,222 @@ @@ -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
$$$

59
src/Tools/SharpCoco/src/SharpCoco.csproj

@ -0,0 +1,59 @@ @@ -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>

5
src/Tools/SharpCoco/src/SharpCoco.csproj.user

@ -0,0 +1,5 @@ @@ -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>

1068
src/Tools/SharpCoco/src/Tab.cs

File diff suppressed because it is too large Load Diff

37
src/Tools/SharpCoco/src/Trace.cs

@ -0,0 +1,37 @@ @@ -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…
Cancel
Save