1) Allow '\' before a non-newline as a token in the preprocessor, and 2) localize line-continuation to just the pp scanner.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24530 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-12-16 23:58:15 +00:00
parent 27151efa71
commit bd95819123
10 changed files with 245 additions and 78 deletions

View file

@ -1484,6 +1484,7 @@ bool TParseContext::lineContinuationCheck(TSourceLoc loc, bool endOfComment)
if (messages & EShMsgRelaxedErrors) {
warn(loc, "not allowed in this version", message, "");
return true;
} else {
requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, message);
profileRequires(loc, EEsProfile, 300, 0, message);

View file

@ -478,74 +478,82 @@ void TScanContext::fillInKeywordMap()
int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
{
parserToken = &token;
TPpToken ppToken;
tokenText = pp->tokenize(&ppToken);
if (tokenText == 0)
return 0;
do {
parserToken = &token;
TPpToken ppToken;
tokenText = pp->tokenize(&ppToken);
if (tokenText == 0)
return 0;
loc = ppToken.loc;
parserToken->sType.lex.loc = loc;
switch (ppToken.token) {
case ';': afterType = false; return SEMICOLON;
case ',': afterType = false; return COMMA;
case ':': return COLON;
case '=': afterType = false; return EQUAL;
case '(': afterType = false; return LEFT_PAREN;
case ')': afterType = false; return RIGHT_PAREN;
case '.': field = true; return DOT;
case '!': return BANG;
case '-': return DASH;
case '~': return TILDE;
case '+': return PLUS;
case '*': return STAR;
case '/': return SLASH;
case '%': return PERCENT;
case '<': return LEFT_ANGLE;
case '>': return RIGHT_ANGLE;
case '|': return VERTICAL_BAR;
case '^': return CARET;
case '&': return AMPERSAND;
case '?': return QUESTION;
case '[': return LEFT_BRACKET;
case ']': return RIGHT_BRACKET;
case '{': return LEFT_BRACE;
case '}': return RIGHT_BRACE;
loc = ppToken.loc;
parserToken->sType.lex.loc = loc;
switch (ppToken.token) {
case ';': afterType = false; return SEMICOLON;
case ',': afterType = false; return COMMA;
case ':': return COLON;
case '=': afterType = false; return EQUAL;
case '(': afterType = false; return LEFT_PAREN;
case ')': afterType = false; return RIGHT_PAREN;
case '.': field = true; return DOT;
case '!': return BANG;
case '-': return DASH;
case '~': return TILDE;
case '+': return PLUS;
case '*': return STAR;
case '/': return SLASH;
case '%': return PERCENT;
case '<': return LEFT_ANGLE;
case '>': return RIGHT_ANGLE;
case '|': return VERTICAL_BAR;
case '^': return CARET;
case '&': return AMPERSAND;
case '?': return QUESTION;
case '[': return LEFT_BRACKET;
case ']': return RIGHT_BRACKET;
case '{': return LEFT_BRACE;
case '}': return RIGHT_BRACE;
case '\\':
parseContext.error(loc, "illegal use of escape character", "\\", "");
break;
case CPP_AND_OP: return AND_OP;
case CPP_SUB_ASSIGN: return SUB_ASSIGN;
case CPP_MOD_ASSIGN: return MOD_ASSIGN;
case CPP_ADD_ASSIGN: return ADD_ASSIGN;
case CPP_DIV_ASSIGN: return DIV_ASSIGN;
case CPP_MUL_ASSIGN: return MUL_ASSIGN;
case CPP_EQ_OP: return EQ_OP;
case CPP_XOR_OP: return XOR_OP;
case CPP_GE_OP: return GE_OP;
case CPP_RIGHT_OP: return RIGHT_OP;
case CPP_LE_OP: return LE_OP;
case CPP_LEFT_OP: return LEFT_OP;
case CPP_DEC_OP: return DEC_OP;
case CPP_NE_OP: return NE_OP;
case CPP_OR_OP: return OR_OP;
case CPP_INC_OP: return INC_OP;
case CPP_RIGHT_ASSIGN: return RIGHT_ASSIGN;
case CPP_LEFT_ASSIGN: return LEFT_ASSIGN;
case CPP_AND_ASSIGN: return AND_ASSIGN;
case CPP_OR_ASSIGN: return OR_ASSIGN;
case CPP_XOR_ASSIGN: return XOR_ASSIGN;
case CPP_AND_OP: return AND_OP;
case CPP_SUB_ASSIGN: return SUB_ASSIGN;
case CPP_MOD_ASSIGN: return MOD_ASSIGN;
case CPP_ADD_ASSIGN: return ADD_ASSIGN;
case CPP_DIV_ASSIGN: return DIV_ASSIGN;
case CPP_MUL_ASSIGN: return MUL_ASSIGN;
case CPP_EQ_OP: return EQ_OP;
case CPP_XOR_OP: return XOR_OP;
case CPP_GE_OP: return GE_OP;
case CPP_RIGHT_OP: return RIGHT_OP;
case CPP_LE_OP: return LE_OP;
case CPP_LEFT_OP: return LEFT_OP;
case CPP_DEC_OP: return DEC_OP;
case CPP_NE_OP: return NE_OP;
case CPP_OR_OP: return OR_OP;
case CPP_INC_OP: return INC_OP;
case CPP_RIGHT_ASSIGN: return RIGHT_ASSIGN;
case CPP_LEFT_ASSIGN: return LEFT_ASSIGN;
case CPP_AND_ASSIGN: return AND_ASSIGN;
case CPP_OR_ASSIGN: return OR_ASSIGN;
case CPP_XOR_ASSIGN: return XOR_ASSIGN;
case CPP_INTCONSTANT: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT;
case CPP_UINTCONSTANT: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT;
case CPP_FLOATCONSTANT: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT;
case CPP_DOUBLECONSTANT: parserToken->sType.lex.d = ppToken.dval; return DOUBLECONSTANT;
case CPP_IDENTIFIER: return tokenizeIdentifier();
case CPP_INTCONSTANT: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT;
case CPP_UINTCONSTANT: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT;
case CPP_FLOATCONSTANT: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT;
case CPP_DOUBLECONSTANT: parserToken->sType.lex.d = ppToken.dval; return DOUBLECONSTANT;
case CPP_IDENTIFIER: return tokenizeIdentifier();
case EOF: return 0;
case EOF: return 0;
default:
parseContext.infoSink.info.message(EPrefixInternalError, "Unknown PP token", loc);
return 0;
}
default:
char buf[2];
buf[0] = ppToken.token;
buf[1] = 0;
parseContext.error(loc, "unexpected token", buf, "");
break;
}
} while (true);
}
int TScanContext::tokenizeIdentifier()

View file

@ -190,12 +190,6 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
TSourceLoc defineLoc = ppToken->loc; // because ppToken is going to go to the next line before we report errors
mac.body = new TokenStream;
while (token != '\n') {
if (token == '\\') {
parseContext.lineContinuationCheck(ppToken->loc, false);
token = currentInput->scan(this, currentInput, ppToken);
if (token == '\n' || token == '\r')
token = currentInput->scan(this, currentInput, ppToken);
}
RecordToken(mac.body, token, ppToken);
token = currentInput->scan(this, currentInput, ppToken);
if (token != '\n' && ppToken->space)

View file

@ -281,20 +281,29 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
case 'k': case 'l': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z': case '\\' :
case 'z': case '\\':
do {
if (ch == '\\') {
// escaped character
pp->parseContext.lineContinuationCheck(ppToken->loc, false);
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
if (ch == '\r' || ch == '\n') {
pp->parseContext.lineContinuationCheck(ppToken->loc, false);
int nextch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
if (ch == '\r' && nextch == '\n')
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
else
ch = nextch;
} else
pp->parseContext.error(ppToken->loc, "can only escape newlines", "\\", "");
} else {
// Not an escaped newline.
// Put back whatever it was
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken);
// If not in the middle of an identifier, the \ is our token
if (len == 0)
return '\\';
// Otherwise, put back the \ character, leave it for the next call
ch = '\\'; // for the upcoming unget(...ch...);
break;
}
} else if (len < TPpToken::maxTokenLength) {
tokenText[len++] = ch;
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
@ -303,7 +312,7 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
pp->parseContext.error(ppToken->loc, "name too long", "", "");
AlreadyComplained = 1;
}
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
}
} while ((ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||