Commit 57a04544 by Jamie Madill Committed by Shannon Woods

Move the code for parsing indexed expressions from the grammar to TParseContext.

TRAC #23509 Signed-off-by: Shannon Woods Signed-off-by: Nicolas Capens Authored-by: Jamie Madill
parent 9c414aca
...@@ -1448,6 +1448,134 @@ bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField ...@@ -1448,6 +1448,134 @@ bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField
} }
// //
// Parse an array index expression
//
TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression)
{
TIntermTyped *indexedExpression = NULL;
if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
{
if (baseExpression->getAsSymbolNode())
{
error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str());
}
else
{
error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
}
recover();
}
if (indexExpression->getQualifier() == EvqConst)
{
int index = indexExpression->getAsConstantUnion()->getIConst(0);
if (index < 0)
{
std::stringstream infoStream;
infoStream << index;
std::string info = infoStream.str();
error(location, "negative index", info.c_str());
recover();
index = 0;
}
if (baseExpression->getType().getQualifier() == EvqConst)
{
if (baseExpression->isArray())
{
// constant folding for arrays
indexedExpression = addConstArrayNode(index, baseExpression, location);
}
else if (baseExpression->isVector())
{
// constant folding for vectors
TVectorFields fields;
fields.num = 1;
fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
indexedExpression = addConstVectorNode(fields, baseExpression, location);
}
else if (baseExpression->isMatrix())
{
// constant folding for matrices
indexedExpression = addConstMatrixNode(index, baseExpression, location);
}
}
else
{
if (baseExpression->isArray())
{
if (index >= baseExpression->getType().getArraySize())
{
std::stringstream extraInfoStream;
extraInfoStream << "array index out of range '" << index << "'";
std::string extraInfo = extraInfoStream.str();
error(location, "", "[", extraInfo.c_str());
recover();
index = baseExpression->getType().getArraySize() - 1;
}
}
else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index)
{
std::stringstream extraInfoStream;
extraInfoStream << "field selection out of range '" << index << "'";
std::string extraInfo = extraInfoStream.str();
error(location, "", "[", extraInfo.c_str());
recover();
index = baseExpression->getType().getNominalSize() - 1;
}
indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
}
}
else
{
indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
}
if (indexedExpression == 0)
{
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setFConst(0.0f);
indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
}
else if (baseExpression->isArray())
{
const TType &baseType = baseExpression->getType();
if (baseType.getStruct())
{
TType copyOfType(baseType.getStruct());
indexedExpression->setType(copyOfType);
}
else
{
indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix()));
}
if (baseExpression->getType().getQualifier() == EvqConst)
{
indexedExpression->getTypePointer()->setQualifier(EvqConst);
}
}
else if (baseExpression->isMatrix())
{
TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize()));
}
else if (baseExpression->isVector())
{
TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
}
else
{
indexedExpression->setType(baseExpression->getType());
}
return indexedExpression;
}
//
// Parse an array of strings using yyparse. // Parse an array of strings using yyparse.
// //
// Returns 0 for success. // Returns 0 for success.
......
...@@ -117,6 +117,7 @@ struct TParseContext { ...@@ -117,6 +117,7 @@ struct TParseContext {
TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&); TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&);
TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line); TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line);
TIntermTyped* addConstStruct(TString& , TIntermTyped*, const TSourceLoc&); TIntermTyped* addConstStruct(TString& , TIntermTyped*, const TSourceLoc&);
TIntermTyped* addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression);
// Performs an error check for embedded struct declarations. // Performs an error check for embedded struct declarations.
// Returns true if an error was raised due to the declaration of // Returns true if an error was raised due to the declaration of
......
...@@ -259,79 +259,7 @@ postfix_expression ...@@ -259,79 +259,7 @@ postfix_expression
$$ = $1; $$ = $1;
} }
| postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) { $$ = context->addIndexExpression($1, @2, $3);
if ($1->getAsSymbolNode())
context->error(@2, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str());
else
context->error(@2, " left of '[' is not of type array, matrix, or vector ", "expression");
context->recover();
}
if ($3->getQualifier() == EvqConst) {
int index = $3->getAsConstantUnion()->getIConst(0);
if (index < 0) {
std::stringstream infoStream;
infoStream << index;
std::string info = infoStream.str();
context->error(@3, "negative index", info.c_str());
context->recover();
index = 0;
}
if ($1->getType().getQualifier() == EvqConst) {
if ($1->isArray()) { // constant folding for arrays
$$ = context->addConstArrayNode(index, $1, @2);
} else if ($1->isVector()) { // constant folding for vectors
TVectorFields fields;
fields.num = 1;
fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
$$ = context->addConstVectorNode(fields, $1, @2);
} else if ($1->isMatrix()) { // constant folding for matrices
$$ = context->addConstMatrixNode(index, $1, @2);
}
} else {
if ($1->isArray()) {
if (index >= $1->getType().getArraySize()) {
std::stringstream extraInfoStream;
extraInfoStream << "array index out of range '" << index << "'";
std::string extraInfo = extraInfoStream.str();
context->error(@2, "", "[", extraInfo.c_str());
context->recover();
index = $1->getType().getArraySize() - 1;
}
} else if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= index) {
std::stringstream extraInfoStream;
extraInfoStream << "field selection out of range '" << index << "'";
std::string extraInfo = extraInfoStream.str();
context->error(@2, "", "[", extraInfo.c_str());
context->recover();
index = $1->getType().getNominalSize() - 1;
}
$3->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
$$ = context->intermediate.addIndex(EOpIndexDirect, $1, $3, @2);
}
} else {
$$ = context->intermediate.addIndex(EOpIndexIndirect, $1, $3, @2);
}
if ($$ == 0) {
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setFConst(0.0f);
$$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), @2);
} else if ($1->isArray()) {
if ($1->getType().getStruct())
$$->setType(TType($1->getType().getStruct()));
else
$$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));
if ($1->getType().getQualifier() == EvqConst)
$$->getTypePointer()->setQualifier(EvqConst);
} else if ($1->isMatrix()) {
TQualifier qualifier = $1->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
$$->setType(TType($1->getBasicType(), $1->getPrecision(), qualifier, $1->getNominalSize()));
} else if ($1->isVector()) {
TQualifier qualifier = $1->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
$$->setType(TType($1->getBasicType(), $1->getPrecision(), qualifier));
} else {
$$->setType($1->getType());
}
} }
| function_call { | function_call {
$$ = $1; $$ = $1;
......
/* A Bison parser, made by GNU Bison 2.7. */ /* A Bison parser, made by GNU Bison 2.7.12-4996. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
......
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