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 #!/usr/bin/env bash
RUNCMD=../Build/Debug/glslang.exe
TARGETDIR=localout TARGETDIR=localout
BASEDIR=localbase BASEDIR=localbase
while read t; do while read t; do
echo Running $t... echo Running $t...
b=`basename $t` b=`basename $t`
./StandAlone -i $t > $TARGETDIR/$b.out ./glslangValidator.exe -i $t > $TARGETDIR/$b.out
diff $BASEDIR/$b.out $TARGETDIR/$b.out diff $BASEDIR/$b.out $TARGETDIR/$b.out
done < testlist done < testlist

View File

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

View File

@ -1561,6 +1561,10 @@ layout_qualifier_id
$$.init($1.loc); $$.init($1.loc);
parseContext.setLayoutQualifier($1.loc, $$, *$1.string, $3.i); 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 | SHARED { // because "shared" is both an identifier and a keyword
$$.init($1.loc); $$.init($1.loc);
TString strShared("shared"); 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 * 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 * 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 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 str_len;
int isDouble = 0; int isDouble = 0;
HasDecimal = 0;
declen = 0; declen = 0;
exp = 0; exp = 0;
str_len=len; str_len=len;
if (ch == '.') { if (ch == '.') {
HasDecimalOrExponent = true;
str[len++]=ch; str[len++]=ch;
HasDecimal = 1;
ch = currentInput->getch(this, currentInput, yylvalpp); ch = currentInput->getch(this, currentInput, yylvalpp);
while (ch >= '0' && ch <= '9') { while (ch >= '0' && ch <= '9') {
if (len < TPpToken::maxTokenLength) { 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); ch = currentInput->getch(this, currentInput, yylvalpp);
} else { } else {
parseContext.error(yylvalpp->loc,"float literal too long", "", ""); parseContext.error(yylvalpp->loc, "float literal too long", "", "");
len = 1,str_len=1; len = 1,str_len=1;
} }
} }
@ -226,8 +226,9 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp)
// Exponent: // Exponent:
if (ch == 'e' || ch == 'E') { if (ch == 'e' || ch == 'E') {
HasDecimalOrExponent = true;
if (len >= TPpToken::maxTokenLength) { 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; len = 1,str_len=1;
} else { } else {
ExpSign = 1; ExpSign = 1;
@ -248,12 +249,12 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp)
str[len++]=ch; str[len++]=ch;
ch = currentInput->getch(this, currentInput, yylvalpp); ch = currentInput->getch(this, currentInput, yylvalpp);
} else { } else {
parseContext.error(yylvalpp->loc,"float literal too long", "", ""); parseContext.error(yylvalpp->loc, "float literal too long", "", "");
len = 1,str_len=1; len = 1,str_len=1;
} }
} }
} else { } else {
parseContext.error(yylvalpp->loc,"bad character in float exponent", "", ""); parseContext.error(yylvalpp->loc, "bad character in float exponent", "", "");
} }
exp *= ExpSign; exp *= ExpSign;
} }
@ -264,6 +265,8 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp)
strcpy(str, "0.0"); strcpy(str, "0.0");
} else { } else {
if (ch == 'l' || ch == 'L') { 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); int ch2 = currentInput->getch(this, currentInput, yylvalpp);
if (ch2 != 'f' && ch2 != 'F') { if (ch2 != 'f' && ch2 != 'F') {
currentInput->ungetch(this, currentInput, ch2, yylvalpp); currentInput->ungetch(this, currentInput, ch2, yylvalpp);
@ -274,15 +277,17 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp)
str[len++] = ch2; str[len++] = ch2;
isDouble = 1; isDouble = 1;
} else { } else {
parseContext.error(yylvalpp->loc,"float literal too long", "", ""); parseContext.error(yylvalpp->loc, "float literal too long", "", "");
len = 1,str_len=1; len = 1,str_len=1;
} }
} }
} else if (ch == 'f' || ch == 'F') { } else if (ch == 'f' || ch == 'F') {
if (! HasDecimalOrExponent)
parseContext.error(yylvalpp->loc, "float literal needs a decimal point or exponent", "", "");
if (len < TPpToken::maxTokenLength) if (len < TPpToken::maxTokenLength)
str[len++] = ch; str[len++] = ch;
else { else {
parseContext.error(yylvalpp->loc,"float literal too long", "", ""); parseContext.error(yylvalpp->loc, "float literal too long", "", "");
len = 1,str_len=1; len = 1,str_len=1;
} }
} else } else
@ -351,13 +356,13 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp)
else else
ch = nextch; ch = nextch;
} else } else
pp->parseContext.error(yylvalpp->loc,"can only escape newlines", "\\", ""); pp->parseContext.error(yylvalpp->loc, "can only escape newlines", "\\", "");
} else if (len < TPpToken::maxTokenLength) { } else if (len < TPpToken::maxTokenLength) {
tokenText[len++] = ch; tokenText[len++] = ch;
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
} else { } else {
if (! AlreadyComplained) { if (! AlreadyComplained) {
pp->parseContext.error(yylvalpp->loc,"name too long", "", ""); pp->parseContext.error(yylvalpp->loc, "name too long", "", "");
AlreadyComplained = 1; AlreadyComplained = 1;
} }
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); 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; yylvalpp->name[len++] = ch;
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
if (ch == 'x' || ch == 'X') { if (ch == 'x' || ch == 'X') {
int uint = 0; // must be hexidecimal
bool isUnsigned = false;
yylvalpp->name[len++] = ch; yylvalpp->name[len++] = ch;
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
if ((ch >= '0' && ch <= '9') || 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') { } else if (ch >= 'a' && ch <= 'f') {
ii = ch - 'a' + 10; ii = ch - 'a' + 10;
} else } 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; ival = (ival << 4) | ii;
} else { } else {
if (! AlreadyComplained) { if (! AlreadyComplained) {
pp->parseContext.error(yylvalpp->loc,"hexidecimal literal too big literal", "", ""); pp->parseContext.error(yylvalpp->loc, "hexidecimal literal too big", "", "");
AlreadyComplained = 1; AlreadyComplained = 1;
} }
ival = 0xffffffff; ival = 0xffffffff;
@ -409,75 +416,98 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp)
(ch >= 'A' && ch <= 'F') || (ch >= 'A' && ch <= 'F') ||
(ch >= 'a' && ch <= 'f')); (ch >= 'a' && ch <= 'f'));
} else { } 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 (ch == 'u' || ch == 'U') {
if (len < TPpToken::maxTokenLength) if (len < TPpToken::maxTokenLength)
yylvalpp->name[len++] = ch; yylvalpp->name[len++] = ch;
uint = 1; isUnsigned = true;
} else } else
pp->currentInput->ungetch(pp, pp->currentInput, ch, yylvalpp); pp->currentInput->ungetch(pp, pp->currentInput, ch, yylvalpp);
yylvalpp->name[len] = '\0'; yylvalpp->name[len] = '\0';
yylvalpp->ival = (int)ival; yylvalpp->ival = (int)ival;
if (uint) if (isUnsigned)
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)
return CPP_UINTCONSTANT; return CPP_UINTCONSTANT;
else else
return CPP_INTCONSTANT; return CPP_INTCONSTANT;
} else { } else {
pp->currentInput->ungetch(pp, pp->currentInput, ch, yylvalpp); // could be octal integer or floating point, speculative pursue octal until it must be floating point
ch = '0';
} bool isUnsigned = false;
// Fall through... bool octalOverflow = false;
case '1': case '2': case '3': case '4': bool nonOctal = false;
case '5': case '6': case '7': case '8': case '9': ival = 0;
do {
if (len < TPpToken::maxTokenLength) { // see how much octal-like stuff we can read
if (len > 0 || ch != '0') { while (ch >= '0' && ch <= '7') {
yylvalpp->name[len] = ch; if (len < TPpToken::maxTokenLength)
len++; yylvalpp->name[len++] = ch;
} else if (! AlreadyComplained) {
} else { pp->parseContext.error(yylvalpp->loc, "numeric literal too long", "", "");
if (! AlreadyComplained) {
pp->parseContext.error(yylvalpp->loc,"numeric literal too long", "", "");
AlreadyComplained = 1; 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); ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
} while (ch >= '0' && ch <= '9'); } 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); return pp->lFloatConst(yylvalpp->name, len, ch, yylvalpp);
} else { } else {
// Finish handling signed and unsigned integers // 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++) { for (ii = 0; ii < numericLen; ii++) {
ch = yylvalpp->name[ii] - '0'; ch = yylvalpp->name[ii] - '0';
if ((ival > 429496729) || (ival == 429496729 && ch >= 6)) { 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; ival = -1;
break; break;
} else } else
@ -687,7 +717,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp)
if (ch == '\n') if (ch == '\n')
nlcount++; nlcount++;
if (ch == EOF) { if (ch == EOF) {
pp->parseContext.error(yylvalpp->loc,"EOF in comment", "comment", ""); pp->parseContext.error(yylvalpp->loc, "EOF in comment", "comment", "");
return EOF; return EOF;
} }
@ -695,7 +725,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp)
} }
ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp);
if (ch == EOF) { if (ch == EOF) {
pp->parseContext.error(yylvalpp->loc,"EOF in comment", "comment", ""); pp->parseContext.error(yylvalpp->loc, "EOF in comment", "comment", "");
return EOF; return EOF;
} }
@ -731,7 +761,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp)
yylvalpp->atom = pp->LookUpAddString(&pp->atomTable, tokenText); yylvalpp->atom = pp->LookUpAddString(&pp->atomTable, tokenText);
return CPP_STRCONSTANT; return CPP_STRCONSTANT;
} else { } 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; return CPP_ERROR_SY;
} }
} }
@ -756,7 +786,7 @@ const char* TPpContext::tokenize(TPpToken* yylvalpp)
return 0; return 0;
continue; continue;
} else { } 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; return 0;
} }
} }