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);
static int ES2_keyword_ES3_reserved(TParseContext *context, int token);
static int ES2_identifier_ES3_keyword(TParseContext *context, int token);
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
......@@ -314,17 +317,21 @@ O [0-7]
return check_type(yyscanner);
}
0[xX]{H}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
0{O}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
0{D}+ { context->error(yylineno, "Invalid Octal number.", yytext); context->recover(); return 0;}
{D}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
0[xX]{H}+ { return int_constant(yyscanner); }
0{O}+ { return int_constant(yyscanner); }
{D}+ { return int_constant(yyscanner); }
0[xX]{H}+[uU] { return uint_constant(context); }
0{O}+[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}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
"."{D}+({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
{D}+{E} { return float_constant(yyscanner); }
{D}+"."{D}*({E})? { return float_constant(yyscanner); }
"."{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(SUB_ASSIGN); }
......@@ -479,10 +486,45 @@ int uint_constant(TParseContext *context)
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;
}
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) {
struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
......
......@@ -114,12 +114,12 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
return pp::Token::IDENTIFIER;
}
{DECIMAL_CONSTANT}|{OCTAL_CONSTANT}|{HEXADECIMAL_CONSTANT} {
({DECIMAL_CONSTANT}[uU]?)|({OCTAL_CONSTANT}[uU]?)|({HEXADECIMAL_CONSTANT}[uU]?) {
yylval->assign(yytext, yyleng);
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);
return pp::Token::CONST_FLOAT;
}
......
......@@ -4,30 +4,23 @@
// found in the LICENSE file.
//
#include <math.h>
#include <stdlib.h>
#include <limits>
#include "util.h"
#include "preprocessor/numeric_lex.h"
#ifdef _MSC_VER
#include <locale.h>
#else
#include <sstream>
#endif
bool atof_clamp(const char *str, float *value)
{
bool success = pp::numeric_lex_float(str, value);
if(!success)
*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
_locale_t l = _create_locale(LC_NUMERIC, "C");
double result = _atof_l(str, l);
_free_locale(l);
return result;
#else
double result;
std::istringstream s(str);
std::locale l("C");
s.imbue(l);
s >> result;
return result;
#endif
bool success = pp::numeric_lex_int(str, value);
if(!success)
*value = std::numeric_limits<int>::max();
return success;
}
......@@ -11,8 +11,15 @@
extern "C" {
#endif
// atof_dot is like atof but forcing C locale, i.e. forcing '.' as decimal point.
double atof_dot(const char *str);
// atof_clamp is like atof but
// 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
} // 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