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:
parent
161d482312
commit
41a5918eaa
96
Test/numeral.frag
Normal file
96
Test/numeral.frag
Normal 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;
|
@ -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
|
||||
|
@ -43,3 +43,4 @@ tokenLength.vert
|
||||
420.vert
|
||||
430scope.vert
|
||||
lineContinuation.vert
|
||||
numeral.frag
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user