Allow unsigned int in the "location = " grammar, and generally improve recognition of numeric literals to be up to spec.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22597 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-08-04 23:51:37 +00:00
parent 161d482312
commit 41a5918eaa
5 changed files with 203 additions and 73 deletions

96
Test/numeral.frag Normal file
View File

@ -0,0 +1,96 @@
#version 400
void main()
{
int o00 = 00;
int o000 = 000;
int o0000 = 0000;
int o5 = 05;
int o05 = 005;
int o006 = 0006;
int o7 = 07;
int o58 = 072;
int omax = 037777777777;
int o8 = 08; // ERROR
int o08 = 008; // ERROR
int o009 = 0009; // ERROR
int obig = 07324327323472347234; // ERROR
int omax1 = 040000000000; // ERROR
uint uo5 = 05u;
uint uo6 = 06u;
uint uo7 = 07u;
uint uo8 = 08u; // ERROR
uint uo9 = 09u; // ERROR
int h0 = 0x0;
int h00 = 0x00;
int h000 = 0x000;
int h1 = 0x1;
int h2 = 0x00000002;
int h300 = 0x000300;
int hABCDEF = 0xAbCdEF;
int hFFFFFFFF = 0xFFFFFFFF;
int h12345678 = 0xBC614E;
int hToBeOrNotToBe = 0x2b | ~0x2B;
uint uh0 = 0x0u;
uint uhg = (0xcu);
uint uh000 = 0x000u;
uint uh1 = 0x1u;
uint uh2 = 0x00000002u;
uint uh300 = 0x000300u;
uint uhABCDEF = 0xAbCdEFu;
uint uhFFFFFFFF = 0xFFFFFFFFu;
uint uh12345678 = 0xBC614Eu;
uint uhToBeOrNotToBe = 0x2bu | ~0x2BU;
//int he1 = 0xG; // ERROR
int he2 = 0x; // ERROR
int hbig = 0xFFFFFFFF1; // ERROR
float f1 = 1.0;
float f2 = 2.;
float f3 = 3e0;
float f4 = 40e-1;
float f5 = 05.;
float f6 = 006.;
float f7 = .7e1;
float f8 = 08e0;
float f9 = .9e+1;
float f10 = 10.0;
float f11 = .011e+3;
float f12 = .0012e4;
float f543 = 000000543.;
float f6789 = 00006789.;
float f88 = 0000088.;
float g1 = 5.3876e4;
float g2 = 4000000000e-11;
float g3 = 1e+5;
float g4 = 7.321E-3;
float g5 = 3.2E+4;
float g6 = 0.5e-5;
float g7 = 0.45;
float g8 = 6.e10;
double gf1 = 1.0lf;
double gf2 = 2.Lf;
double gf3 = .3e1lF;
double gf4 = .4e1LF;
float gf5 = 5.f;
float gf6 = 6.F;
//float e1 = 1..; // ERROR
//float e2 = 2.l; // ERROR
//float e3 = ..3; // ERROR
//float e4 = 4ee1; // ERROR
float e5 = 5f; // ERROR
}
layout (location = 2) out vec4 c2;
layout (location = 3u) out vec4 c3;
layout (location = 04) out vec4 c4;
layout (location = 005u) out vec4 c5;
layout (location = 0x6) out vec4 c6;
layout (location = 0x7u) out vec4 c7;

View File

@ -1,12 +1,11 @@
#!/usr/bin/env bash
RUNCMD=../Build/Debug/glslang.exe
TARGETDIR=localout
BASEDIR=localbase
while read t; do
echo Running $t...
b=`basename $t`
./StandAlone -i $t > $TARGETDIR/$b.out
./glslangValidator.exe -i $t > $TARGETDIR/$b.out
diff $BASEDIR/$b.out $TARGETDIR/$b.out
done < testlist

View File

@ -43,3 +43,4 @@ tokenLength.vert
420.vert
430scope.vert
lineContinuation.vert
numeral.frag

View File

@ -1561,6 +1561,10 @@ layout_qualifier_id
$$.init($1.loc);
parseContext.setLayoutQualifier($1.loc, $$, *$1.string, $3.i);
}
| IDENTIFIER EQUAL UINTCONSTANT {
$$.init($1.loc);
parseContext.setLayoutQualifier($1.loc, $$, *$1.string, (int)$3.u);
}
| SHARED { // because "shared" is both an identifier and a keyword
$$.init($1.loc);
TString strShared("shared");

View File

@ -190,23 +190,23 @@ int TPpContext::ScanFromString(char *s)
/*
* lFloatConst() - Scan a single- or double-precision floating point constant. Assumes that the scanner
* has seen at least one digit, followed by either a decimal '.' or the
* letter 'e'.
* letter 'e', or a precision ending (e.g., F or LF).
*/
int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp)
{
int HasDecimal, declen, exp, ExpSign;
bool HasDecimalOrExponent = false;
int declen, exp, ExpSign;
int str_len;
int isDouble = 0;
HasDecimal = 0;
declen = 0;
exp = 0;
str_len=len;
if (ch == '.') {
HasDecimalOrExponent = true;
str[len++]=ch;
HasDecimal = 1;
ch = currentInput->getch(this, currentInput, yylvalpp);
while (ch >= '0' && ch <= '9') {
if (len < TPpToken::maxTokenLength) {
@ -217,7 +217,7 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp)
}
ch = currentInput->getch(this, currentInput, yylvalpp);
} else {
parseContext.error(yylvalpp->loc,"float literal too long", "", "");
parseContext.error(yylvalpp->loc, "float literal too long", "", "");
len = 1,str_len=1;
}
}
@ -226,8 +226,9 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp)
// Exponent:
if (ch == 'e' || ch == 'E') {
HasDecimalOrExponent = true;
if (len >= TPpToken::maxTokenLength) {
parseContext.error(yylvalpp->loc,"float literal too long", "", "");
parseContext.error(yylvalpp->loc, "float literal too long", "", "");
len = 1,str_len=1;
} else {
ExpSign = 1;
@ -248,12 +249,12 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp)
str[len++]=ch;
ch = currentInput->getch(this, currentInput, yylvalpp);
} else {
parseContext.error(yylvalpp->loc,"float literal too long", "", "");
parseContext.error(yylvalpp->loc, "float literal too long", "", "");
len = 1,str_len=1;
}
}
} else {
parseContext.error(yylvalpp->loc,"bad character in float exponent", "", "");
parseContext.error(yylvalpp->loc, "bad character in float exponent", "", "");
}
exp *= ExpSign;
}
@ -264,6 +265,8 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp)
strcpy(str, "0.0");
} else {
if (ch == 'l' || ch == 'L') {
if (! HasDecimalOrExponent)
parseContext.error(yylvalpp->loc, "float literal needs a decimal point or exponent", "", "");
int ch2 = currentInput->getch(this, currentInput, yylvalpp);
if (ch2 != 'f' && ch2 != 'F') {
currentInput->ungetch(this, currentInput, ch2, yylvalpp);
@ -274,15 +277,17 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp)
str[len++] = ch2;
isDouble = 1;
} else {
parseContext.error(yylvalpp->loc,"float literal too long", "", "");
parseContext.error(yylvalpp->loc, "float literal too long", "", "");
len = 1,str_len=1;
}
}
} else if (ch == 'f' || ch == 'F') {
if (! HasDecimalOrExponent)
parseContext.error(yylvalpp->loc, "float literal needs a decimal point or exponent", "", "");
if (len < TPpToken::maxTokenLength)
str[len++] = ch;
else {
parseContext.error(yylvalpp->loc,"float literal too long", "", "");
parseContext.error(yylvalpp->loc, "float literal too long", "", "");
len = 1,str_len=1;
}
} else
@ -351,13 +356,13 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp)
else
ch = nextch;
} else
pp->parseContext.error(yylvalpp->loc,"can only escape newlines", "\\", "");
pp->parseContext.error(yylvalpp->loc, "can only escape newlines", "\\", "");
} else if (len < TPpToken::maxTokenLength) {
tokenText[len++] = ch;
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
} else {
if (! AlreadyComplained) {
pp->parseContext.error(yylvalpp->loc,"name too long", "", "");
pp->parseContext.error(yylvalpp->loc, "name too long", "", "");
AlreadyComplained = 1;
}
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
@ -377,7 +382,9 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp)
yylvalpp->name[len++] = ch;
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
if (ch == 'x' || ch == 'X') {
int uint = 0;
// must be hexidecimal
bool isUnsigned = false;
yylvalpp->name[len++] = ch;
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
if ((ch >= '0' && ch <= '9') ||
@ -395,11 +402,11 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp)
} else if (ch >= 'a' && ch <= 'f') {
ii = ch - 'a' + 10;
} else
pp->parseContext.error(yylvalpp->loc,"bad digit in hexidecimal literal", "", "");
pp->parseContext.error(yylvalpp->loc, "bad digit in hexidecimal literal", "", "");
ival = (ival << 4) | ii;
} else {
if (! AlreadyComplained) {
pp->parseContext.error(yylvalpp->loc,"hexidecimal literal too big literal", "", "");
pp->parseContext.error(yylvalpp->loc, "hexidecimal literal too big", "", "");
AlreadyComplained = 1;
}
ival = 0xffffffff;
@ -409,75 +416,98 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp)
(ch >= 'A' && ch <= 'F') ||
(ch >= 'a' && ch <= 'f'));
} else {
pp->parseContext.error(yylvalpp->loc,"bad digit in hexidecimal literal", "", "");
pp->parseContext.error(yylvalpp->loc, "bad digit in hexidecimal literal", "", "");
}
if (ch == 'u' || ch == 'U') {
if (len < TPpToken::maxTokenLength)
yylvalpp->name[len++] = ch;
uint = 1;
isUnsigned = true;
} else
pp->currentInput->ungetch(pp, pp->currentInput, ch, yylvalpp);
yylvalpp->name[len] = '\0';
yylvalpp->ival = (int)ival;
if (uint)
return CPP_UINTCONSTANT;
else
return CPP_INTCONSTANT;
} else if (ch >= '0' && ch <= '7') { // octal integer constants
int uint = 0;
ival = 0;
do {
if (ival <= 0x1fffffff) {
yylvalpp->name[len++] = ch;
ii = ch - '0';
ival = (ival << 3) | ii;
} else {
if (!AlreadyComplained) {
pp->parseContext.error(yylvalpp->loc,"octal literal too big", "", "");
AlreadyComplained = 1;
}
ival = 0xffffffff;
}
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
} while (ch >= '0' && ch <= '7');
if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E' || ch == 'F' || ch == 'l' || ch == 'L')
return pp->lFloatConst(yylvalpp->name, len, ch, yylvalpp);
else if (ch == 'u' || ch == 'U') {
if (len < TPpToken::maxTokenLength)
yylvalpp->name[len++] = ch;
uint = 1;
} else
pp->currentInput->ungetch(pp, pp->currentInput, ch, yylvalpp);
yylvalpp->name[len] = '\0';
yylvalpp->ival = (int)ival;
if (uint)
if (isUnsigned)
return CPP_UINTCONSTANT;
else
return CPP_INTCONSTANT;
} else {
pp->currentInput->ungetch(pp, pp->currentInput, ch, yylvalpp);
ch = '0';
}
// Fall through...
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
do {
if (len < TPpToken::maxTokenLength) {
if (len > 0 || ch != '0') {
yylvalpp->name[len] = ch;
len++;
}
} else {
if (! AlreadyComplained) {
pp->parseContext.error(yylvalpp->loc,"numeric literal too long", "", "");
// could be octal integer or floating point, speculative pursue octal until it must be floating point
bool isUnsigned = false;
bool octalOverflow = false;
bool nonOctal = false;
ival = 0;
// see how much octal-like stuff we can read
while (ch >= '0' && ch <= '7') {
if (len < TPpToken::maxTokenLength)
yylvalpp->name[len++] = ch;
else if (! AlreadyComplained) {
pp->parseContext.error(yylvalpp->loc, "numeric literal too long", "", "");
AlreadyComplained = 1;
}
if (ival <= 0x1fffffff) {
ii = ch - '0';
ival = (ival << 3) | ii;
} else
octalOverflow = true;
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
}
// could be part of a float...
if (ch == '8' || ch == '9') {
nonOctal = true;
do {
if (len < TPpToken::maxTokenLength)
yylvalpp->name[len++] = ch;
else if (! AlreadyComplained) {
pp->parseContext.error(yylvalpp->loc, "numeric literal too long", "", "");
AlreadyComplained = 1;
}
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
} while (ch >= '0' && ch <= '9');
}
if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F' || ch == 'l' || ch == 'L')
return pp->lFloatConst(yylvalpp->name, len, ch, yylvalpp);
// wasn't a float, so must be octal...
if (nonOctal)
pp->parseContext.error(yylvalpp->loc, "octal literal digit too large", "", "");
if (ch == 'u' || ch == 'U') {
if (len < TPpToken::maxTokenLength)
yylvalpp->name[len++] = ch;
isUnsigned = true;
} else
pp->currentInput->ungetch(pp, pp->currentInput, ch, yylvalpp);
yylvalpp->name[len] = '\0';
if (octalOverflow)
pp->parseContext.error(yylvalpp->loc, "octal literal too big", "", "");
yylvalpp->ival = (int)ival;
if (isUnsigned)
return CPP_UINTCONSTANT;
else
return CPP_INTCONSTANT;
}
break;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
// can't be hexidecimal or octal, is either decimal or floating point
do {
if (len < TPpToken::maxTokenLength)
yylvalpp->name[len++] = ch;
else if (! AlreadyComplained) {
pp->parseContext.error(yylvalpp->loc, "numeric literal too long", "", "");
AlreadyComplained = 1;
}
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
} while (ch >= '0' && ch <= '9');
if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E' || ch == 'F' || ch == 'l' || ch == 'L') {
if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F' || ch == 'l' || ch == 'L') {
return pp->lFloatConst(yylvalpp->name, len, ch, yylvalpp);
} else {
// Finish handling signed and unsigned integers
@ -495,7 +525,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp)
for (ii = 0; ii < numericLen; ii++) {
ch = yylvalpp->name[ii] - '0';
if ((ival > 429496729) || (ival == 429496729 && ch >= 6)) {
pp->parseContext.error(yylvalpp->loc,"numeric literal too big", "", "");
pp->parseContext.error(yylvalpp->loc, "numeric literal too big", "", "");
ival = -1;
break;
} else
@ -687,7 +717,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp)
if (ch == '\n')
nlcount++;
if (ch == EOF) {
pp->parseContext.error(yylvalpp->loc,"EOF in comment", "comment", "");
pp->parseContext.error(yylvalpp->loc, "EOF in comment", "comment", "");
return EOF;
}
@ -695,7 +725,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp)
}
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
if (ch == EOF) {
pp->parseContext.error(yylvalpp->loc,"EOF in comment", "comment", "");
pp->parseContext.error(yylvalpp->loc, "EOF in comment", "comment", "");
return EOF;
}
@ -731,7 +761,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp)
yylvalpp->atom = pp->LookUpAddString(&pp->atomTable, tokenText);
return CPP_STRCONSTANT;
} else {
pp->parseContext.error(yylvalpp->loc,"end of line in string", "string", "");
pp->parseContext.error(yylvalpp->loc, "end of line in string", "string", "");
return CPP_ERROR_SY;
}
}
@ -756,7 +786,7 @@ const char* TPpContext::tokenize(TPpToken* yylvalpp)
return 0;
continue;
} else {
parseContext.error(yylvalpp->loc,"preprocessor directive cannot be preceded by another token", "#", "");
parseContext.error(yylvalpp->loc, "preprocessor directive cannot be preceded by another token", "#", "");
return 0;
}
}