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

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

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

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

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

If not otherwise stated, any source code generated by Coco/R (other than
Coco/R itself) does not fall under the GNU General Public License.
----------------------------------------------------------------------*/
-->begin
/* This file (Parser.cs) is generated from Dafny.atg by the Coco/R
 * parser generator. Do not edit this file directly. Instead, make
 * changes to Dafny.atg and then rebuild using the Makefile found
 * in the same directory as Dafny.atg.
 */

using System;
using System.Diagnostics.Contracts;
using System.Threading;

-->namespace

public partial class Parser {
-->constants
  const bool _T = true;
  const bool _x = false;
  const int minErrDist = 2;

  public Scanner scanner;
  public Errors  errors;
  CancellationToken cancellationToken;

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

-->declarations

  public Parser(Scanner scanner, Errors errors, CancellationToken cancellationToken) {
    this.scanner = scanner;
    this.errors = errors;
    this.cancellationToken = cancellationToken;
    this.la = scanner.FirstToken;
    this.t = scanner.FirstToken; // just to satisfy its non-null constraint
  }

  void SynErr (int n) {
    if (errDist >= minErrDist) {
      errors.SynErr(la.Uri, la.line, la.col, n);
    }
    errDist = 0;
  }
  
  public void SemErr(Enum errorId, IOrigin tok, string msg) {
    Contract.Requires(tok != null);
    Contract.Requires(msg != null);
    errors.SemErr(errorId, tok, msg);
  }

  void Get() {
    cancellationToken.ThrowIfCancellationRequested();
    for (; ; ) {
      var tmp = la;
      la = scanner.Scan();
      tmp.Next = la;
      la.Prev = tmp;
      t = tmp;
      if (la.kind <= maxT) { 
        ++errDist; 
        break;
      }
-->pragmas
      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) {
    int kind = la.kind;
    if (kind == n) {Get(); return true;}
    else if (StartOf(repFol)) {return false;}
    else {
      SynErr(n);
      while (!(set[syFol, kind] || set[repFol, kind] || set[0, kind])) {
        Get();
        kind = la.kind;
      }
      return StartOf(syFol);
    }
  }


-->productions

  public void Parse() {
    la = scanner.FirstToken;
    Get();
-->parseRoot
  }

  static readonly bool[,] set = {
-->initialization
  };
} // end Parser


public class Errors {
  public readonly ErrorReporter Reporting;
  public int ErrorCount;

  public Errors(ErrorReporter Reporting) {
    Contract.Requires(Reporting != null);
    this.Reporting = Reporting;
  }

  public void SynErr(Uri uri, int line, int col, int n) {
    SynErr(uri, line, col, GetSyntaxErrorString(n));
  }

  public void SynErr(Uri uri, int line, int col, string msg) {
    Contract.Requires(msg != null);
    ErrorCount++;
    Reporting.Error(MessageSource.Parser, ErrorId.p_generic_syntax_error, uri, line, col, msg);
  }

  string GetSyntaxErrorString(int n) {
    string s;
    switch (n) {
-->errors
      default: s = "error " + n; break;
    }
    return s;
  }

  public void SemErr(string errorId, IOrigin tok, string msg) {  // semantic errors
    Contract.Requires(tok != null);
    Contract.Requires(msg != null);
    ErrorCount++;
    Reporting.Error(MessageSource.Parser, errorId, tok, msg);
  }
  
  public void SemErr(Enum errorId, IOrigin tok, string msg) {  // semantic errors
    Contract.Requires(tok != null);
    Contract.Requires(msg != null);
    ErrorCount++;
    Reporting.Error(MessageSource.Parser, errorId, tok, msg);
  }

  public void SemErr(ErrorId errorId, Uri uri, int line, int col, string msg) {
    Contract.Requires(msg != null);
    ErrorCount++;
    Reporting.Error(MessageSource.Parser, errorId, uri, line, col, msg);
  }

  public void Deprecated(Enum errorId, IOrigin tok, string msg) {
    Contract.Requires(tok != null);
    Contract.Requires(msg != null);
    Reporting.Deprecated(MessageSource.Parser, errorId, tok, msg);
  }

  public void Warning(ErrorId errorId, IOrigin tok, string msg) {
    Contract.Requires(tok != null);
    Contract.Requires(msg != null);
    Reporting.Warning(MessageSource.Parser, errorId, tok, msg);
  }

} // Errors


public class FatalError: Exception {
  public FatalError(string m): base(m) {}
}
