mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 17:35:35 +02:00
Patch for John Camelon:
- added quickParse heuristic to Scanner for handling #if conditionals to avoid throwing ScannerExceptions on undefined preprocessor symbols - added minimal enum support to Parser (though not to DOM or CModel)
This commit is contained in:
parent
a4732cccb3
commit
640ec6e2e6
4 changed files with 134 additions and 43 deletions
|
@ -10,6 +10,7 @@
|
|||
******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.parser;
|
||||
|
||||
import java.util.EmptyStackException;
|
||||
import java.util.Stack;
|
||||
|
||||
public class ExpressionEvaluator extends NullParserCallback {
|
||||
|
@ -104,7 +105,7 @@ public class ExpressionEvaluator extends NullParserCallback {
|
|||
}
|
||||
}
|
||||
|
||||
public Object getResult() {
|
||||
public Object getResult() throws EmptyStackException {
|
||||
return stack.peek();
|
||||
}
|
||||
|
||||
|
|
|
@ -341,7 +341,7 @@ c, quick);
|
|||
classSpecifier(decl);
|
||||
return;
|
||||
case Token.t_enum:
|
||||
// enumSpecifier();
|
||||
enumSpecifier(decl);
|
||||
break;
|
||||
default:
|
||||
break declSpecifiers;
|
||||
|
@ -465,9 +465,6 @@ c, quick);
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
callback.declaratorEnd( declarator );
|
||||
|
@ -590,6 +587,46 @@ c, quick);
|
|||
throw backtrack;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* enumSpecifier
|
||||
* "enum" (name)? "{" (enumerator-list) "}"
|
||||
*/
|
||||
public void enumSpecifier( Object owner ) throws Exception
|
||||
{
|
||||
if( LT(1) != Token.t_enum )
|
||||
throw backtrack;
|
||||
consume();
|
||||
|
||||
// insert beginEnum callback here
|
||||
|
||||
if( LT(1) == Token.tIDENTIFIER )
|
||||
consume();
|
||||
|
||||
|
||||
if( LT(1) == Token.tLBRACE )
|
||||
{
|
||||
consume();
|
||||
// for the time being to get the CModel working ignore the enumerator list
|
||||
int depth = 1;
|
||||
while (depth > 0) {
|
||||
switch (consume().getType()) {
|
||||
case Token.tRBRACE:
|
||||
--depth;
|
||||
break;
|
||||
case Token.tLBRACE:
|
||||
++depth;
|
||||
break;
|
||||
case Token.tEOF:
|
||||
// Oops, no match
|
||||
throw backtrack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// insert endEnum callback here
|
||||
}
|
||||
|
||||
/**
|
||||
* classSpecifier
|
||||
* : classKey name (baseClause)? "{" (memberSpecification)* "}"
|
||||
|
@ -1232,7 +1269,8 @@ c, quick);
|
|||
}
|
||||
|
||||
public void primaryExpression() throws Exception {
|
||||
switch (LT(1)) {
|
||||
int type = LT(1);
|
||||
switch (type) {
|
||||
// TO DO: we need more literals...
|
||||
case Token.tINTEGER:
|
||||
callback.expressionTerminal(consume());
|
||||
|
@ -1240,6 +1278,9 @@ c, quick);
|
|||
case Token.tSTRING:
|
||||
callback.expressionTerminal(consume());
|
||||
return;
|
||||
case Token.tIDENTIFIER:
|
||||
callback.expressionTerminal(consume());
|
||||
return;
|
||||
case Token.t_this:
|
||||
consume();
|
||||
return;
|
||||
|
|
|
@ -526,14 +526,14 @@ public class Scanner implements IScanner {
|
|||
case PreprocessorDirectives.IF :
|
||||
// get the rest of the line
|
||||
String expression = getRestOfPreprocessorLine();
|
||||
|
||||
boolean expressionEvalResult =
|
||||
evaluateExpression(expression);
|
||||
|
||||
boolean expressionEvalResult = evaluateExpression(expression);
|
||||
passOnToClient = branches.poundif( expressionEvalResult );
|
||||
c = getChar();
|
||||
continue;
|
||||
|
||||
|
||||
|
||||
case PreprocessorDirectives.IFDEF :
|
||||
skipOverWhitespace();
|
||||
String definition = getNextIdentifier();
|
||||
|
@ -588,7 +588,7 @@ public class Scanner implements IScanner {
|
|||
throw new ScannerException("Malformed #elsif clause");
|
||||
|
||||
boolean elsifResult =
|
||||
evaluateExpression(elsifExpression);
|
||||
evaluateExpression(elsifExpression );
|
||||
|
||||
passOnToClient = branches.poundelif( elsifResult );
|
||||
c = getChar();
|
||||
|
@ -1089,42 +1089,59 @@ public class Scanner implements IScanner {
|
|||
return branches.getDepth();
|
||||
}
|
||||
|
||||
protected boolean evaluateExpression(String expression)
|
||||
protected boolean evaluateExpression(String expression )
|
||||
throws ScannerException {
|
||||
Object expressionEvalResult = null;
|
||||
try {
|
||||
ExpressionEvaluator evaluator = new ExpressionEvaluator();
|
||||
Scanner trial =
|
||||
new Scanner(
|
||||
new StringReader(expression),
|
||||
EXPRESSION,
|
||||
definitions);
|
||||
Parser parser = new Parser(trial, evaluator);
|
||||
parser.expression();
|
||||
expressionEvalResult = evaluator.getResult();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception from Parser : " + e.toString());
|
||||
|
||||
if( quickScan )
|
||||
{
|
||||
if( expression.trim().equals( "0" ) )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (expressionEvalResult == null)
|
||||
throw new ScannerException(
|
||||
"Expression "
|
||||
+ expression
|
||||
+ " evaluates to an undefined value");
|
||||
|
||||
if (expressionEvalResult.getClass() == java.lang.Integer.class) {
|
||||
int i = ((Integer) expressionEvalResult).intValue();
|
||||
if (i == 0) {
|
||||
return false;
|
||||
else
|
||||
{
|
||||
Object expressionEvalResult = null;
|
||||
try {
|
||||
ExpressionEvaluator evaluator = new ExpressionEvaluator();
|
||||
Scanner trial =
|
||||
new Scanner(
|
||||
new StringReader(expression),
|
||||
EXPRESSION,
|
||||
definitions);
|
||||
Parser parser = new Parser(trial, evaluator);
|
||||
parser.expression();
|
||||
|
||||
expressionEvalResult = evaluator.getResult();
|
||||
|
||||
} catch (Exception e ) {
|
||||
throw new ScannerException(
|
||||
"Expression "
|
||||
+ expression
|
||||
+ " evaluates to an undefined value");
|
||||
} finally
|
||||
{
|
||||
if (expressionEvalResult == null)
|
||||
throw new ScannerException(
|
||||
"Expression "
|
||||
+ expression
|
||||
+ " evaluates to an undefined value");
|
||||
}
|
||||
|
||||
|
||||
if (expressionEvalResult.getClass() == java.lang.Integer.class) {
|
||||
int i = ((Integer) expressionEvalResult).intValue();
|
||||
if (i == 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else if (
|
||||
expressionEvalResult.getClass() == java.lang.Boolean.class) {
|
||||
return ((Boolean) expressionEvalResult).booleanValue();
|
||||
} else {
|
||||
throw new ScannerException(
|
||||
"Unexpected expression type - we do not expect "
|
||||
+ expressionEvalResult.getClass().getName());
|
||||
}
|
||||
return true;
|
||||
} else if (
|
||||
expressionEvalResult.getClass() == java.lang.Boolean.class) {
|
||||
return ((Boolean) expressionEvalResult).booleanValue();
|
||||
} else {
|
||||
throw new ScannerException(
|
||||
"Unexpected expression type - we do not expect "
|
||||
+ expressionEvalResult.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -811,6 +811,38 @@ public class ScannerTestCase extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
public void testQuickScan()
|
||||
{
|
||||
try
|
||||
{
|
||||
initializeScanner( "#if X + 5 < 7\n int found = 1;\n#endif" );
|
||||
scanner.setQuickScan( true );
|
||||
validateToken( Token.t_int );
|
||||
validateIdentifier( "found" );
|
||||
validateToken( Token.tASSIGN );
|
||||
validateInteger( "1");
|
||||
validateToken( Token.tSEMI );
|
||||
validateEOF();
|
||||
|
||||
}
|
||||
catch( ScannerException se )
|
||||
{
|
||||
fail( EXCEPTION_THROWN + se.getMessage() );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
initializeScanner( "#if 0\n int error = 666;\n#endif" );
|
||||
scanner.setQuickScan( true );
|
||||
validateEOF();
|
||||
}
|
||||
catch( ScannerException se )
|
||||
{
|
||||
fail( EXCEPTION_THROWN + se.getMessage() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testInclusions()
|
||||
{
|
||||
try
|
||||
|
|
Loading…
Add table
Reference in a new issue