context: // Generated by TinyPG v1.3 available at www.codeproject.com
  
  using System;
  using System.Collections.Generic;
  using System.Globalization;
  using System.Text.RegularExpressions;
  using System.Xml.Serialization;
  
  namespace kOS.Safe.Compilation.KS
  {
      #region Scanner
  
      public partial class Scanner
      {
          public string Input;
          public string LowerInput;
          public int StartPos = 0;
          public int EndPos = 0;
          public string CurrentFile;
          public int CurrentLine;
          public int CurrentColumn;
          public int CurrentPosition;
          public List<Token> Skipped; // tokens that were skipped
          public Dictionary<TokenType, Regex> Patterns;
  
          private Token LookAheadToken;
          private List<TokenType> Tokens;
          private List<TokenType> SkipList; // tokens to be skipped
          private readonly TokenType FileAndLine;
  
          public Scanner()
          {
              Regex regex;
              Patterns = new Dictionary<TokenType, Regex>();
              Tokens = new List<TokenType>();
              LookAheadToken = null;
              Skipped = new List<Token>();
  
              SkipList = new List<TokenType>();
              SkipList.Add(TokenType.WHITESPACE);
              SkipList.Add(TokenType.COMMENTLINE);
  
              regex = new Regex(@"\G(?:(\+|-))");
              Patterns.Add(TokenType.PLUSMINUS, regex);
              Tokens.Add(TokenType.PLUSMINUS);
  
              regex = new Regex(@"\G(?:\*)");
              Patterns.Add(TokenType.MULT, regex);
              Tokens.Add(TokenType.MULT);
  
              regex = new Regex(@"\G(?:/)");
              Patterns.Add(TokenType.DIV, regex);
              Tokens.Add(TokenType.DIV);
  
              regex = new Regex(@"\G(?:\^)");
              Patterns.Add(TokenType.POWER, regex);
              Tokens.Add(TokenType.POWER);
  
              regex = new Regex(@"\G(?:e((?=\d)|\b))");
              Patterns.Add(TokenType.E, regex);
              Tokens.Add(TokenType.E);
  
              regex = new Regex(@"\G(?:not\b)");
              Patterns.Add(TokenType.NOT, regex);
              Tokens.Add(TokenType.NOT);
  
              regex = new Regex(@"\G(?:and\b)");
              Patterns.Add(TokenType.AND, regex);
              Tokens.Add(TokenType.AND);
  
              regex = new Regex(@"\G(?:or\b)");
              Patterns.Add(TokenType.OR, regex);
              Tokens.Add(TokenType.OR);
  
              regex = new Regex(@"\G(?:true\b|\bfalse\b)");
              Patterns.Add(TokenType.TRUEFALSE, regex);
              Tokens.Add(TokenType.TRUEFALSE);
  
              regex = new Regex(@"\G(?:<>|>=|<=|=|>|<)");
              Patterns.Add(TokenType.COMPARATOR, regex);
              Tokens.Add(TokenType.COMPARATOR);
  
              regex = new Regex(@"\G(?:set\b)");
              Patterns.Add(TokenType.SET, regex);
              Tokens.Add(TokenType.SET);
  
              regex = new Regex(@"\G(?:to\b)");
              Patterns.Add(TokenType.TO, regex);
              Tokens.Add(TokenType.TO);
  
              regex = new Regex(@"\G(?:is\b)");
              Patterns.Add(TokenType.IS, regex);
              Tokens.Add(TokenType.IS);
  
              regex = new Regex(@"\G(?:if\b)");
              Patterns.Add(TokenType.IF, regex);
              Tokens.Add(TokenType.IF);
  
              regex = new Regex(@"\G(?:else\b)");
              Patterns.Add(TokenType.ELSE, regex);
              Tokens.Add(TokenType.ELSE);
  
              regex = new Regex(@"\G(?:until\b)");
              Patterns.Add(TokenType.UNTIL, regex);
              Tokens.Add(TokenType.UNTIL);
  
              regex = new Regex(@"\G(?:step\b)");
              Patterns.Add(TokenType.STEP, regex);
              Tokens.Add(TokenType.STEP);
  
              regex = new Regex(@"\G(?:do\b)");
              Patterns.Add(TokenType.DO, regex);
              Tokens.Add(TokenType.DO);
  
              regex = new Regex(@"\G(?:lock\b)");
              Patterns.Add(TokenType.LOCK, regex);
              Tokens.Add(TokenType.LOCK);
  
              regex = new Regex(@"\G(?:unlock\b)");
              Patterns.Add(TokenType.UNLOCK, regex);
              Tokens.Add(TokenType.UNLOCK);
  
              regex = new Regex(@"\G(?:print\b)");
              Patterns.Add(TokenType.PRINT, regex);
              Tokens.Add(TokenType.PRINT);
  
              regex = new Regex(@"\G(?:at\b)");
              Patterns.Add(TokenType.AT, regex);
              Tokens.Add(TokenType.AT);
  
              regex = new Regex(@"\G(?:on\b)");
              Patterns.Add(TokenType.ON, regex);
              Tokens.Add(TokenType.ON);
  
              regex = new Regex(@"\G(?:toggle\b)");
              Patterns.Add(TokenType.TOGGLE, regex);
              Tokens.Add(TokenType.TOGGLE);
  
              regex = new Regex(@"\G(?:wait\b)");
              Patterns.Add(TokenType.WAIT, regex);
              Tokens.Add(TokenType.WAIT);
  
              regex = new Regex(@"\G(?:when\b)");
              Patterns.Add(TokenType.WHEN, regex);
              Tokens.Add(TokenType.WHEN);
  
              regex = new Regex(@"\G(?:then\b)");
              Patterns.Add(TokenType.THEN, regex);
              Tokens.Add(TokenType.THEN);
  
              regex = new Regex(@"\G(?:off\b)");
              Patterns.Add(TokenType.OFF, regex);
              Tokens.Add(TokenType.OFF);
  
              regex = new Regex(@"\G(?:stage\b)");
              Patterns.Add(TokenType.STAGE, regex);
              Tokens.Add(TokenType.STAGE);
  
              regex = new Regex(@"\G(?:clearscreen\b)");
              Patterns.Add(TokenType.CLEARSCREEN, regex);
              Tokens.Add(TokenType.CLEARSCREEN);
  
              regex = new Regex(@"\G(?:add\b)");
              Patterns.Add(TokenType.ADD, regex);
              Tokens.Add(TokenType.ADD);
  
              regex = new Regex(@"\G(?:remove\b)");
              Patterns.Add(TokenType.REMOVE, regex);
              Tokens.Add(TokenType.REMOVE);
  
              regex = new Regex(@"\G(?:log\b)");
              Patterns.Add(TokenType.LOG, regex);
              Tokens.Add(TokenType.LOG);
  
              regex = new Regex(@"\G(?:break\b)");
              Patterns.Add(TokenType.BREAK, regex);
              Tokens.Add(TokenType.BREAK);
  
              regex = new Regex(@"\G(?:preserve\b)");
              Patterns.Add(TokenType.PRESERVE, regex);
              Tokens.Add(TokenType.PRESERVE);
  
              regex = new Regex(@"\G(?:declare\b)");
              Patterns.Add(TokenType.DECLARE, regex);
              Tokens.Add(TokenType.DECLARE);
  
              regex = new Regex(@"\G(?:defined\b)");
              Patterns.Add(TokenType.DEFINED, regex);
              Tokens.Add(TokenType.DEFINED);
  
              regex = new Regex(@"\G(?:local\b)");
              Patterns.Add(TokenType.LOCAL, regex);
              Tokens.Add(TokenType.LOCAL);
  
              regex = new Regex(@"\G(?:global\b)");
              Patterns.Add(TokenType.GLOBAL, regex);
              Tokens.Add(TokenType.GLOBAL);
  
              regex = new Regex(@"\G(?:parameter\b)");
              Patterns.Add(TokenType.PARAMETER, regex);
              Tokens.Add(TokenType.PARAMETER);
  
              regex = new Regex(@"\G(?:function\b)");
              Patterns.Add(TokenType.FUNCTION, regex);
              Tokens.Add(TokenType.FUNCTION);
  
              regex = new Regex(@"\G(?:return\b)");
              Patterns.Add(TokenType.RETURN, regex);
              Tokens.Add(TokenType.RETURN);
  
              regex = new Regex(@"\G(?:switch\b)");
              Patterns.Add(TokenType.SWITCH, regex);
              Tokens.Add(TokenType.SWITCH);
  
              regex = new Regex(@"\G(?:copy\b)");
              Patterns.Add(TokenType.COPY, regex);
              Tokens.Add(TokenType.COPY);
  
              regex = new Regex(@"\G(?:from\b)");
              Patterns.Add(TokenType.FROM, regex);
              Tokens.Add(TokenType.FROM);
  
              regex = new Regex(@"\G(?:rename\b)");
              Patterns.Add(TokenType.RENAME, regex);
              Tokens.Add(TokenType.RENAME);
  
              regex = new Regex(@"\G(?:volume\b)");
              Patterns.Add(TokenType.VOLUME, regex);
              Tokens.Add(TokenType.VOLUME);
  
              regex = new Regex(@"\G(?:file\b)");
              Patterns.Add(TokenType.FILE, regex);
              Tokens.Add(TokenType.FILE);
  
              regex = new Regex(@"\G(?:delete\b)");
              Patterns.Add(TokenType.DELETE, regex);
              Tokens.Add(TokenType.DELETE);
  
              regex = new Regex(@"\G(?:edit\b)");
              Patterns.Add(TokenType.EDIT, regex);
              Tokens.Add(TokenType.EDIT);
  
              regex = new Regex(@"\G(?:run\b)");
              Patterns.Add(TokenType.RUN, regex);
              Tokens.Add(TokenType.RUN);
  
              regex = new Regex(@"\G(?:runpath\b)");
              Patterns.Add(TokenType.RUNPATH, regex);
              Tokens.Add(TokenType.RUNPATH);
  
              regex = new Regex(@"\G(?:runoncepath\b)");
              Patterns.Add(TokenType.RUNONCEPATH, regex);
              Tokens.Add(TokenType.RUNONCEPATH);
  
              regex = new Regex(@"\G(?:once\b)");
              Patterns.Add(TokenType.ONCE, regex);
              Tokens.Add(TokenType.ONCE);
  
              regex = new Regex(@"\G(?:compile\b)");
              Patterns.Add(TokenType.COMPILE, regex);
              Tokens.Add(TokenType.COMPILE);
  
              regex = new Regex(@"\G(?:list\b)");
              Patterns.Add(TokenType.LIST, regex);
              Tokens.Add(TokenType.LIST);
  
              regex = new Regex(@"\G(?:reboot\b)");
              Patterns.Add(TokenType.REBOOT, regex);
              Tokens.Add(TokenType.REBOOT);
  
              regex = new Regex(@"\G(?:shutdown\b)");
              Patterns.Add(TokenType.SHUTDOWN, regex);
              Tokens.Add(TokenType.SHUTDOWN);
  
              regex = new Regex(@"\G(?:for\b)");
              Patterns.Add(TokenType.FOR, regex);
              Tokens.Add(TokenType.FOR);
  
              regex = new Regex(@"\G(?:unset\b)");
              Patterns.Add(TokenType.UNSET, regex);
              Tokens.Add(TokenType.UNSET);
  
              regex = new Regex(@"\G(?:\()");
              Patterns.Add(TokenType.BRACKETOPEN, regex);
              Tokens.Add(TokenType.BRACKETOPEN);
  
              regex = new Regex(@"\G(?:\))");
              Patterns.Add(TokenType.BRACKETCLOSE, regex);
              Tokens.Add(TokenType.BRACKETCLOSE);
  
              regex = new Regex(@"\G(?:\{)");
              Patterns.Add(TokenType.CURLYOPEN, regex);
              Tokens.Add(TokenType.CURLYOPEN);
  
              regex = new Regex(@"\G(?:\})");
              Patterns.Add(TokenType.CURLYCLOSE, regex);
              Tokens.Add(TokenType.CURLYCLOSE);
  
              regex = new Regex(@"\G(?:\[)");
              Patterns.Add(TokenType.SQUAREOPEN, regex);
              Tokens.Add(TokenType.SQUAREOPEN);
  
              regex = new Regex(@"\G(?:\])");
              Patterns.Add(TokenType.SQUARECLOSE, regex);
              Tokens.Add(TokenType.SQUARECLOSE);
  
              regex = new Regex(@"\G(?:,)");
              Patterns.Add(TokenType.COMMA, regex);
              Tokens.Add(TokenType.COMMA);
  
              regex = new Regex(@"\G(?::)");
              Patterns.Add(TokenType.COLON, regex);
              Tokens.Add(TokenType.COLON);
  
              regex = new Regex(@"\G(?:in\b)");
              Patterns.Add(TokenType.IN, regex);
              Tokens.Add(TokenType.IN);
  
              regex = new Regex(@"\G(?:#)");
              Patterns.Add(TokenType.ARRAYINDEX, regex);
              Tokens.Add(TokenType.ARRAYINDEX);
  
              regex = new Regex(@"\G(?:all\b)");
              Patterns.Add(TokenType.ALL, regex);
              Tokens.Add(TokenType.ALL);
  
              regex = new Regex(@"\G(?:[_\p{L}]\w*)");
              Patterns.Add(TokenType.IDENTIFIER, regex);
              Tokens.Add(TokenType.IDENTIFIER);
  
              regex = new Regex(@"\G(?:[_\p{L}]\w*(\.[_\p{L}]\w*)*)");
              Patterns.Add(TokenType.FILEIDENT, regex);
              Tokens.Add(TokenType.FILEIDENT);
  
              regex = new Regex(@"\G(?:\d[_\d]*)");
              Patterns.Add(TokenType.INTEGER, regex);
              Tokens.Add(TokenType.INTEGER);
  
              regex = new Regex(@"\G(?:(\d+(?:_\d*)*)?\.\d+(?:_\d*)*)");
              Patterns.Add(TokenType.DOUBLE, regex);
              Tokens.Add(TokenType.DOUBLE);
  
              regex = new Regex(@"\G(?:@?\""(\""\""|[^\""])*\"")");
              Patterns.Add(TokenType.STRING, regex);
              Tokens.Add(TokenType.STRING);
  
              regex = new Regex(@"\G(?:\.)");
              Patterns.Add(TokenType.EOI, regex);
              Tokens.Add(TokenType.EOI);
  
              regex = new Regex(@"\G(?:@)");
              Patterns.Add(TokenType.ATSIGN, regex);
              Tokens.Add(TokenType.ATSIGN);
  
              regex = new Regex(@"\G(?:lazyglobal\b)");
              Patterns.Add(TokenType.LAZYGLOBAL, regex);
              Tokens.Add(TokenType.LAZYGLOBAL);
  
              regex = new Regex(@"\G(?:$)");
              Patterns.Add(TokenType.EOF, regex);
              Tokens.Add(TokenType.EOF);
  
              regex = new Regex(@"\G(?:(\s|\p{C})+)");
              Patterns.Add(TokenType.WHITESPACE, regex);
              Tokens.Add(TokenType.WHITESPACE);
  
              regex = new Regex(@"\G(?://[^\n]*\n?)");
              Patterns.Add(TokenType.COMMENTLINE, regex);
              Tokens.Add(TokenType.COMMENTLINE);
  
  
          }
  
          public void Init(string input)
          {
              Init(input, "");
          }
  
          public void Init(string input, string fileName)
          {
              this.Input = input;
              LowerInput = Input.ToLower();
              StartPos = 0;
              EndPos = 0;
              CurrentFile = fileName;
              CurrentLine = 1;
              CurrentColumn = 1;
              CurrentPosition = 0;
              LookAheadToken = null;
          }
  
          public Token GetToken(TokenType type)
          {
              Token t = new Token(this.StartPos, this.EndPos);
              t.Type = type;
              return t;
          }
  
           /// <summary>
          /// executes a lookahead of the next token
          /// and will advance the scan on the input string
          /// </summary>
          /// <returns></returns>
          public Token Scan(params TokenType[] expectedtokens)
          {
              Token tok = LookAhead(expectedtokens); // temporarely retrieve the lookahead
              LookAheadToken = null; // reset lookahead token, so scanning will continue
              StartPos = tok.EndPos;
              EndPos = tok.EndPos; // set the tokenizer to the new scan position
              CurrentLine = tok.Line + (tok.Text.Length - tok.Text.Replace("\n", "").Length);
              CurrentFile = tok.File;
              return tok;
          }
  
          /// <summary>
          /// returns token with longest best match
          /// </summary>
          /// <returns></returns>
          public Token LookAhead(params TokenType[] expectedtokens)
          {
              int i;
              int startpos = StartPos;
              int endpos = EndPos;
              int currentline = CurrentLine;
              string currentFile = CurrentFile;
              Token tok = null;
              List<TokenType> scantokens;
  
  
              // this prevents double scanning and matching
              // increased performance
              if (LookAheadToken != null 
                  && LookAheadToken.Type != TokenType._UNDETERMINED_ 
                  && LookAheadToken.Type != TokenType._NONE_) return LookAheadToken;
  
              // if no scantokens specified, then scan for all of them (= backward compatible)
              if (expectedtokens.Length == 0)
                  scantokens = Tokens;
              else
              {
                  scantokens = new List<TokenType>(expectedtokens);
                  scantokens.AddRange(SkipList);
              }
  
              do
              {
  
                  int len = -1;
                  TokenType index = (TokenType)int.MaxValue;
  
                  tok = new Token(startpos, endpos);
  
                  for (i = 0; i < scantokens.Count; i++)
                  {
                      Regex r = Patterns[scantokens[i]];
                      // use startpos instead of a substring to save memory allocation, but anchors must use \G in place of ^
                      Match m = r.Match(LowerInput, startpos);
                      if (m.Success && m.Index == startpos && ((m.Length > len) || (scantokens[i] < index && m.Length == len )))
                      {
                          len = m.Length;
                          index = scantokens[i];  
                      }
                  }
  
                  if (index >= 0 && len >= 0)
                  {
                      tok.EndPos = startpos + len;
                      tok.Text = Input.Substring(tok.StartPos, len);
                      tok.Type = index;
                  }
                  else if (tok.StartPos == tok.EndPos)
                  {
                      if (tok.StartPos < Input.Length)
                          tok.Text = Input.Substring(tok.StartPos, 1);
                      else
                          tok.Text = "EOF";
                  }
  
                  // Update the line and column count for error reporting.
                  tok.File = currentFile;
                  tok.Line = currentline;
                  if (tok.StartPos < Input.Length)
                      tok.Column = tok.StartPos - Input.LastIndexOf('\n', tok.StartPos);
  
                  if (SkipList.Contains(tok.Type))
                  {
                      startpos = tok.EndPos;
                      endpos = tok.EndPos;
                      currentline = tok.Line + (tok.Text.Length - tok.Text.Replace("\n", "").Length);
                      currentFile = tok.File;
                      Skipped.Add(tok);
                  }
                  else
                  {
                      // only assign to non-skipped tokens
                      tok.Skipped = Skipped; // assign prior skips to this token
                      Skipped = new List<Token>(); //reset skips
                  }
  
                  // Check to see if the parsed token wants to 
                  // alter the file and line number.
                  if (tok.Type == FileAndLine)
                  {
                      var match = Patterns[tok.Type].Match(tok.Text);
                      var fileMatch = match.Groups["File"];
                      if (fileMatch.Success)
                          currentFile = fileMatch.Value.Replace("\\\\", "\\");
                      var lineMatch = match.Groups["Line"];
                      if (lineMatch.Success)
                          currentline = int.Parse(lineMatch.Value, NumberStyles.Integer, CultureInfo.InvariantCulture);
                  }
              }
              while (SkipList.Contains(tok.Type));
  
              LookAheadToken = tok;
              return tok;
          }
      }
  
      #endregion
  
      #region Token
  
      public enum TokenType
      {
  
              //Non terminal tokens:
              _NONE_  = 0,
              _UNDETERMINED_= 1,
  
              //Non terminal tokens:
              Start   = 2,
              instruction_block= 3,
              instruction= 4,
              lazyglobal_directive= 5,
              directive= 6,
              empty_stmt= 7,
              set_stmt= 8,
              if_stmt = 9,
              until_stmt= 10,
              fromloop_stmt= 11,
              unlock_stmt= 12,
              print_stmt= 13,
              on_stmt = 14,
              toggle_stmt= 15,
              wait_stmt= 16,
              when_stmt= 17,
              onoff_stmt= 18,
              onoff_trailer= 19,
              stage_stmt= 20,
              clear_stmt= 21,
              add_stmt= 22,
              remove_stmt= 23,
              log_stmt= 24,
              break_stmt= 25,
              preserve_stmt= 26,
              declare_identifier_clause= 27,
              declare_parameter_clause= 28,
              declare_function_clause= 29,
              declare_lock_clause= 30,
              declare_stmt= 31,
              return_stmt= 32,
              switch_stmt= 33,
              copy_stmt= 34,
              rename_stmt= 35,
              delete_stmt= 36,
              edit_stmt= 37,
              run_stmt= 38,
              runpath_stmt= 39,
              runoncepath_stmt= 40,
              compile_stmt= 41,
              list_stmt= 42,
              reboot_stmt= 43,
              shutdown_stmt= 44,
              for_stmt= 45,
              unset_stmt= 46,
              arglist = 47,
              expr    = 48,
              or_expr = 49,
              and_expr= 50,
              compare_expr= 51,
              arith_expr= 52,
              multdiv_expr= 53,
              unary_expr= 54,
              factor  = 55,
              suffix  = 56,
              suffix_trailer= 57,
              suffixterm= 58,
              suffixterm_trailer= 59,
              function_trailer= 60,
              array_trailer= 61,
              atom    = 62,
              sci_number= 63,
              number  = 64,
              varidentifier= 65,
              identifier_led_stmt= 66,
              identifier_led_expr= 67,
  
              //Terminal tokens:
              PLUSMINUS= 68,
              MULT    = 69,
              DIV     = 70,
              POWER   = 71,
              E       = 72,
              NOT     = 73,
              AND     = 74,
              OR      = 75,
              TRUEFALSE= 76,
              COMPARATOR= 77,
              SET     = 78,
              TO      = 79,
              IS      = 80,
              IF      = 81,
              ELSE    = 82,
              UNTIL   = 83,
              STEP    = 84,
              DO      = 85,
              LOCK    = 86,
              UNLOCK  = 87,
              PRINT   = 88,
              AT      = 89,
              ON      = 90,
              TOGGLE  = 91,
              WAIT    = 92,
              WHEN    = 93,
              THEN    = 94,
              OFF     = 95,
              STAGE   = 96,
              CLEARSCREEN= 97,
              ADD     = 98,
              REMOVE  = 99,
              LOG     = 100,
              BREAK   = 101,
              PRESERVE= 102,
              DECLARE = 103,
              DEFINED = 104,
              LOCAL   = 105,
              GLOBAL  = 106,
              PARAMETER= 107,
              FUNCTION= 108,
              RETURN  = 109,
              SWITCH  = 110,
              COPY    = 111,
              FROM    = 112,
              RENAME  = 113,
              VOLUME  = 114,
              FILE    = 115,
              DELETE  = 116,
              EDIT    = 117,
              RUN     = 118,
              RUNPATH = 119,
              RUNONCEPATH= 120,
              ONCE    = 121,
              COMPILE = 122,
              LIST    = 123,
              REBOOT  = 124,
              SHUTDOWN= 125,
              FOR     = 126,
              UNSET   = 127,
              BRACKETOPEN= 128,
              BRACKETCLOSE= 129,
              CURLYOPEN= 130,
              CURLYCLOSE= 131,
              SQUAREOPEN= 132,
              SQUARECLOSE= 133,
              COMMA   = 134,
              COLON   = 135,
              IN      = 136,
              ARRAYINDEX= 137,
              ALL     = 138,
              IDENTIFIER= 139,
              FILEIDENT= 140,
              INTEGER = 141,
              DOUBLE  = 142,
              STRING  = 143,
              EOI     = 144,
              ATSIGN  = 145,
              LAZYGLOBAL= 146,
              EOF     = 147,
              WHITESPACE= 148,
              COMMENTLINE= 149
      }
  
      public class Token
      {
          private string file;
          private int line;
          private int column;
          private int startpos;
          private int endpos;
          private string text;
          private object value;
  
          // contains all prior skipped symbols
          private List<Token> skipped;
  
          public string File { 
              get { return file; } 
              set { file = value; }
          }
  
          public int Line { 
              get { return line; } 
              set { line = value; }
          }
  
          public int Column {
              get { return column; } 
              set { column = value; }
          }
  
          public int StartPos { 
              get { return startpos;} 
              set { startpos = value; }
          }
  
          public int Length { 
              get { return endpos - startpos;} 
          }
  
          public int EndPos { 
              get { return endpos;} 
              set { endpos = value; }
          }
  
          public string Text { 
              get { return text;} 
  
gt:             set { text = value; }