//-----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All Rights Reserved.
//
//-----------------------------------------------------------------------------
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Microsoft.Contracts;
using Bpl = Microsoft.Boogie;
using BoogiePL;
namespace Microsoft.Dafny {
[Immutable]
public class Token : Bpl.Token {
public Token();
public Token(int linenum, int colnum) {
base(linenum, colnum);
}
public new static Token! NoToken = new Token();
}
}
namespace Microsoft.Dafny {
public class Scanner {
const char EOF = '\0';
const char CR = '\r';
const char LF = '\n';
[Microsoft.Contracts.Verify(false)]
static Scanner() {
start[0] = 50;
start[33] = 31;
start[34] = 3;
start[37] = 40;
start[38] = 25;
start[39] = 1;
start[40] = 12;
start[41] = 13;
start[42] = 15;
start[43] = 37;
start[44] = 7;
start[45] = 38;
start[46] = 44;
start[47] = 39;
start[48] = 2;
start[49] = 2;
start[50] = 2;
start[51] = 2;
start[52] = 2;
start[53] = 2;
start[54] = 2;
start[55] = 2;
start[56] = 2;
start[57] = 2;
start[58] = 9;
start[59] = 8;
start[60] = 10;
start[61] = 21;
start[62] = 11;
start[63] = 1;
start[65] = 1;
start[66] = 1;
start[67] = 1;
start[68] = 1;
start[69] = 1;
start[70] = 1;
start[71] = 1;
start[72] = 1;
start[73] = 1;
start[74] = 1;
start[75] = 1;
start[76] = 1;
start[77] = 1;
start[78] = 1;
start[79] = 1;
start[80] = 1;
start[81] = 1;
start[82] = 1;
start[83] = 1;
start[84] = 1;
start[85] = 1;
start[86] = 1;
start[87] = 1;
start[88] = 1;
start[89] = 1;
start[90] = 1;
start[91] = 42;
start[92] = 1;
start[93] = 43;
start[95] = 1;
start[96] = 1;
start[97] = 1;
start[98] = 1;
start[99] = 1;
start[100] = 1;
start[101] = 1;
start[102] = 1;
start[103] = 1;
start[104] = 1;
start[105] = 1;
start[106] = 1;
start[107] = 1;
start[108] = 1;
start[109] = 1;
start[110] = 1;
start[111] = 1;
start[112] = 1;
start[113] = 1;
start[114] = 1;
start[115] = 1;
start[116] = 1;
start[117] = 1;
start[118] = 1;
start[119] = 1;
start[120] = 1;
start[121] = 1;
start[122] = 1;
start[123] = 5;
start[124] = 16;
start[125] = 6;
start[172] = 41;
start[8226] = 49;
start[8658] = 24;
start[8660] = 20;
start[8704] = 46;
start[8707] = 47;
start[8743] = 27;
start[8744] = 29;
start[8800] = 34;
start[8804] = 35;
start[8805] = 36;
}
const int noSym = 86;
static short[] start = new short[16385];
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 Queue! oldEols; // EOLs that appeared in a comment;
static BitArray/*!*/ ignore; // set of characters to be ignored by the scanner
static string Filename;
///
///Initializes the scanner. Note: first fill the Buffer.
///
///File name used for error reporting
public static void Init (string filename) {
Filename = filename;
pos = -1; line = 1; lineStart = 0;
oldEols = new Queue();
NextCh();
ignore = new BitArray(16384);
ignore[9] = true; ignore[10] = true; ignore[13] = true; ignore[32] = true;
}
private static void NextCh() {
if (oldEols.Count > 0) {
ch = (char) ((!)oldEols.Dequeue());
} else {
while (true) {
ch = (char)BoogiePL.Buffer.Read(); pos++;
if (ch == BoogiePL.Buffer.eof) {
ch = EOF;
} else if (ch == LF) {
line++;
lineStart = pos + 1;
} else if (ch == '#' && pos == lineStart) {
int prLine = line;
int prColumn = pos - lineStart; // which is 0
string hashLine = BoogiePL.Buffer.ReadToEOL(); pos += hashLine.Length;
line++;
lineStart = pos + 1;
hashLine = hashLine.TrimEnd(null);
if (hashLine.StartsWith("line ") || hashLine == "line") {
// parse #line pragma: #line num [filename]
string h = hashLine.Substring(4).TrimStart(null);
int x = h.IndexOf(' ');
if (x == -1) {
x = h.Length; // this will be convenient below when we look for a filename
}
try {
int li = int.Parse(h.Substring(0, x));
h = h.Substring(x).Trim();
// act on #line
line = li;
if (h.Length != 0) {
// a filename was specified
Filename = h;
}
continue; // successfully parsed and acted on the #line pragma
} catch (System.FormatException) {
// just fall down through to produce an error message
}
Errors.SemErr(Filename, prLine, prColumn, "Malformed (#line num [filename]) pragma: #" + hashLine);
continue;
}
Errors.SemErr(Filename, prLine, prColumn, "Unrecognized pragma: #" + hashLine);
continue;
}
return;
}
}
}
static bool Comment0() {
int level = 1, line0 = line, lineStart0 = lineStart;
NextCh();
if (ch == '/') {
NextCh();
for(;;) {
if (ch == 10) {
level--;
if (level == 0) {
while(line0 < line) {oldEols.Enqueue('\r'); oldEols.Enqueue('\n'); line0++;}
NextCh(); return true;
}
NextCh();
} else if (ch == EOF) return false;
else NextCh();
}
} else {
if (ch==CR) {line--; lineStart = lineStart0;}
pos = pos - 2; Buffer.Pos = pos+1; NextCh();
}
return false;
}
static bool Comment1() {
int level = 1, line0 = line, lineStart0 = lineStart;
NextCh();
if (ch == '*') {
NextCh();
for(;;) {
if (ch == '*') {
NextCh();
if (ch == '/') {
level--;
if (level == 0) {
while(line0 < line) {oldEols.Enqueue('\r'); oldEols.Enqueue('\n'); line0++;}
NextCh(); return true;
}
NextCh();
}
} else if (ch == '/') {
NextCh();
if (ch == '*') {
level++; NextCh();
}
} else if (ch == EOF) return false;
else NextCh();
}
} else {
if (ch==CR) {line--; lineStart = lineStart0;}
pos = pos - 2; Buffer.Pos = pos+1; NextCh();
}
return false;
}
static void CheckLiteral() {
switch (t.val) {
case "class": t.kind = 4; break;
case "var": t.kind = 7; break;
case "frame": t.kind = 13; break;
case "method": t.kind = 14; break;
case "returns": t.kind = 15; break;
case "modifies": t.kind = 16; break;
case "free": t.kind = 17; break;
case "requires": t.kind = 18; break;
case "ensures": t.kind = 19; break;
case "bool": t.kind = 22; break;
case "int": t.kind = 23; break;
case "object": t.kind = 24; break;
case "set": t.kind = 25; break;
case "seq": t.kind = 26; break;
case "function": t.kind = 27; break;
case "use": t.kind = 28; break;
case "reads": t.kind = 29; break;
case "if": t.kind = 30; break;
case "else": t.kind = 31; break;
case "label": t.kind = 32; break;
case "break": t.kind = 33; break;
case "return": t.kind = 34; break;
case "new": t.kind = 36; break;
case "havoc": t.kind = 37; break;
case "while": t.kind = 38; break;
case "invariant": t.kind = 39; break;
case "decreases": t.kind = 40; break;
case "call": t.kind = 42; break;
case "foreach": t.kind = 43; break;
case "in": t.kind = 44; break;
case "assert": t.kind = 46; break;
case "assume": t.kind = 47; break;
case "false": t.kind = 70; break;
case "true": t.kind = 71; break;
case "null": t.kind = 72; break;
case "fresh": t.kind = 73; break;
case "this": t.kind = 78; break;
case "old": t.kind = 79; break;
case "forall": t.kind = 80; break;
case "exists": t.kind = 82; break;
default: break;
}
}
public static Token/*!*/ Scan() {
while (ignore[ch]) { NextCh(); }
if (ch == '/' && Comment0() || ch == '/' && Comment1() ) return Scan();
t = new Token();
t.pos = pos; t.col = pos - lineStart + 1; t.line = line; t.filename = Filename;
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 == 39 || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == 92 || ch >= '_' && 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:
if ((ch == '"')) {buf.Append(ch); NextCh(); goto case 4;}
else if ((ch >= ' ' && ch <= '!' || ch >= '#' && ch <= '~')) {buf.Append(ch); NextCh(); goto case 3;}
else {t.kind = noSym; goto done;}
case 4:
{t.kind = 3; goto done;}
case 5:
{t.kind = 5; goto done;}
case 6:
{t.kind = 6; goto done;}
case 7:
{t.kind = 8; goto done;}
case 8:
{t.kind = 9; goto done;}
case 9:
if (ch == '=') {buf.Append(ch); NextCh(); goto case 14;}
else if (ch == ':') {buf.Append(ch); NextCh(); goto case 48;}
else {t.kind = 10; goto done;}
case 10:
if (ch == '=') {buf.Append(ch); NextCh(); goto case 17;}
else {t.kind = 11; goto done;}
case 11:
if (ch == '=') {buf.Append(ch); NextCh(); goto case 30;}
else {t.kind = 12; goto done;}
case 12:
{t.kind = 20; goto done;}
case 13:
{t.kind = 21; goto done;}
case 14:
{t.kind = 35; goto done;}
case 15:
{t.kind = 41; goto done;}
case 16:
if (ch == '|') {buf.Append(ch); NextCh(); goto case 28;}
else {t.kind = 45; goto done;}
case 17:
if (ch == '=') {buf.Append(ch); NextCh(); goto case 18;}
else {t.kind = 57; goto done;}
case 18:
if (ch == '>') {buf.Append(ch); NextCh(); goto case 19;}
else {t.kind = noSym; goto done;}
case 19:
{t.kind = 48; goto done;}
case 20:
{t.kind = 49; goto done;}
case 21:
if (ch == '=') {buf.Append(ch); NextCh(); goto case 22;}
else {t.kind = noSym; goto done;}
case 22:
if (ch == '>') {buf.Append(ch); NextCh(); goto case 23;}
else {t.kind = 56; goto done;}
case 23:
{t.kind = 50; goto done;}
case 24:
{t.kind = 51; goto done;}
case 25:
if (ch == '&') {buf.Append(ch); NextCh(); goto case 26;}
else {t.kind = noSym; goto done;}
case 26:
{t.kind = 52; goto done;}
case 27:
{t.kind = 53; goto done;}
case 28:
{t.kind = 54; goto done;}
case 29:
{t.kind = 55; goto done;}
case 30:
{t.kind = 58; goto done;}
case 31:
if (ch == '=') {buf.Append(ch); NextCh(); goto case 32;}
else if (ch == '!') {buf.Append(ch); NextCh(); goto case 33;}
else {t.kind = 68; goto done;}
case 32:
{t.kind = 59; goto done;}
case 33:
{t.kind = 60; goto done;}
case 34:
{t.kind = 61; goto done;}
case 35:
{t.kind = 62; goto done;}
case 36:
{t.kind = 63; goto done;}
case 37:
{t.kind = 64; goto done;}
case 38:
{t.kind = 65; goto done;}
case 39:
{t.kind = 66; goto done;}
case 40:
{t.kind = 67; goto done;}
case 41:
{t.kind = 69; goto done;}
case 42:
{t.kind = 74; goto done;}
case 43:
{t.kind = 75; goto done;}
case 44:
if (ch == '.') {buf.Append(ch); NextCh(); goto case 45;}
else {t.kind = 76; goto done;}
case 45:
{t.kind = 77; goto done;}
case 46:
{t.kind = 81; goto done;}
case 47:
{t.kind = 83; goto done;}
case 48:
{t.kind = 84; goto done;}
case 49:
{t.kind = 85; goto done;}
case 50: {t.kind = 0; goto done;}
}
done:
t.val = buf.ToString();
return t;
}
} // end Scanner
public delegate void ErrorProc(int n, string filename, int line, int col);
public class Errors {
public static int count = 0; // number of errors detected
public static ErrorProc/*!*/ SynErr; // syntactic errors
public static void SemErr(string filename, int line, int col, string! msg) { // semantic errors
System.ConsoleColor color = System.Console.ForegroundColor;
System.Console.ForegroundColor = System.ConsoleColor.Red;
System.Console.WriteLine("{0}({1},{2}): Error: {3}", filename, line, col, msg);
System.Console.ForegroundColor = color;
count++;
}
public static void SemErr(Bpl.IToken! tok, string! msg) { // semantic errors
SemErr(tok.filename, tok.line, tok.col, msg);
}
public static void Exception (string s) {
System.ConsoleColor color = System.Console.ForegroundColor;
System.Console.ForegroundColor = System.ConsoleColor.Red;
System.Console.WriteLine(s);
System.Console.ForegroundColor = color;
System.Environment.Exit(0);
}
} // Errors
} // end namespace