Basic Error Handling
Added Scanner and Parsing Exceptions as well as keeping track of the source position.master
parent
242ca887f9
commit
f34ccd138d
|
@ -3,6 +3,7 @@ package miniJava;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import miniJava.SyntacticAnalyzer.*;
|
import miniJava.SyntacticAnalyzer.*;
|
||||||
|
import miniJava.SyntacticAnalyzer.Errors.*;
|
||||||
import miniJava.AbstractSyntaxTrees.*;
|
import miniJava.AbstractSyntaxTrees.*;
|
||||||
import miniJava.AbstractSyntaxTrees.Package;
|
import miniJava.AbstractSyntaxTrees.Package;
|
||||||
|
|
||||||
|
@ -30,10 +31,16 @@ public class Compiler {
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
|
|
||||||
} catch(FileNotFoundException e) {
|
} catch(FileNotFoundException e) {
|
||||||
System.exit(rc);
|
System.out.println(e.getMessage());
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
System.exit(rc);
|
System.out.println(e.getMessage());
|
||||||
|
}catch(ScanningException e) {
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
} catch(ParsingException e) {
|
||||||
|
System.out.println(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.exit(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package miniJava.SyntacticAnalyzer.Errors;
|
||||||
|
|
||||||
|
import miniJava.SyntacticAnalyzer.Token;
|
||||||
|
|
||||||
|
public class ParsingException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public ParsingException() {
|
||||||
|
super("Unidentified parsing error!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParsingException(Token t) {
|
||||||
|
super("Parsing error with " + t.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package miniJava.SyntacticAnalyzer.Errors;
|
||||||
|
|
||||||
|
public class ScanningException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public ScanningException(int col, int line) {
|
||||||
|
super("Scanning error at Column: " + col + ", Line: " + line);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,9 +1,10 @@
|
||||||
package miniJava.SyntacticAnalyzer;
|
package miniJava.SyntacticAnalyzer;
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
import miniJava.AbstractSyntaxTrees.*;
|
import miniJava.AbstractSyntaxTrees.*;
|
||||||
import miniJava.AbstractSyntaxTrees.Package;
|
import miniJava.AbstractSyntaxTrees.Package;
|
||||||
|
import miniJava.SyntacticAnalyzer.Errors.*;
|
||||||
|
|
||||||
public class Parser {
|
public class Parser {
|
||||||
|
|
||||||
|
@ -18,9 +19,9 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* Program ::= (ClassDeclaration)* eot
|
* Program ::= (ClassDeclaration)* eot
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
public Package parse() throws IOException {
|
public Package parse() throws ParsingException, ScanningException {
|
||||||
ClassDeclList decls = new ClassDeclList();
|
ClassDeclList decls = new ClassDeclList();
|
||||||
while(peek(1).type == Token.TYPE.CLASS) {
|
while(peek(1).type == Token.TYPE.CLASS) {
|
||||||
decls.add(parseClassDeclaration());
|
decls.add(parseClassDeclaration());
|
||||||
|
@ -36,9 +37,9 @@ public class Parser {
|
||||||
* (Declarators id (; | MethodDeclaration))*
|
* (Declarators id (; | MethodDeclaration))*
|
||||||
* }
|
* }
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private ClassDecl parseClassDeclaration() throws IOException {
|
private ClassDecl parseClassDeclaration() throws ParsingException, ScanningException {
|
||||||
|
|
||||||
// Class Header
|
// Class Header
|
||||||
accept(Token.TYPE.CLASS);
|
accept(Token.TYPE.CLASS);
|
||||||
|
@ -72,9 +73,9 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* Declarators ::= (public | private)? static? Type
|
* Declarators ::= (public | private)? static? Type
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Declarators parseDeclarators() throws IOException {
|
private Declarators parseDeclarators() throws ParsingException, ScanningException {
|
||||||
|
|
||||||
// Visibility
|
// Visibility
|
||||||
boolean isPrivate = false;
|
boolean isPrivate = false;
|
||||||
|
@ -103,9 +104,9 @@ public class Parser {
|
||||||
* }
|
* }
|
||||||
* @param f describes the declaratory aspect of the method
|
* @param f describes the declaratory aspect of the method
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private MethodDecl parseMethodDeclaration(FieldDecl f) throws IOException {
|
private MethodDecl parseMethodDeclaration(FieldDecl f) throws ParsingException, ScanningException {
|
||||||
|
|
||||||
// Method Header
|
// Method Header
|
||||||
accept(Token.TYPE.LPAREN);
|
accept(Token.TYPE.LPAREN);
|
||||||
|
@ -139,9 +140,9 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* Type ::= boolean | void | int ([])? | id ([])?
|
* Type ::= boolean | void | int ([])? | id ([])?
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Type parseType() throws IOException {
|
private Type parseType() throws ParsingException, ScanningException {
|
||||||
|
|
||||||
switch(peek(1).type) {
|
switch(peek(1).type) {
|
||||||
|
|
||||||
|
@ -181,16 +182,16 @@ public class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new IOException();
|
throw new ParsingException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ParameterList ::= Type id (, Type id)*
|
* ParameterList ::= Type id (, Type id)*
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private ParameterDeclList parseParameterList() throws IOException {
|
private ParameterDeclList parseParameterList() throws ParsingException, ScanningException {
|
||||||
|
|
||||||
ParameterDeclList decls = new ParameterDeclList();
|
ParameterDeclList decls = new ParameterDeclList();
|
||||||
|
|
||||||
|
@ -213,9 +214,9 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* ArgumentList ::= Expression (, Expression)*
|
* ArgumentList ::= Expression (, Expression)*
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private ExprList parseArgumentList() throws IOException {
|
private ExprList parseArgumentList() throws ParsingException, ScanningException {
|
||||||
ExprList e = new ExprList();
|
ExprList e = new ExprList();
|
||||||
e.add(parseExpression());
|
e.add(parseExpression());
|
||||||
while(peek(1).type == Token.TYPE.COMMA) {
|
while(peek(1).type == Token.TYPE.COMMA) {
|
||||||
|
@ -229,9 +230,9 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* Reference ::= BaseRef (. BaseRef)*
|
* Reference ::= BaseRef (. BaseRef)*
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Reference parseReference() throws IOException {
|
private Reference parseReference() throws ParsingException, ScanningException {
|
||||||
Reference r = parseBaseRef();
|
Reference r = parseBaseRef();
|
||||||
while(peek(1).type == Token.TYPE.PERIOD) {
|
while(peek(1).type == Token.TYPE.PERIOD) {
|
||||||
accept(Token.TYPE.PERIOD);
|
accept(Token.TYPE.PERIOD);
|
||||||
|
@ -253,9 +254,9 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* BaseRef ::= this | id ([ Expression])?
|
* BaseRef ::= this | id ([ Expression])?
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Reference parseBaseRef() throws IOException {
|
private Reference parseBaseRef() throws ParsingException, ScanningException {
|
||||||
|
|
||||||
switch(peek(1).type) {
|
switch(peek(1).type) {
|
||||||
case THIS:
|
case THIS:
|
||||||
|
@ -289,9 +290,9 @@ public class Parser {
|
||||||
* | if (Expression) Statement (else Statement)?
|
* | if (Expression) Statement (else Statement)?
|
||||||
* | while (Expression) Statement
|
* | while (Expression) Statement
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Statement parseStatement() throws IOException {
|
private Statement parseStatement() throws ParsingException, ScanningException {
|
||||||
|
|
||||||
switch(peek(1).type) {
|
switch(peek(1).type) {
|
||||||
|
|
||||||
|
@ -391,9 +392,9 @@ public class Parser {
|
||||||
* | num | true | false
|
* | num | true | false
|
||||||
* | new (id() | int [ Expression ] | id [ Expression ] )
|
* | new (id() | int [ Expression ] | id [ Expression ] )
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Expression parseSingleExpression() throws IOException {
|
private Expression parseSingleExpression() throws ParsingException, ScanningException {
|
||||||
|
|
||||||
Expression e = null;
|
Expression e = null;
|
||||||
switch(peek(1).type) {
|
switch(peek(1).type) {
|
||||||
|
@ -430,7 +431,7 @@ public class Parser {
|
||||||
Operator o = new Operator(accept(peek(1).type), null);
|
Operator o = new Operator(accept(peek(1).type), null);
|
||||||
e = new UnaryExpr(o, parseSingleExpression(), null);
|
e = new UnaryExpr(o, parseSingleExpression(), null);
|
||||||
}
|
}
|
||||||
else throw new IOException();
|
else throw new ParsingException();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,7 +488,7 @@ public class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new IOException();
|
throw new ParsingException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
|
@ -497,9 +498,9 @@ public class Parser {
|
||||||
* Disjunction & Initial Call:
|
* Disjunction & Initial Call:
|
||||||
* Expression ::= Expression binop Expression
|
* Expression ::= Expression binop Expression
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Expression parseExpression() throws IOException {
|
private Expression parseExpression() throws ParsingException, ScanningException {
|
||||||
|
|
||||||
Expression e = parseCExpression();
|
Expression e = parseCExpression();
|
||||||
while(peek(1).spelling.equals("||")) {
|
while(peek(1).spelling.equals("||")) {
|
||||||
|
@ -513,9 +514,9 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* Conjunction
|
* Conjunction
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Expression parseCExpression() throws IOException {
|
private Expression parseCExpression() throws ParsingException, ScanningException {
|
||||||
|
|
||||||
Expression e = parseEExpression();
|
Expression e = parseEExpression();
|
||||||
while(peek(1).spelling.equals("&&")) {
|
while(peek(1).spelling.equals("&&")) {
|
||||||
|
@ -529,9 +530,9 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* Equality
|
* Equality
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Expression parseEExpression() throws IOException {
|
private Expression parseEExpression() throws ParsingException, ScanningException {
|
||||||
|
|
||||||
Expression e = parseRExpression();
|
Expression e = parseRExpression();
|
||||||
while(peek(1).spelling.equals("==") || peek(1).spelling.equals("!=")) {
|
while(peek(1).spelling.equals("==") || peek(1).spelling.equals("!=")) {
|
||||||
|
@ -545,9 +546,9 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* Relational
|
* Relational
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Expression parseRExpression() throws IOException {
|
private Expression parseRExpression() throws ParsingException, ScanningException {
|
||||||
|
|
||||||
Expression e = parseAExpression();
|
Expression e = parseAExpression();
|
||||||
while(peek(1).spelling.equals("<") || peek(1).spelling.equals("<=")
|
while(peek(1).spelling.equals("<") || peek(1).spelling.equals("<=")
|
||||||
|
@ -562,9 +563,9 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* Additive
|
* Additive
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Expression parseAExpression() throws IOException {
|
private Expression parseAExpression() throws ParsingException, ScanningException {
|
||||||
|
|
||||||
Expression e = parseMExpression();
|
Expression e = parseMExpression();
|
||||||
while(peek(1).spelling.equals("+") || peek(1).spelling.equals("-")) {
|
while(peek(1).spelling.equals("+") || peek(1).spelling.equals("-")) {
|
||||||
|
@ -578,9 +579,9 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* Multiplicative
|
* Multiplicative
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Expression parseMExpression() throws IOException {
|
private Expression parseMExpression() throws ParsingException, ScanningException {
|
||||||
|
|
||||||
Expression e = parseSingleExpression();
|
Expression e = parseSingleExpression();
|
||||||
while(peek(1).spelling.equals("*") || peek(1).spelling.equals("/")) {
|
while(peek(1).spelling.equals("*") || peek(1).spelling.equals("/")) {
|
||||||
|
@ -594,9 +595,9 @@ public class Parser {
|
||||||
/**
|
/**
|
||||||
* Sees what the next token is, caching the result.
|
* Sees what the next token is, caching the result.
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Token peek(int lookahead) throws IOException {
|
private Token peek(int lookahead) throws ScanningException {
|
||||||
|
|
||||||
// Cache tokens
|
// Cache tokens
|
||||||
while(stream.size() < lookahead) {
|
while(stream.size() < lookahead) {
|
||||||
|
@ -610,12 +611,12 @@ public class Parser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consumes token or throws exception.
|
* Consumes token or throws exception.
|
||||||
* @throws IOException
|
* @throws ScanningException
|
||||||
*/
|
*/
|
||||||
private Token accept(Token.TYPE type) throws IOException {
|
private Token accept(Token.TYPE type) throws ParsingException, ScanningException {
|
||||||
Token next = peek(1);
|
Token next = peek(1);
|
||||||
if(next.type == type) stream.poll();
|
if(next.type == type) stream.poll();
|
||||||
else throw new IOException();
|
else throw new ParsingException(next);
|
||||||
|
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,12 @@ package miniJava.SyntacticAnalyzer;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
|
import miniJava.SyntacticAnalyzer.Errors.ScanningException;
|
||||||
|
|
||||||
public class Scanner {
|
public class Scanner {
|
||||||
|
|
||||||
|
private int col = 1;
|
||||||
|
private int line = 1;
|
||||||
private BufferedReader input;
|
private BufferedReader input;
|
||||||
|
|
||||||
public Scanner(BufferedReader input) {
|
public Scanner(BufferedReader input) {
|
||||||
|
@ -15,7 +19,7 @@ public class Scanner {
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public Token scan() throws IOException {
|
public Token scan() throws ScanningException {
|
||||||
|
|
||||||
String attr = "";
|
String attr = "";
|
||||||
Token token = null;
|
Token token = null;
|
||||||
|
@ -23,7 +27,7 @@ public class Scanner {
|
||||||
while(token == null) {
|
while(token == null) {
|
||||||
|
|
||||||
// Check for EOF
|
// Check for EOF
|
||||||
int c = input.read();
|
int c = read();
|
||||||
if(c == -1) return new Token("", Token.TYPE.EOT);
|
if(c == -1) return new Token("", Token.TYPE.EOT);
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
|
@ -37,18 +41,18 @@ public class Scanner {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
if(peek('+')) throw new IOException();
|
if(peek('+')) throw new ScanningException(col, line);
|
||||||
token = new Token(attr, Token.TYPE.BINOP);
|
token = new Token(attr, Token.TYPE.BINOP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '-':
|
case '-':
|
||||||
if(peek('-')) throw new IOException();
|
if(peek('-')) throw new ScanningException(col, line);
|
||||||
token = new Token(attr, Token.TYPE.BINOP);
|
token = new Token(attr, Token.TYPE.BINOP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Check for comment
|
// Check for comment
|
||||||
case '/':
|
case '/':
|
||||||
if(peek('*')) { input.read(); readComment(); attr = ""; }
|
if(peek('*')) { read(); readComment(); attr = ""; }
|
||||||
else if(peek('/')) { readLine(); attr = ""; }
|
else if(peek('/')) { readLine(); attr = ""; }
|
||||||
else token = new Token(attr, Token.TYPE.BINOP);
|
else token = new Token(attr, Token.TYPE.BINOP);
|
||||||
break;
|
break;
|
||||||
|
@ -56,7 +60,7 @@ public class Scanner {
|
||||||
// Check for c or c=
|
// Check for c or c=
|
||||||
case '>':
|
case '>':
|
||||||
case '<':
|
case '<':
|
||||||
if(peek('=')) attr += (char) input.read();
|
if(peek('=')) attr += (char) read();
|
||||||
token = new Token(attr, Token.TYPE.BINOP);
|
token = new Token(attr, Token.TYPE.BINOP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -64,7 +68,7 @@ public class Scanner {
|
||||||
case '!':
|
case '!':
|
||||||
if(!peek('=')) token = new Token(attr, Token.TYPE.UNOP);
|
if(!peek('=')) token = new Token(attr, Token.TYPE.UNOP);
|
||||||
else {
|
else {
|
||||||
attr += (char) input.read();
|
attr += (char) read();
|
||||||
token = new Token(attr, Token.TYPE.BINOP);
|
token = new Token(attr, Token.TYPE.BINOP);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -72,9 +76,9 @@ public class Scanner {
|
||||||
// Check for && or ||
|
// Check for && or ||
|
||||||
case '&':
|
case '&':
|
||||||
case '|':
|
case '|':
|
||||||
if(!peek((char) c)) throw new IOException();
|
if(!peek((char) c)) throw new ScanningException(col, line);
|
||||||
else {
|
else {
|
||||||
attr += (char) input.read();
|
attr += (char) read();
|
||||||
token = new Token(attr, Token.TYPE.BINOP);
|
token = new Token(attr, Token.TYPE.BINOP);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -83,7 +87,7 @@ public class Scanner {
|
||||||
case '=':
|
case '=':
|
||||||
if(!peek('=')) token = new Token(attr, Token.TYPE.EQUALS);
|
if(!peek('=')) token = new Token(attr, Token.TYPE.EQUALS);
|
||||||
else {
|
else {
|
||||||
attr += (char) input.read();
|
attr += (char) read();
|
||||||
token = new Token(attr, Token.TYPE.BINOP);
|
token = new Token(attr, Token.TYPE.BINOP);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -129,7 +133,7 @@ public class Scanner {
|
||||||
// Identifier or Keyword
|
// Identifier or Keyword
|
||||||
if(isAlpha((char) c)) {
|
if(isAlpha((char) c)) {
|
||||||
for(char n = peek(); isAlpha(n) || isDigit(n) || n == '_';) {
|
for(char n = peek(); isAlpha(n) || isDigit(n) || n == '_';) {
|
||||||
attr += (char) input.read();
|
attr += (char) read();
|
||||||
n = peek();
|
n = peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +147,7 @@ public class Scanner {
|
||||||
// Number
|
// Number
|
||||||
else if(isDigit((char) c)) {
|
else if(isDigit((char) c)) {
|
||||||
for(char n = peek(); isDigit(n);) {
|
for(char n = peek(); isDigit(n);) {
|
||||||
attr += (char) input.read();
|
attr += (char) read();
|
||||||
n = peek();
|
n = peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +160,7 @@ public class Scanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unrecognized Character
|
// Unrecognized Character
|
||||||
else throw new IOException();
|
else throw new ScanningException(col, line);;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -171,12 +175,16 @@ public class Scanner {
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private char peek() throws IOException {
|
private char peek() throws ScanningException {
|
||||||
|
try {
|
||||||
input.mark(1);
|
input.mark(1);
|
||||||
int next = input.read();
|
int next = input.read();
|
||||||
input.reset();
|
input.reset();
|
||||||
|
|
||||||
return next == -1 ? '\0' : (char) next;
|
return next == -1 ? '\0' : (char) next;
|
||||||
|
} catch(IOException e) {
|
||||||
|
throw new ScanningException(col, line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -186,12 +194,34 @@ public class Scanner {
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private boolean peek(char c) throws IOException {
|
private boolean peek(char c) throws ScanningException {
|
||||||
|
try {
|
||||||
input.mark(1);
|
input.mark(1);
|
||||||
int next = input.read();
|
int next = input.read();
|
||||||
input.reset();
|
input.reset();
|
||||||
|
|
||||||
return c == next;
|
return c == next;
|
||||||
|
} catch(IOException e) {
|
||||||
|
throw new ScanningException(col, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alternative reading that keeps track of position.
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private int read() throws ScanningException {
|
||||||
|
try {
|
||||||
|
int next = input.read();
|
||||||
|
if(next != '\n' && next != '\r') col += 1;
|
||||||
|
else { col = 1; line += 1; }
|
||||||
|
|
||||||
|
return next;
|
||||||
|
} catch(IOException e) {
|
||||||
|
throw new ScanningException(col, line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -199,7 +229,8 @@ public class Scanner {
|
||||||
* Consumes input until an end of comment has been reached.
|
* Consumes input until an end of comment has been reached.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private void readComment() throws IOException {
|
private void readComment() throws ScanningException {
|
||||||
|
try {
|
||||||
char prev = '\0', current = '\0';
|
char prev = '\0', current = '\0';
|
||||||
while(prev != '*' || current != '/') {
|
while(prev != '*' || current != '/') {
|
||||||
|
|
||||||
|
@ -209,6 +240,9 @@ public class Scanner {
|
||||||
if(next == -1) throw new IOException();
|
if(next == -1) throw new IOException();
|
||||||
else current = (char) next;
|
else current = (char) next;
|
||||||
}
|
}
|
||||||
|
} catch(IOException e) {
|
||||||
|
throw new ScanningException(col, line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -216,8 +250,12 @@ public class Scanner {
|
||||||
* Consumes input until the end of line is reached
|
* Consumes input until the end of line is reached
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private void readLine() throws IOException {
|
private void readLine() throws ScanningException {
|
||||||
|
try {
|
||||||
for(int n = 0; n != '\n' && n != '\r' && n != -1; n = input.read()) {}
|
for(int n = 0; n != '\n' && n != '\r' && n != -1; n = input.read()) {}
|
||||||
|
} catch(IOException e) {
|
||||||
|
throw new ScanningException(col, line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue