Change throwing of Error objects into IOException objects in lexer so that main class...
[IRC.git] / Robust / src / Lex / Lexer.java
index 2cdd84e9da8f3d27a26ce86d041ebf868f13f403..a7cbe1b4876e12d3ae461647cf55c9a20286a730 100644 (file)
@@ -1,5 +1,6 @@
 package Lex;
 
+import java.io.IOException;
 import java.io.Reader;
 import java.io.LineNumberReader;
 import Parse.Sym;
@@ -19,13 +20,13 @@ public class Lexer {
   int line_pos = 1;
   int line_num = 0;
   LineList lineL = new LineList(-line_pos, null); // sentinel for line #0
-  
+
   public Lexer(Reader reader) {
     this.reader = new LineNumberReader(new EscapedUnicodeReader(reader));
     this.isJava12 = true;
     this.isJava14 = true;
   }
-  
+
   public java_cup.runtime.Symbol nextToken() throws java.io.IOException {
     java_cup.runtime.Symbol sym =
       lookahead==null ? _nextToken() : lookahead.get();
@@ -37,9 +38,9 @@ public class Lexer {
     if (last==null || last.sym!=Sym.IDENTIFIER)
       return false;
     if (lookahead==null) lookahead = new FIFO(new FIFO.Getter() {
-       java_cup.runtime.Symbol next() throws java.io.IOException
-       { return _nextToken(); }
-      });
+                                                java_cup.runtime.Symbol next() throws java.io.IOException
+                                                { return _nextToken(); }
+                                             });
     int i=0;
     // skip past IDENTIFIER (DOT IDENTIFIER)*
     if (lookahead.peek(i++).sym != Sym.IDENTIFIER)
@@ -59,6 +60,7 @@ public class Lexer {
     switch(lookahead.peek(i).sym) {
     default:
       return false;
+
     case Sym.LT:
     case Sym.GT:
     case Sym.COMMA:
@@ -103,9 +105,13 @@ public class Lexer {
   }
 
   String comment;
-  public String lastComment() { return comment; }
-  public void clearComment() { comment=""; }
-  
+  public String lastComment() {
+    return comment;
+  }
+  public void clearComment() {
+    comment="";
+  }
+
   InputElement getInputElement() throws java.io.IOException {
     if (line_num == 0)
       nextLine();
@@ -116,14 +122,14 @@ public class Lexer {
       if (line==null)
        return new EOF();
     }
-    
+
     switch (line.charAt(line_pos)) {
 
       // White space:
-    case ' ':  // ASCII SP
-    case '\t': // ASCII HT
-    case '\f': // ASCII FF
-    case '\n': // LineTerminator
+    case ' ':    // ASCII SP
+    case '\t':    // ASCII HT
+    case '\f':    // ASCII FF
+    case '\n':    // LineTerminator
       return new WhiteSpace(consume());
 
       // EOF character:
@@ -149,6 +155,7 @@ public class Lexer {
       comment = line.substring(line_pos+2);
       line_pos = line.length();
       return new EndOfLineComment(comment);
+
     case '*': // TraditionalComment or DocumentationComment
       line_pos += 2;
       if (line.charAt(line_pos)=='*') { // DocumentationComment
@@ -156,6 +163,7 @@ public class Lexer {
       } else { // TraditionalComment
        return snarfComment(new TraditionalComment());
       }
+
     default: // it's a token, not a comment.
       return getToken();
     }
@@ -171,8 +179,8 @@ public class Lexer {
          c.appendLine(text.toString()); text.setLength(0);
          line_pos = line.length();
          nextLine();
-         if (line==null) 
-           throw new Error("Unterminated comment at end of file.");
+         if (line==null)
+           throw new IOException("Unterminated comment at end of file.");
        } else {
          text.append(line.substring(line_pos, star_pos));
          line_pos=star_pos;
@@ -187,7 +195,7 @@ public class Lexer {
     }
   }
 
-  Token getToken() {
+  Token getToken() throws java.io.IOException {
     // Tokens are: Identifiers, Keywords, Literals, Separators, Operators.
     switch (line.charAt(line_pos)) {
       // Separators: (period is a special case)
@@ -218,8 +226,10 @@ public class Lexer {
     case '^':
     case '%':
       return getOperator();
+
     case '\'':
       return getCharLiteral();
+
     case '\"':
       return getStringLiteral();
 
@@ -228,39 +238,47 @@ public class Lexer {
       if (Character.digit(line.charAt(line_pos+1),10)!=-1)
        return getNumericLiteral();
       else if (isJava15 &&
-              line.charAt(line_pos+1)=='.' &&
-              line.charAt(line_pos+2)=='.') {
+               line.charAt(line_pos+1)=='.' &&
+               line.charAt(line_pos+2)=='.') {
        consume(); consume(); consume();
        return new Separator('\u2026'); // unicode ellipsis character.
       } else return new Separator(consume());
-    default: 
+
+    default:
       break;
     }
     if (Character.isJavaIdentifierStart(line.charAt(line_pos)))
       return getIdentifier();
     if (Character.isDigit(line.charAt(line_pos)))
       return getNumericLiteral();
-    throw new Error("Illegal character on line "+line_num);
+    throw new IOException("Illegal character on line "+line_num);
   }
 
   static final String[] keywords = new String[] {
     "abstract", "assert", "atomic", "boolean", "break", "byte", "case", "catch", "char",
-    "class", "const", "continue", "default", "do", "double", "else", "enum",
-    "extends", "external", "final", "finally", 
+    "class", "const", "continue",
+    "default", "disjoint", "do", "double",
+    "else", "enum",
+    "extends", "external", "final", "finally",
     "flag", //keyword for failure aware computation
-    "float", "for", "global", "goto", "if", 
-    "implements", "import", "instanceof", "int", "interface", "long",  
-    "native", "new", "optional", "package", "private", "protected", "public", 
-    "return", "short", "static", "strictfp", "super", "switch", "synchronized",
+    "float", "for","getoffset", "global", "goto", "if",
+    //"implements",
+    "import", "instanceof", "int",
+    //"interface",
+    "isavailable",
+    "long",
+    "native", "new", "optional", "package", "private", "protected", "public",
+    "return", "sese", "short", "static", "strictfp", "super", "switch", "synchronized",
     "tag", "task", "taskexit", //keywords for failure aware computation
     "this", "throw", "throws", "transient", "try", "void",
-    "volatile", "while"};
-  Token getIdentifier() {
+    "volatile", "while"
+  };
+  Token getIdentifier() throws java.io.IOException {
     // Get id string.
     StringBuffer sb = new StringBuffer().append(consume());
 
     if (!Character.isJavaIdentifierStart(sb.charAt(0)))
-      throw new Error("Invalid Java Identifier on line "+line_num);
+      throw new IOException("Invalid Java Identifier on line "+line_num);
     while (Character.isJavaIdentifierPart(line.charAt(line_pos)))
       sb.append(consume());
     String s = sb.toString();
@@ -278,22 +296,22 @@ public class Lexer {
     // use binary search.
     for (int l=0, r=keywords.length; r > l; ) {
       int x = (l+r)/2, cmp = s.compareTo(keywords[x]);
-      if (cmp < 0) r=x; else l=x+1;
+      if (cmp < 0) r=x;else l=x+1;
       if (cmp== 0) return new Keyword(s);
     }
     // not a keyword.
     return new Identifier(s);
   }
-  NumericLiteral getNumericLiteral() {
+  NumericLiteral getNumericLiteral() throws java.io.IOException {
     int i;
     // leading decimal indicates float.
     if (line.charAt(line_pos)=='.')
       return getFloatingPointLiteral();
     // 0x indicates Hex.
     if (line.charAt(line_pos)=='0' &&
-       (line.charAt(line_pos+1)=='x' ||
-        line.charAt(line_pos+1)=='X')) {
-      line_pos+=2; return getIntegerLiteral(/*base*/16);
+        (line.charAt(line_pos+1)=='x' ||
+         line.charAt(line_pos+1)=='X')) {
+      line_pos+=2; return getIntegerLiteral(/*base*/ 16);
     }
     // otherwise scan to first non-numeric
     for (i=line_pos; Character.digit(line.charAt(i),10)!=-1; )
@@ -307,39 +325,40 @@ public class Lexer {
     case 'e':
     case 'E':
       return getFloatingPointLiteral();
+
     case 'L':
     case 'l':
     default:
       if (line.charAt(line_pos)=='0')
-       return getIntegerLiteral(/*base*/8);
-      return getIntegerLiteral(/*base*/10);
+       return getIntegerLiteral(/*base*/ 8);
+      return getIntegerLiteral(/*base*/ 10);
     }
   }
-  NumericLiteral getIntegerLiteral(int radix) {
+  NumericLiteral getIntegerLiteral(int radix) throws java.io.IOException {
     long val=0;
     while (Character.digit(line.charAt(line_pos),radix)!=-1)
       val = (val*radix) + Character.digit(consume(),radix);
     if (line.charAt(line_pos) == 'l' ||
-       line.charAt(line_pos) == 'L') {
+        line.charAt(line_pos) == 'L') {
       consume();
       return new LongLiteral(val);
-    } 
+    }
     // we compare MAX_VALUE against val/2 to allow constants like
     // 0xFFFF0000 to get past the test. (unsigned long->signed int)
     if ((val/2) > Integer.MAX_VALUE ||
-        val    < Integer.MIN_VALUE)
-      throw new Error("Constant does not fit in integer on line "+line_num);
+        val    < Integer.MIN_VALUE)
+      throw new IOException("Constant does not fit in integer on line "+line_num);
     return new IntegerLiteral((int)val);
   }
-  NumericLiteral getFloatingPointLiteral() {
+  NumericLiteral getFloatingPointLiteral() throws java.io.IOException {
     String rep = getDigits();
     if (line.charAt(line_pos)=='.')
       rep+=consume() + getDigits();
     if (line.charAt(line_pos)=='e' ||
-       line.charAt(line_pos)=='E') {
+        line.charAt(line_pos)=='E') {
       rep+=consume();
       if (line.charAt(line_pos)=='+' ||
-         line.charAt(line_pos)=='-')
+          line.charAt(line_pos)=='-')
        rep+=consume();
       rep+=getDigits();
     }
@@ -349,15 +368,17 @@ public class Lexer {
       case 'F':
        consume();
        return new FloatLiteral(Float.valueOf(rep).floatValue());
+
       case 'd':
       case 'D':
        consume();
+
        /* falls through */
       default:
        return new DoubleLiteral(Double.valueOf(rep).doubleValue());
       }
     } catch (NumberFormatException e) {
-      throw new Error("Illegal floating-point on line "+line_num+": "+e);
+      throw new IOException("Illegal floating-point on line "+line_num+": "+e);
     }
   }
   String getDigits() {
@@ -377,23 +398,25 @@ public class Lexer {
     case '?':
     case ':':
       return new Operator(new String(new char[] {first}));
+
       // doubled operators
     case '+':
     case '-':
     case '&':
     case '|':
-      if (first==second) 
+      if (first==second)
        return new Operator(new String(new char[] {first, consume()}));
+
     default:
       break;
     }
     // Check for trailing '='
     if (second=='=')
-       return new Operator(new String(new char[] {first, consume()}));
+      return new Operator(new String(new char[] {first, consume()}));
 
     // Special-case '<<', '>>' and '>>>'
     if ((first=='<' && second=='<') || // <<
-       (first=='>' && second=='>')) {  // >>
+        (first=='>' && second=='>')) {  // >>
       String op = new String(new char[] {first, consume()});
       if (first=='>' && line.charAt(line_pos)=='>') // >>>
        op += consume();
@@ -406,27 +429,30 @@ public class Lexer {
     return new Operator(new String(new char[] {first}));
   }
 
-  CharacterLiteral getCharLiteral() {
+  CharacterLiteral getCharLiteral() throws java.io.IOException {
     char firstquote = consume();
     char val;
     switch (line.charAt(line_pos)) {
     case '\\':
       val = getEscapeSequence();
       break;
+
     case '\'':
-      throw new Error("Invalid character literal on line "+line_num);
+      throw new IOException("Invalid character literal on line "+line_num);
+
     case '\n':
-      throw new Error("Invalid character literal on line "+line_num);
+      throw new IOException("Invalid character literal on line "+line_num);
+
     default:
       val = consume();
       break;
     }
     char secondquote = consume();
     if (firstquote != '\'' || secondquote != '\'')
-      throw new Error("Invalid character literal on line "+line_num);
+      throw new IOException("Invalid character literal on line "+line_num);
     return new CharacterLiteral(val);
   }
-  StringLiteral getStringLiteral() {
+  StringLiteral getStringLiteral() throws java.io.IOException {
     char openquote = consume();
     StringBuffer val = new StringBuffer();
     while (line.charAt(line_pos)!='\"') {
@@ -434,8 +460,10 @@ public class Lexer {
       case '\\':
        val.append(getEscapeSequence());
        break;
+
       case '\n':
-       throw new Error("Invalid string literal on line " + line_num);
+       throw new IOException("Invalid string literal on line " + line_num);
+
       default:
        val.append(consume());
        break;
@@ -443,79 +471,97 @@ public class Lexer {
     }
     char closequote = consume();
     if (openquote != '\"' || closequote != '\"')
-      throw new Error("Invalid string literal on line " + line_num);
-    
+      throw new IOException("Invalid string literal on line " + line_num);
+
     return new StringLiteral(val.toString().intern());
   }
 
-  char getEscapeSequence() {
+  char getEscapeSequence() throws java.io.IOException {
     if (consume() != '\\')
-      throw new Error("Invalid escape sequence on line " + line_num);
+      throw new IOException("Invalid escape sequence on line " + line_num);
     switch(line.charAt(line_pos)) {
     case 'b':
       consume(); return '\b';
+
     case 't':
       consume(); return '\t';
+
     case 'n':
       consume(); return '\n';
+
     case 'f':
       consume(); return '\f';
+
     case 'r':
       consume(); return '\r';
+
     case '\"':
       consume(); return '\"';
+
     case '\'':
       consume(); return '\'';
+
     case '\\':
       consume(); return '\\';
+
     case '0':
     case '1':
     case '2':
     case '3':
       return (char) getOctal(3);
+
     case '4':
     case '5':
     case '6':
     case '7':
       return (char) getOctal(2);
+
     default:
-      throw new Error("Invalid escape sequence on line " + line_num);
+      throw new IOException("Invalid escape sequence on line " + line_num);
     }
   }
-  int getOctal(int maxlength) {
+  int getOctal(int maxlength) throws java.io.IOException {
     int i, val=0;
     for (i=0; i<maxlength; i++)
       if (Character.digit(line.charAt(line_pos), 8)!=-1) {
        val = (8*val) + Character.digit(consume(), 8);
       } else break;
     if ((i==0) || (val>0xFF)) // impossible.
-      throw new Error("Invalid octal escape sequence in line " + line_num);
+      throw new IOException("Invalid octal escape sequence in line " + line_num);
     return val;
   }
 
-  char consume() { return line.charAt(line_pos++); }
+  char consume() {
+    return line.charAt(line_pos++);
+  }
   void nextLine() throws java.io.IOException {
     line=reader.readLine();
-    if (line!=null) line=line+'\n'; 
+    if (line!=null) line=line+'\n';
     lineL = new LineList(lineL.head+line_pos, lineL); // for error reporting
-    line_pos=0; 
-    line_num++; 
+    line_pos=0;
+    line_num++;
   }
 
   // Deal with error messages.
   public void errorMsg(String msg, java_cup.runtime.Symbol info) {
     int n=line_num, c=info.left-lineL.head;
     for (LineList p = lineL; p!=null; p=p.tail, n--)
-       if (p.head<=info.left) { c=info.left-p.head; break; }
+      if (p.head<=info.left) {
+       c=info.left-p.head; break;
+      }
     System.err.println(msg+" at line "+n);
     num_errors++;
   }
   private int num_errors = 0;
-  public int numErrors() { return num_errors; }
-  
+  public int numErrors() {
+    return num_errors;
+  }
+
   class LineList {
     int head;
     LineList tail;
-    LineList(int head, LineList tail) { this.head = head; this.tail = tail; }
+    LineList(int head, LineList tail) {
+      this.head = head; this.tail = tail;
+    }
   }
 }