Click here to Skip to main content
15,891,951 members
Articles / Programming Languages / C#

Coco Custom Tool for Visual Studio.NET

Rate me:
Please Sign up or sign in to vote.
4.64/5 (34 votes)
29 Oct 2005CPOL4 min read 131.2K   698   53  
Use the award winning Coco compiler's compiler directly from within Visual Studio
// Compiled by vsCoco on 29/10/2005 16:32:55
/*----------------------------------------------------------------------
Compiler Generator Coco/R,
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
extended by M. Loeberbauer & A. Woess, Univ. of Linz
with improvements by Pat Terry, Rhodes University

This program is free software; you can redistribute it and/or modify it 
under the terms of the GNU General Public License as published by the 
Free Software Foundation; either version 2, or (at your option) any 
later version.

This program is distributed in the hope that it will be useful, but 
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
for more details.

You should have received a copy of the GNU General Public License along 
with this program; if not, write to the Free Software Foundation, Inc., 
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

As an exception, it is allowed to write an extension of Coco/R that is
used as a plugin in non-free software.

If not otherwise stated, any source code generated by Coco/R (other than 
Coco/R itself) does not fall under the GNU General Public License.
----------------------------------------------------------------------*/

//------------------------------------------------------------------------------
// <autogenerated>
//     This code was generated by COCO from Parser.frame.
//     Changes to this file may cause incorrect behavior and will be lost if 
//     the code is regenerated.
// </autogenerated>
//------------------------------------------------------------------------------

using System;
using System.IO;
using System.Collections;

namespace Calculator {


	public class Parser {
	const int _EOF = 0;
	const int _number = 1;
	const int maxT = 8;

		const bool T = true;
		const bool x = false;
		const int minErrDist = 2;
		
		public Scanner scanner;
		public Errors  errors;

		public Token t;    // last recognized token
		public Token la;   // lookahead token
		int errDist = minErrDist;


#line hidden
public double result = 0;
 

#line hidden

		public Parser(Scanner scanner) {
			this.scanner = scanner;
			errors = new Errors(scanner);
		}

		public Parser(System.IO.Stream str) {
			scanner = new Scanner(str);
			errors = new Errors(scanner);
		}
		
		public Parser(string source) {
			MemoryStream memIn = new MemoryStream();
			byte[] b=System.Text.Encoding.ASCII.GetBytes(source);
			memIn.Write(b,0,b.Length);
			memIn.Seek(0,0);
			this.scanner = new Scanner(memIn);
			errors = new Errors(scanner);
		}

		void SynErr (int n) {
			if (errDist >= minErrDist) errors.SynErr(la.line, la.col, n);
			errDist = 0;
		}

		public void SemErr (string msg) {
			if (errDist >= minErrDist) errors.Error(t.line, t.col, msg);
			errDist = 0;
		}
		
		void Get () {
			for (;;) {
				t = la;
				la = scanner.Scan();
				if (la.kind <= maxT) { ++errDist; break; }

				la = t;
			}
		}
		
		void Expect (int n) {
			if (la.kind==n) Get(); else { SynErr(n); }
		}
		
		bool StartOf (int s) {
			return set[s, la.kind];
		}
		
		void ExpectWeak (int n, int follow) {
			if (la.kind == n) Get();
			else {
				SynErr(n);
				while (!StartOf(follow)) Get();
			}
		}
		
		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);
			}
		}
		
	void OPERAND(
#line 31 "C:\dotnet\vsCoco\Calculator\Calc.atg"
        out double val
#line hidden
) {

#line 32 "C:\dotnet\vsCoco\Calculator\Calc.atg"
            val = 0; 
#line hidden

		if (la.kind == 1) {
			Get();

#line 34 "C:\dotnet\vsCoco\Calculator\Calc.atg"
                 val = Double.Parse(t.val,
									System.Globalization.NumberStyles.Float, 
									System.Globalization.CultureInfo.InvariantCulture); 
							
#line hidden

		} else if (la.kind == 2) {
			Get();
			EXPR(
#line 38 "C:\dotnet\vsCoco\Calculator\Calc.atg"
             out val
#line hidden
);
			Expect(3);
		} else SynErr(9);
	}

	void EXPR(
#line 76 "C:\dotnet\vsCoco\Calculator\Calc.atg"
     out double val
#line hidden
) {
		EXPR09(
#line 78 "C:\dotnet\vsCoco\Calculator\Calc.atg"
        out val
#line hidden
);
		while (la.kind == 4 || la.kind == 5) {

#line 79 "C:\dotnet\vsCoco\Calculator\Calc.atg"
           double val2; 
#line hidden

			if (la.kind == 5) {
				Get();
				EXPR09(
#line 81 "C:\dotnet\vsCoco\Calculator\Calc.atg"
         out val2
#line hidden
);

#line 81 "C:\dotnet\vsCoco\Calculator\Calc.atg"
                      val+=val2; 
#line hidden

			} else {
				Get();
				EXPR09(
#line 83 "C:\dotnet\vsCoco\Calculator\Calc.atg"
         out val2
#line hidden
);

#line 83 "C:\dotnet\vsCoco\Calculator\Calc.atg"
                      val-=val2; 
#line hidden

			}
		}
	}

	void EXPR10(
#line 50 "C:\dotnet\vsCoco\Calculator\Calc.atg"
       out double val
#line hidden
) {

#line 51 "C:\dotnet\vsCoco\Calculator\Calc.atg"
                           bool neg=false; 
#line hidden

		while (la.kind == 4 || la.kind == 5) {
			if (la.kind == 4) {
				Get();

#line 53 "C:\dotnet\vsCoco\Calculator\Calc.atg"
             neg=!neg; 
#line hidden

			} else {
				Get();

#line 54 "C:\dotnet\vsCoco\Calculator\Calc.atg"
                               
#line hidden

			}
		}
		OPERAND(
#line 57 "C:\dotnet\vsCoco\Calculator\Calc.atg"
         out val
#line hidden
);

#line 57 "C:\dotnet\vsCoco\Calculator\Calc.atg"
                     if (neg) val*=-1; 
#line hidden

	}

	void EXPR09(
#line 62 "C:\dotnet\vsCoco\Calculator\Calc.atg"
       out double val
#line hidden
) {
		EXPR10(
#line 64 "C:\dotnet\vsCoco\Calculator\Calc.atg"
        out val
#line hidden
);
		while (la.kind == 6 || la.kind == 7) {

#line 65 "C:\dotnet\vsCoco\Calculator\Calc.atg"
           double val2; 
#line hidden

			if (la.kind == 6) {
				Get();
				EXPR10(
#line 67 "C:\dotnet\vsCoco\Calculator\Calc.atg"
         out val2
#line hidden
);

#line 67 "C:\dotnet\vsCoco\Calculator\Calc.atg"
                      val*=val2; 
#line hidden

			} else {
				Get();
				EXPR10(
#line 69 "C:\dotnet\vsCoco\Calculator\Calc.atg"
         out val2
#line hidden
);

#line 69 "C:\dotnet\vsCoco\Calculator\Calc.atg"
                      val/=val2; 
#line hidden

			}
		}
	}

	void calc() {
		EXPR(
#line 92 "C:\dotnet\vsCoco\Calculator\Calc.atg"
      out result
#line hidden
);
	}


		public void Parse() {
			la = new Token();
			la.val = "";		
			Get();
		calc();

		Expect(0);
		}
		
		bool[,] set = {
		{T,x,x,x, x,x,x,x, x,x}

		};
	} // end Parser


	public class Errors {
		public int count = 0;                                    // number of errors detected
		public string errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
		private Scanner scanner;

		public Errors(Scanner scanner)
		{
			this.scanner=scanner;
		}
		
		public void SynErr (int line, int col, int n) {
			string s;
			switch (n) {
			case 0: s = "EOF expected"; break;
			case 1: s = "number expected"; break;
			case 2: s = "\"(\" expected"; break;
			case 3: s = "\")\" expected"; break;
			case 4: s = "\"-\" expected"; break;
			case 5: s = "\"+\" expected"; break;
			case 6: s = "\"*\" expected"; break;
			case 7: s = "\"/\" expected"; break;
			case 8: s = "??? expected"; break;
			case 9: s = "invalid OPERAND"; break;

				default: s = "error " + n; break;
			}
			Error(line, col, s);
		}

		public virtual void Error (int lin, int col, string err) {
			scanner.WriteError(errMsgFormat,scanner.srcFile,lin,col,err);
			count++;
		}

	} // Errors

}/*----------------------------------------------------------------------
Compiler Generator Coco/R,
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
extended by M. Loeberbauer & A. Woess, Univ. of Linz
with improvements by Pat Terry, Rhodes University

This program is free software; you can redistribute it and/or modify it 
under the terms of the GNU General Public License as published by the 
Free Software Foundation; either version 2, or (at your option) any 
later version.

This program is distributed in the hope that it will be useful, but 
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
for more details.

You should have received a copy of the GNU General Public License along 
with this program; if not, write to the Free Software Foundation, Inc., 
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

As an exception, it is allowed to write an extension of Coco/R that is
used as a plugin in non-free software.

If not otherwise stated, any source code generated by Coco/R (other than 
Coco/R itself) does not fall under the GNU General Public License.
-----------------------------------------------------------------------*/

//------------------------------------------------------------------------------
// <autogenerated>
//     This code was generated by COCO from Scanner.frame.
//     Changes to this file may cause incorrect behavior and will be lost if 
//     the code is regenerated.
// </autogenerated>
//------------------------------------------------------------------------------

namespace Calculator {

	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;  // ML 2005-03-11 Tokens are kept in linked list
	}

	public class Buffer {
		public const char EOF = (char)256;
		const int MAX_BUFFER_LENGTH = 64 * 1024; // 64KB
		byte[] buf;         // input buffer
		int bufStart;       // position of first byte in buffer relative to input stream
		int bufLen;         // length of buffer
		int fileLen;        // length of input stream
		int pos;            // current position in buffer
		Stream stream;      // input stream (seekable)
		bool isUserStream;  // was the stream opened by the user?
		
		public Buffer (Stream s, bool isUserStream) {
			stream = s; this.isUserStream = isUserStream;
			fileLen = bufLen = (int) s.Length;
			if (stream.CanSeek && bufLen > MAX_BUFFER_LENGTH) bufLen = MAX_BUFFER_LENGTH;
			buf = new byte[bufLen];
			bufStart = Int32.MaxValue; // nothing in the buffer so far
			Pos = 0; // setup buffer to position 0 (start)
			if (bufLen == fileLen) Close();
		}
		
		~Buffer() { Close(); }
		
		void Close() {
			if (!isUserStream && stream != null) {
				stream.Close();
				stream = null;
			}
		}
		
		public int Read () {
			if (pos < bufLen) {
				return buf[pos++];
			} else if (Pos < fileLen) {
				Pos = Pos; // shift buffer start to Pos
				return buf[pos++];
			} else {
				return EOF;
			}
		}

		public int Peek () {
			if (pos < bufLen) {
				return buf[pos];
			} else if (Pos < fileLen) {
				Pos = Pos; // shift buffer start to Pos
				return buf[pos];
			} else {
				return EOF;
			}
		}
		
		public string GetString (int beg, int end) {
			int len = end - beg;
			char[] buf = new char[len];
			int oldPos = Pos;
			Pos = beg;
			for (int i = 0; i < len; i++) buf[i] = (char) Read();
			Pos = oldPos;
			return new String(buf);
		}

		public int Pos {
			get { return pos + bufStart; }
			set {
				if (value < 0) value = 0; 
				else if (value > fileLen) value = fileLen;
				if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
					pos = value - bufStart;
				} else if (stream != null) { // must be swapped in
					stream.Seek(value, SeekOrigin.Begin);
					bufLen = stream.Read(buf, 0, buf.Length);
					bufStart = value; pos = 0;
				} else {
					pos = fileLen - bufStart; // make Pos return fileLen
				}
			}
		}
	}

	public class Scanner {
		const char EOL = '\n';
		const int eofSym = 0; /* pdt */
	const int charSetSize = 256;
	const int maxT = 8;
	const int noSym = 8;
	short[] start = {
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  3,  4,  7,  6,  0,  5,  0,  8,
	  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  -1};
	char valCh;       // current input character (for token.val)

		public Buffer buffer; // scanner buffer
		public string srcFile;
		
		Token t;          // current token
		char ch;          // current input character
		int pos;          // column number of current character
		int line;         // line number of current character
		int lineStart;    // start position of current line
		int oldEols;      // EOLs that appeared in a comment;
		BitArray ignore;  // set of characters to be ignored by the scanner
		Token tokens;     // list of tokens already peeked (first token is a dummy)
		Token pt;         // current peek token
		
		char[] tval = new char[128]; // text of current token
		int tlen;         // length of current token
		
		public Scanner (string fileName) {
			srcFile=fileName;
			try {
				Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
				buffer = new Buffer(stream, false);
				Init();
			} catch (IOException) {
				throw new Exception(String.Format("--- Cannot open file {0}", fileName));
			}
		}
		
		public Scanner (Stream s) {
			buffer = new Buffer(s, true);
			Init();
		}
		
		public virtual void WriteLine(string s) 
		{
			Console.WriteLine(s);
		}
		
		public virtual void Write(string s) 
		{
			Console.Write(s);
		}
		
		public virtual void WriteError(string fmt,string file, int lin, int col, string err)
		{
			Console.WriteLine(string.Format(fmt,new object[] {file, lin, col, err}));
		}

		
		void Init() {
			pos = -1; line = 1; lineStart = 0;
			oldEols = 0;
			NextCh();
			ignore = new BitArray(charSetSize+1);
			ignore[' '] = true;  // blanks are always white space
		ignore[9] = true; ignore[10] = true; ignore[13] = true; 
			pt = tokens = new Token();  // first token is a dummy
		}
		
		void NextCh() {
			if (oldEols > 0) { ch = EOL; oldEols--; } 
			else {
				ch = (char)buffer.Read(); pos++;
				// replace isolated '\r' by '\n' in order to make
				// eol handling uniform across Windows, Unix and Mac
				if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
				if (ch == EOL) { line++; lineStart = pos + 1; }
			}
		valCh = ch;
		if (ch != Buffer.EOF) ch = char.ToLower(ch);
		}

		void AddCh() {
			if (tlen >= tval.Length) {
				char[] newBuf = new char[2 * tval.Length];
				Array.Copy(tval, 0, newBuf, 0, tval.Length);
				tval = newBuf;
			}
		tval[tlen++] = valCh;
			NextCh();
		}



	bool Comment0() {
		int level = 1, line0 = line, lineStart0 = lineStart;
		NextCh();
		if (ch == '/') {
			NextCh();
			for(;;) {
				if (ch == 13) {
					NextCh();
					if (ch == 10) {
						level--;
						if (level == 0) { oldEols = line - line0; NextCh(); return true; }
						NextCh();
					}
				} else if (ch == Buffer.EOF) return false;
				else NextCh();
			}
		} else {
			if (ch==EOL) {line--; lineStart = lineStart0;}
			pos = pos - 2; buffer.Pos = pos+1; NextCh();
		}
		return false;
	}


		void CheckLiteral() {
		switch (t.val.ToLower()) {
			default: break;
		}
		}

		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];
			tlen = 0; AddCh();
			
			switch (state) {
				case -1: { t.kind = eofSym; break; } // NextCh already done
				case 0: { t.kind = noSym; break; }   // NextCh already done
			case 1:
				if ((ch >= '0' && ch <= '9')) {AddCh(); goto case 1;}
				else if (ch == '.') {AddCh(); goto case 2;}
				else {t.kind = 1; break;}
			case 2:
				if ((ch >= '0' && ch <= '9')) {AddCh(); goto case 2;}
				else {t.kind = 1; break;}
			case 3:
				{t.kind = 2; break;}
			case 4:
				{t.kind = 3; break;}
			case 5:
				{t.kind = 4; break;}
			case 6:
				{t.kind = 5; break;}
			case 7:
				{t.kind = 6; break;}
			case 8:
				{t.kind = 7; break;}

			}
			t.val = new String(tval, 0, tlen);
			return t;
		}
		
		// get the next token (possibly a token already seen during peeking)
		public Token Scan () {
			if (tokens.next == null) {
				return NextToken();
			} else {
				pt = tokens = tokens.next;
				return tokens;
			}
		}

		// peek for the next token, ignore pragmas
		public Token Peek () {
			if (pt.next == null) {
				do {
					pt = pt.next = NextToken();
				} while (pt.kind > maxT); // skip pragmas
			} else {
				do {
					pt = pt.next;
				} while (pt.kind > maxT);
			}
			return pt;
		}
		
		// make sure that peeking starts at the current scan position
		public void ResetPeek () { pt = tokens; }

	} // end Scanner

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
France France
I am a French programmer.
These days I spend most of my time with the .NET framework, JavaScript and html.

Comments and Discussions