}
protected final Token parse_main() throws IOException, LexerException {
for (; ; ) {
Token tok;
if (!isActive()) {
try {
/* XXX Tell lexer to ignore warnings. */
sourceManager.getSource().setActive(false);
tok = retrieveTokenFromSource();
} finally {
/* XXX Tell lexer to stop ignoring warnings. */
if (sourceManager.getSource() != null)
sourceManager.getSource().setActive(true);
}
switch (tok.getType()) {
case HASH:
case NL:
/* The preprocessor has to take action here. */
break;
case EOF:
case WHITESPACE:
return tok;
case CCOMMENT:
case CPPCOMMENT:
// Patch up to preserve whitespace.
if (getFeature(Feature.KEEPALLCOMMENTS))
return tok;
if (!isActive())
return toWhitespace(tok);
if (getFeature(Feature.KEEPCOMMENTS))
return tok;
return toWhitespace(tok);
default:
// Return NL to preserve whitespace.
/* XXX This might lose a comment. */
return source_skipline(false);
}
} else {
tok = retrieveTokenFromSource();
}
LEX:
switch (tok.getType()) {
case EOF:
/* Pop the stacks. */
return tok;
case WHITESPACE:
case NL:
return tok;
case CCOMMENT:
case CPPCOMMENT:
return tok;
case '!':
case '%':
case '&':
case '(':
case ')':
case '*':
case '+':
case ',':
case '-':
case '/':
case ':':
case ';':
case '<':
case '=':
case '>':
case '?':
case '[':
case ']':
case '^':
case '{':
case '|':
case '}':
case '~':
case '.':
/* From Olivier Chafik for Objective C? */
case '@':
/* The one remaining ASCII, might as well. */
case '`':
// case '#':
case AND_EQ:
case ARROW:
case CHARACTER:
case DEC:
case DIV_EQ:
case ELLIPSIS:
case EQ:
case GE:
case HEADER: /* Should only arise from include() */
case INC:
case LAND:
case LE:
case LOR:
case LSH:
case LSH_EQ:
case SUB_EQ:
case MOD_EQ:
case MULT_EQ:
case NE:
case OR_EQ:
case PLUS_EQ:
case RANGE:
case RSH:
case RSH_EQ:
case STRING:
case XOR_EQ:
return tok;
case INTEGER:
return tok;
case IDENTIFIER:
// apply macro (in visible code)
MacroExpansion<MacroData>[] m = macros.getApplicableMacroExpansions(tok
.getText(), state.getFullPresenceCondition());
if (m.length == 0)
return tok;
if (!sourceManager.getSource().mayExpand(tok.getText())
|| !tok.mayExpand())
return tok;
if (macro_expandToken(tok.getText(), m, tok, processing_include))
break;
return tok;
case P_LINE:
if (getFeature(Feature.LINEMARKERS))
return tok;
break;
case INVALID:
if (getFeature(Feature.CSYNTAX))
error(tok, String.valueOf(tok.getValue()));
return tok;
case HASH:
tok = source_token_nonwhite();
// (new Exception("here")).printStackTrace();
switch (tok.getType()) {
case NL:
break LEX; /* Some code has #\n */
case IDENTIFIER:
break;
default:
//no warning, interpreted as comment
// warning(tok, "Preprocessor directive not a word "
// + tok.getText() + ", skipping line");
return source_skipline(false);
}
// System.out.println(previousToken);
Integer _ppcmd = ppcmds.get(tok.getText());
if (_ppcmd == null) {
warning(tok, "Unknown preprocessor directive "
+ tok.getText() + ", skipping line");
return source_skipline(false);
}
int ppcmd = _ppcmd.intValue();
// PP:
switch (ppcmd) {
case PP_DEFINE:
if (!isActive())
return source_skipline(false);
else
return parse_define();
// break;
case PP_UNDEF:
if (!isActive())
return source_skipline(false);
else
return parse_undef();
// break;
case PP_INCLUDE:
if (!isActive())
return source_skipline(false);
else {
Token ret_tok = parse_include(false);
assert !processing_include;
return ret_tok;
}
// break;
case PP_INCLUDE_NEXT:
if (!isActive())
return source_skipline(false);
if (!getFeature(Feature.INCLUDENEXT)) {
error(tok, "Directive include_next not enabled");
return source_skipline(false);
}
Token ret_tok = parse_include(true);
assert !processing_include;
return ret_tok;
// break;
/**
* error tokens are not processed by the jcpp but left for
* the type system
*/
case PP_WARNING:
case PP_ERROR:
if (!isActive())
return source_skipline(false);
else
// cppError(tok, ppcmd == PP_ERROR);
return parseErrorToken(tok, ppcmd == PP_ERROR);
case PP_IF:
push_state();
expr_token = null;
if (isParentActive()) {
FeatureExpr localFeatureExpr = parse_featureExpr();
state.putLocalFeature(localFeatureExpr, macros);
tok = expr_token(true); /* unget */
if (tok.getType() != NL)
source_skipline(isParentActive());
} else {
state.putLocalFeature(FeatureExprLib.False(), macros);
source_skipline(false);
}
return ifdefPrinter.startIf(tok, isParentActive(), state);
// break;
case PP_ELIF:
if (state.sawElse()) {
error(tok, "#elif after #" + "else");
return source_skipline(false);
} else {
expr_token = null;
// parse with parents state to allow macro expansion
State oldState = state;
state = state.parent;
FeatureExpr localFeaturExpr = isActive() ? parse_featureExpr() : FeatureExprLib.False();
state = oldState;
state.processElIf();
state.putLocalFeature(localFeaturExpr, macros);
tok = expr_token(true); /* unget */
if (tok.getType() != NL)
source_skipline(isParentActive());
return ifdefPrinter.startElIf(tok, isParentActive(),
state);
}
// break;
case PP_ELSE:
if (state.sawElse()) {
error(tok, "#" + "else after #" + "else");
return source_skipline(false);
} else {
state.setSawElse();
source_skipline(warnings.contains(Warning.ENDIF_LABELS));
return ifdefPrinter.startElIf(tok, isParentActive(),
state);
}
// break;
case PP_IFDEF:
push_state();
tok = source_token_nonwhite();
// System.out.println("ifdef " + tok);
if (tok.getType() != IDENTIFIER) {
error(tok, "Expected identifier, not " + tok.getText());
return source_skipline(false);
} else {
FeatureExpr localFeatureExpr2 = parse_ifdefExpr(tok
.getText());
state.putLocalFeature(
isParentActive() ? localFeatureExpr2
: FeatureExprLib.False(), macros);
// return
if (tok.getType() != NL)
source_skipline(isParentActive());
return ifdefPrinter.startIf(tok, isParentActive(),
state);
}
// break;
case PP_IFNDEF:
push_state();
tok = source_token_nonwhite();
if (tok.getType() != IDENTIFIER) {
error(tok, "Expected identifier, not " + tok.getText());
return source_skipline(false);
} else {
FeatureExpr localFeatureExpr3 = parse_ifndefExpr(tok
.getText());
state.putLocalFeature(
isParentActive() ? localFeatureExpr3
: FeatureExprLib.False(), macros);
if (tok.getType() != NL)
source_skipline(isParentActive());
return ifdefPrinter.startIf(tok, isParentActive(),
state);
}
// break;
case PP_ENDIF:
pop_state();
Token l = source_skipline(warnings
.contains(Warning.ENDIF_LABELS));
return ifdefPrinter.endIf(l);
// break;
case PP_LINE: