1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 18:26:01 +02:00

Changed EOF token into a backtrack exception.

This commit is contained in:
Doug Schaefer 2003-03-17 19:48:49 +00:00
parent 1843a71939
commit c885b918e3
7 changed files with 113 additions and 78 deletions

View file

@ -1,3 +1,7 @@
2003-03-17 Doug Schaefer
Changed EOF to be a Backtrack exception instead of a token so simplify
error handling.
2003-03-13 John Camelon 2003-03-13 John Camelon
Moved ## token to IScanner from Scanner. Moved ## token to IScanner from Scanner.
Updated IParserCallback and implementations to deal with Elaborated Type Specifiers. Updated IParserCallback and implementations to deal with Elaborated Type Specifiers.

View file

@ -26,7 +26,7 @@ public interface IScanner {
public void addIncludePath(String includePath); public void addIncludePath(String includePath);
public void overwriteIncludePath( List newIncludePaths ); public void overwriteIncludePath( List newIncludePaths );
public Token nextToken() throws ScannerException; public Token nextToken() throws ScannerException, Parser.EndOfFile;
public void setQuickScan(boolean qs); public void setQuickScan(boolean qs);
public void setCallback(IParserCallback c); public void setCallback(IParserCallback c);

View file

@ -32,7 +32,6 @@ public class Parser {
quickParse = quick; quickParse = quick;
scanner.setQuickScan(quick); scanner.setQuickScan(quick);
scanner.setCallback(c); scanner.setCallback(c);
//fetchToken();
} }
public Parser(IScanner s, IParserCallback c) throws Exception { public Parser(IScanner s, IParserCallback c) throws Exception {
@ -78,13 +77,16 @@ c, quick);
public void translationUnit() throws Exception { public void translationUnit() throws Exception {
Object translationUnit = callback.translationUnitBegin(); Object translationUnit = callback.translationUnitBegin();
Token lastBacktrack = null; Token lastBacktrack = null;
Token lastToken = null; Token lastToken;
while (LT(1) != Token.tEOF) { while (true) {
try { try {
lastToken = currToken; lastToken = LA(1);
declaration( translationUnit ); declaration( translationUnit );
if( currToken == lastToken ) if( LA(1) == lastToken )
consumeToNextSemicolon(); consumeToNextSemicolon();
} catch (EndOfFile e) {
// Good
break;
} catch (Backtrack b) { } catch (Backtrack b) {
// Mark as failure and try to reach a recovery point // Mark as failure and try to reach a recovery point
parsePassed = false; parsePassed = false;
@ -102,12 +104,11 @@ c, quick);
callback.translationUnitEnd(translationUnit); callback.translationUnitEnd(translationUnit);
} }
protected void consumeToNextSemicolon() { protected void consumeToNextSemicolon() throws EndOfFile {
for (int t = LT(1); t != Token.tEOF; t = LT(1)) { consume();
// TODO - we should really check for matching braces too
while (LT(1) != Token.tSEMI) {
consume(); consume();
// TO DO: we should really check for matching braces too
if (t == Token.tSEMI)
break;
} }
} }
@ -205,9 +206,7 @@ c, quick);
// and look for the left brace; // and look for the left brace;
consume(); consume();
while (LT(1) != Token.tLBRACE) { while (LT(1) != Token.tLBRACE) {
if (consume().getType() == Token.tEOF) consume();
// Oops, couldn't find it
throw backtrack;
} }
// Falling through on purpose // Falling through on purpose
case Token.tLBRACE: case Token.tLBRACE:
@ -225,9 +224,6 @@ c, quick);
case Token.tLBRACE: case Token.tLBRACE:
++depth; ++depth;
break; break;
case Token.tEOF:
// Oops, no match
throw backtrack;
} }
} }
} else { } else {
@ -461,9 +457,6 @@ c, quick);
case Token.tLBRACE: case Token.tLBRACE:
++depth; ++depth;
break; break;
case Token.tEOF:
// Oops, no match
throw backtrack;
} }
} }
} }
@ -529,6 +522,7 @@ c, quick);
// parameterDeclarationClause // parameterDeclarationClause
Object clause = callback.argumentsBegin(declarator); Object clause = callback.argumentsBegin(declarator);
consume(); consume();
boolean seenParameter = false;
parameterDeclarationLoop: parameterDeclarationLoop:
for (;;) { for (;;) {
switch (LT(1)) { switch (LT(1)) {
@ -540,9 +534,13 @@ c, quick);
break; break;
case Token.tCOMMA: case Token.tCOMMA:
consume(); consume();
seenParameter = false;
break; break;
default: default:
if (seenParameter)
throw backtrack;
parameterDeclaration( clause ); parameterDeclaration( clause );
seenParameter = true;
} }
} }
callback.argumentsEnd(clause); callback.argumentsEnd(clause);
@ -633,9 +631,6 @@ c, quick);
case Token.tLBRACE: case Token.tLBRACE:
++depth; ++depth;
break; break;
case Token.tEOF:
// Oops, no match
throw backtrack;
} }
} }
} }
@ -1362,24 +1357,32 @@ c, quick);
} }
// Backtracking // Backtracking
private static class Backtrack extends Exception { public static class Backtrack extends Exception {
} }
private static Backtrack backtrack = new Backtrack(); private static Backtrack backtrack = new Backtrack();
// End of file generally causes backtracking
public static class EndOfFile extends Backtrack {
}
public static EndOfFile endOfFile = new EndOfFile();
// Token management // Token management
private IScanner scanner; private IScanner scanner;
private Token currToken; private Token currToken;
private Token fetchToken() { private Token fetchToken() throws EndOfFile {
try { try {
return scanner.nextToken(); return scanner.nextToken();
} catch (EndOfFile e) {
throw e;
} catch (Exception e) { } catch (Exception e) {
return null; return null;
} }
} }
protected Token LA(int i) { protected Token LA(int i) throws EndOfFile {
if (i < 1) if (i < 1)
// can't go backwards // can't go backwards
return null; return null;
@ -1390,34 +1393,37 @@ c, quick);
Token retToken = currToken; Token retToken = currToken;
for (; i > 1; --i) { for (; i > 1; --i) {
if (retToken.getNext() == null)
fetchToken();
retToken = retToken.getNext(); retToken = retToken.getNext();
if (retToken == null)
retToken = fetchToken();
} }
return retToken; return retToken;
} }
protected int LT(int i) { protected int LT(int i) throws EndOfFile {
return LA(i).type; return LA(i).type;
} }
protected Token consume() { protected Token consume() throws EndOfFile {
if (currToken.getNext() == null) if (currToken == null)
fetchToken(); currToken = fetchToken();
Token retToken = currToken; Token retToken = currToken;
currToken = currToken.getNext(); currToken = currToken.getNext();
return retToken; return retToken;
} }
protected Token consume(int type) throws Exception { protected Token consume(int type) throws Backtrack {
if (LT(1) == type) if (LT(1) == type)
return consume(); return consume();
else else
throw backtrack; throw backtrack;
} }
protected Token mark() { protected Token mark() throws EndOfFile {
if (currToken == null)
currToken = fetchToken();
return currToken; return currToken;
} }

View file

@ -366,6 +366,9 @@ public class Scanner implements IScanner {
private int getChar() { private int getChar() {
int c = NOCHAR; int c = NOCHAR;
if (currentContext == null)
// past the end of file
return c;
boolean done; boolean done;
do { do {
@ -436,12 +439,12 @@ public class Scanner implements IScanner {
public Token nextToken() throws ScannerException { public Token nextToken() throws ScannerException, Parser.EndOfFile {
return nextToken( true ); return nextToken( true );
} }
protected Token nextToken( boolean pasting ) throws ScannerException protected Token nextToken( boolean pasting ) throws ScannerException, Parser.EndOfFile
{ {
count++; count++;
@ -1102,10 +1105,9 @@ public class Scanner implements IScanner {
break; break;
} }
return newToken( // Bad character
Token.tEOF, // TODO - does this need it's own exception
"Bad Char: " + (char) c, throw Parser.endOfFile;
currentContext);
} }
} }
@ -1113,9 +1115,7 @@ public class Scanner implements IScanner {
throw new ScannerException("End of file encountered without terminating #endif"); throw new ScannerException("End of file encountered without terminating #endif");
// we're done // we're done
if (currentToken != null) throw Parser.endOfFile;
currentToken.setNext(Token.EOF);
return Token.EOF;
} }
static { static {
@ -1254,7 +1254,8 @@ public class Scanner implements IScanner {
ExpressionEvaluator evaluator = new ExpressionEvaluator(); ExpressionEvaluator evaluator = new ExpressionEvaluator();
Scanner trial = Scanner trial =
new Scanner( new Scanner(
new StringReader(expression), // Semicolon makes this valid C (hopefully)
new StringReader(expression + ";"),
EXPRESSION, EXPRESSION,
definitions); definitions);
Parser parser = new Parser(trial, evaluator); Parser parser = new Parser(trial, evaluator);
@ -1373,7 +1374,7 @@ public class Scanner implements IScanner {
handleInclusion(f.trim(), useIncludePath ); handleInclusion(f.trim(), useIncludePath );
} }
protected void poundDefine() throws ScannerException { protected void poundDefine() throws ScannerException, Parser.EndOfFile {
skipOverWhitespace(); skipOverWhitespace();
// definition // definition
String key = getNextIdentifier(); String key = getNextIdentifier();
@ -1424,9 +1425,13 @@ public class Scanner implements IScanner {
null); null);
Token t = helperScanner.nextToken(false); Token t = helperScanner.nextToken(false);
while (t.type != Token.tEOF) { try {
macroReplacementTokens.add(t); while (true) {
t = helperScanner.nextToken(false); macroReplacementTokens.add(t);
t = helperScanner.nextToken(false);
}
} catch (Parser.EndOfFile e) {
// Good
} }
IMacroDescriptor descriptor = new MacroDescriptor(); IMacroDescriptor descriptor = new MacroDescriptor();

View file

@ -24,8 +24,6 @@ public class Token {
image = i; image = i;
} }
public static Token EOF = new Token(Token.tEOF, "<EOF>");
public String toString() public String toString()
{ {
return "Token type=" + type + " image =" + image + " offset=" + offset; return "Token type=" + type + " image =" + image + " offset=" + offset;
@ -47,7 +45,6 @@ public class Token {
public void setNext(Token t) { next = t; } public void setNext(Token t) { next = t; }
// Token types // Token types
static public final int tEOF = 0;
static public final int tIDENTIFIER = 1; static public final int tIDENTIFIER = 1;
static public final int tINTEGER = 2; static public final int tINTEGER = 2;
static public final int tCOLONCOLON = 3; static public final int tCOLONCOLON = 3;

View file

@ -25,17 +25,17 @@ public class ExprEvalTest extends TestCase {
} }
public void testInteger() throws Exception { public void testInteger() throws Exception {
runTest("5", 5); runTest("5;", 5);
} }
public void testRelational() throws Exception { public void testRelational() throws Exception {
runTest("1 < 2", 1); runTest("1 < 2;", 1);
runTest("2 < 1", 0); runTest("2 < 1;", 0);
runTest("2 == 1 + 1", 1); runTest("2 == 1 + 1;", 1);
runTest("2 != 1 + 1", 0); runTest("2 != 1 + 1;", 0);
} }
public void testBracketed() throws Exception { public void testBracketed() throws Exception {
runTest("2 * (3 + 4)", 14); runTest("2 * (3 + 4);", 14);
} }
} }

View file

@ -8,6 +8,7 @@ import junit.framework.TestCase;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.eclipse.cdt.internal.core.parser.IMacroDescriptor; import org.eclipse.cdt.internal.core.parser.IMacroDescriptor;
import org.eclipse.cdt.internal.core.parser.Parser;
import org.eclipse.cdt.internal.core.parser.Scanner; import org.eclipse.cdt.internal.core.parser.Scanner;
import org.eclipse.cdt.internal.core.parser.ScannerException; import org.eclipse.cdt.internal.core.parser.ScannerException;
import org.eclipse.cdt.internal.core.parser.Token; import org.eclipse.cdt.internal.core.parser.Token;
@ -176,16 +177,19 @@ public class ScannerTestCase extends TestCase
try try
{ {
Token t= scanner.nextToken(); Token t= scanner.nextToken();
while ((t != null) && (t.type != Token.tEOF)) while (t != null)
{ {
if (verbose) if (verbose)
System.out.println("Token t = " + t); System.out.println("Token t = " + t);
if ((t.type < Token.tEOF) || (t.type > Token.tLAST)) if ((t.type < 1) || (t.type > Token.tLAST))
System.out.println("Unknown type for token " + t); System.out.println("Unknown type for token " + t);
t= scanner.nextToken(); t= scanner.nextToken();
} }
} }
catch (Parser.EndOfFile e)
{
}
catch (ScannerException se) catch (ScannerException se)
{ {
throw se; throw se;
@ -245,7 +249,7 @@ public class ScannerTestCase extends TestCase
validateToken(Token.tASSIGN); validateToken(Token.tASSIGN);
validateInteger("5"); validateInteger("5");
validateToken(Token.tSEMI); validateToken(Token.tSEMI);
validateToken(Token.tEOF); validateEOF();
// the case we were failing against in ctype.h // the case we were failing against in ctype.h
// this is a definition, not a macro! // this is a definition, not a macro!
@ -445,7 +449,7 @@ public class ScannerTestCase extends TestCase
validateEOF(); validateEOF();
initializeScanner("#define SYMBOL 5\n#ifndef SYMBOL\nint counter(SYMBOL);\n#endif"); initializeScanner("#define SYMBOL 5\n#ifndef SYMBOL\nint counter(SYMBOL);\n#endif");
validateToken(Token.tEOF); validateEOF();
initializeScanner("#ifndef DEFINED\n#define DEFINED 100\n#endif\nint count = DEFINED;"); initializeScanner("#ifndef DEFINED\n#define DEFINED 100\n#endif\nint count = DEFINED;");
validateToken(Token.t_int); validateToken(Token.t_int);
@ -522,7 +526,7 @@ public class ScannerTestCase extends TestCase
validateBalance(); validateBalance();
initializeScanner("#ifndef FOO\n#define FOO 4\n#else\n#undef FOO\n#define FOO 6\n#endif"); initializeScanner("#ifndef FOO\n#define FOO 4\n#else\n#undef FOO\n#define FOO 6\n#endif");
validateToken(Token.tEOF); validateEOF();
validateBalance(); validateBalance();
validateDefinition("FOO", "4"); validateDefinition("FOO", "4");
@ -833,7 +837,7 @@ public class ScannerTestCase extends TestCase
} }
} }
public void testQuickScan() public void testQuickScan() throws Parser.EndOfFile
{ {
try try
{ {
@ -970,29 +974,45 @@ public class ScannerTestCase extends TestCase
public void validateIdentifier(String expectedImage) throws ScannerException public void validateIdentifier(String expectedImage) throws ScannerException
{ {
Token t= scanner.nextToken(); try {
assertTrue(t.type == Token.tIDENTIFIER); Token t= scanner.nextToken();
assertTrue(t.image.equals(expectedImage)); assertTrue(t.type == Token.tIDENTIFIER);
assertTrue(t.image.equals(expectedImage));
} catch (Parser.EndOfFile e) {
assertTrue(false);
}
} }
public void validateInteger(String expectedImage) throws ScannerException public void validateInteger(String expectedImage) throws ScannerException
{ {
Token t= scanner.nextToken(); try {
assertTrue(t.type == Token.tINTEGER); Token t= scanner.nextToken();
assertTrue(t.image.equals(expectedImage)); assertTrue(t.type == Token.tINTEGER);
assertTrue(t.image.equals(expectedImage));
} catch (Parser.EndOfFile e) {
assertTrue(false);
}
} }
public void validateString(String expectedImage) throws ScannerException public void validateString(String expectedImage) throws ScannerException
{ {
Token t= scanner.nextToken(); try {
assertTrue(t.type == Token.tSTRING); Token t= scanner.nextToken();
assertTrue(t.image.equals(expectedImage)); assertTrue(t.type == Token.tSTRING);
assertTrue(t.image.equals(expectedImage));
} catch (Parser.EndOfFile e) {
assertTrue(false);
}
} }
public void validateToken(int tokenType) throws ScannerException public void validateToken(int tokenType) throws ScannerException
{ {
Token t= scanner.nextToken(); try {
assertTrue(t.type == tokenType); Token t= scanner.nextToken();
assertTrue(t.type == tokenType);
} catch (Parser.EndOfFile e) {
assertTrue(false);
}
} }
public void validateBalance(int expected) public void validateBalance(int expected)
@ -1007,7 +1027,10 @@ public class ScannerTestCase extends TestCase
public void validateEOF() throws ScannerException public void validateEOF() throws ScannerException
{ {
validateToken(Token.tEOF); try {
assertNull(scanner.nextToken());
} catch (Parser.EndOfFile e) {
}
} }
public void validateDefinition(String name, String value) public void validateDefinition(String name, String value)
@ -1022,7 +1045,7 @@ public class ScannerTestCase extends TestCase
{ {
String definition= null; String definition= null;
definition= (String) scanner.getDefinition(name); definition= (String) scanner.getDefinition(name);
this.assertNotNull(definition); assertNotNull(definition);
int intValue= (Integer.valueOf((String) definition)).intValue(); int intValue= (Integer.valueOf((String) definition)).intValue();
assertEquals(value, intValue); assertEquals(value, intValue);
} }
@ -1105,7 +1128,7 @@ public class ScannerTestCase extends TestCase
validateInteger( "0"); validateInteger( "0");
validateToken( Token.tSEMI ); validateToken( Token.tSEMI );
validateToken( Token.tRBRACE ); validateToken( Token.tRBRACE );
validateToken( Token.tEOF ); validateEOF();
} }
} catch( ScannerException se ) } catch( ScannerException se )
{ {