Commit 3ef0c0a8 by Alexis Hetu Committed by Alexis Hétu

Added proper number suffixes in GLSL parser

Numbers like "1.0f" or "10u" are now allowed in GLSL, so I added code to do proper parsing of these numbers. Change-Id: Ia4635ab2b449399bd4adea2c5c94567b5b8a5f8e Reviewed-on: https://swiftshader-review.googlesource.com/3434Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent f159eb55
...@@ -58,6 +58,9 @@ static int ES2_reserved_ES3_keyword(TParseContext *context, int token); ...@@ -58,6 +58,9 @@ static int ES2_reserved_ES3_keyword(TParseContext *context, int token);
static int ES2_keyword_ES3_reserved(TParseContext *context, int token); static int ES2_keyword_ES3_reserved(TParseContext *context, int token);
static int ES2_identifier_ES3_keyword(TParseContext *context, int token); static int ES2_identifier_ES3_keyword(TParseContext *context, int token);
static int uint_constant(TParseContext *context); static int uint_constant(TParseContext *context);
static int int_constant(yyscan_t yyscanner);
static int float_constant(yyscan_t yyscanner);
static int floatsuffix_check(TParseContext* context);
%} %}
%option noyywrap nounput never-interactive %option noyywrap nounput never-interactive
...@@ -314,17 +317,21 @@ O [0-7] ...@@ -314,17 +317,21 @@ O [0-7]
return check_type(yyscanner); return check_type(yyscanner);
} }
0[xX]{H}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } 0[xX]{H}+ { return int_constant(yyscanner); }
0{O}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } 0{O}+ { return int_constant(yyscanner); }
0{D}+ { context->error(yylineno, "Invalid Octal number.", yytext); context->recover(); return 0;} {D}+ { return int_constant(yyscanner); }
{D}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
0[xX]{H}+[uU] { return uint_constant(context); } 0[xX]{H}+[uU] { return uint_constant(context); }
0{O}+[uU] { return uint_constant(context); } 0{O}+[uU] { return uint_constant(context); }
{D}+[uU] { return uint_constant(context); } {D}+[uU] { return uint_constant(context); }
{D}+{E} { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } {D}+{E} { return float_constant(yyscanner); }
{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } {D}+"."{D}*({E})? { return float_constant(yyscanner); }
"."{D}+({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } "."{D}+({E})? { return float_constant(yyscanner); }
{D}+{E}[fF] { return floatsuffix_check(context); }
{D}+"."{D}*({E})?[fF] { return floatsuffix_check(context); }
"."{D}+({E})?[fF] { return floatsuffix_check(context); }
"+=" { return(ADD_ASSIGN); } "+=" { return(ADD_ASSIGN); }
"-=" { return(SUB_ASSIGN); } "-=" { return(SUB_ASSIGN); }
...@@ -479,10 +486,45 @@ int uint_constant(TParseContext *context) ...@@ -479,10 +486,45 @@ int uint_constant(TParseContext *context)
return 0; return 0;
} }
yylval->lex.u = static_cast<unsigned int>(strtol(yytext, 0, 0)); if (!atoi_clamp(yytext, &(yylval->lex.i)))
yyextra->warning(yylineno, "Integer overflow", yytext, "");
return UINTCONSTANT; return UINTCONSTANT;
} }
int floatsuffix_check(TParseContext* context)
{
struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
if (context->shaderVersion < 300)
{
context->error(yylineno, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext);
context->recover();
return 0;
}
if (!atof_clamp(yytext, &(yylval->lex.f)))
yyextra->warning(yylineno, "Float overflow", yytext, "");
return(FLOATCONSTANT);
}
int int_constant(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
if (!atoi_clamp(yytext, &(yylval->lex.i)))
yyextra->warning(yylineno, "Integer overflow", yytext, "");
return INTCONSTANT;
}
int float_constant(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
if (!atof_clamp(yytext, &(yylval->lex.f)))
yyextra->warning(yylineno, "Float overflow", yytext, "");
return FLOATCONSTANT;
}
void yyerror(TParseContext* context, const char* reason) { void yyerror(TParseContext* context, const char* reason) {
struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
......
...@@ -114,12 +114,12 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") ...@@ -114,12 +114,12 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
return pp::Token::IDENTIFIER; return pp::Token::IDENTIFIER;
} }
{DECIMAL_CONSTANT}|{OCTAL_CONSTANT}|{HEXADECIMAL_CONSTANT} { ({DECIMAL_CONSTANT}[uU]?)|({OCTAL_CONSTANT}[uU]?)|({HEXADECIMAL_CONSTANT}[uU]?) {
yylval->assign(yytext, yyleng); yylval->assign(yytext, yyleng);
return pp::Token::CONST_INT; return pp::Token::CONST_INT;
} }
({DIGIT}+{EXPONENT_PART})|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?) { ({DIGIT}+{EXPONENT_PART}[fF]?)|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?[fF]?) {
yylval->assign(yytext, yyleng); yylval->assign(yytext, yyleng);
return pp::Token::CONST_FLOAT; return pp::Token::CONST_FLOAT;
} }
......
...@@ -4,30 +4,23 @@ ...@@ -4,30 +4,23 @@
// found in the LICENSE file. // found in the LICENSE file.
// //
#include <math.h> #include <limits>
#include <stdlib.h>
#include "util.h" #include "util.h"
#include "preprocessor/numeric_lex.h"
#ifdef _MSC_VER bool atof_clamp(const char *str, float *value)
#include <locale.h> {
#else bool success = pp::numeric_lex_float(str, value);
#include <sstream> if(!success)
#endif *value = std::numeric_limits<float>::max();
return success;
}
double atof_dot(const char *str) bool atoi_clamp(const char *str, int *value)
{ {
#ifdef _MSC_VER bool success = pp::numeric_lex_int(str, value);
_locale_t l = _create_locale(LC_NUMERIC, "C"); if(!success)
double result = _atof_l(str, l); *value = std::numeric_limits<int>::max();
_free_locale(l); return success;
return result;
#else
double result;
std::istringstream s(str);
std::locale l("C");
s.imbue(l);
s >> result;
return result;
#endif
} }
...@@ -11,8 +11,15 @@ ...@@ -11,8 +11,15 @@
extern "C" { extern "C" {
#endif #endif
// atof_dot is like atof but forcing C locale, i.e. forcing '.' as decimal point. // atof_clamp is like atof but
double atof_dot(const char *str); // 1. it forces C locale, i.e. forcing '.' as decimal point.
// 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens.
// Return false if overflow happens.
bool atof_clamp(const char *str, float *value);
// If overflow happens, clamp the value to INT_MIN or INT_MAX.
// Return false if overflow happens.
bool atoi_clamp(const char *str, int *value);
#ifdef __cplusplus #ifdef __cplusplus
} // end extern "C" } // end extern "C"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment