зеркало из https://github.com/AvaloniaUI/angle.git
Implement parsing switch statements
Put in some groundwork for parsing switch statements and case labels in the parser, including definitions for IntermNode classes. Intermediate functions for adding the statements are stubbed to only generate errors for now. Tested by manually disabling shading language version checks for switch in a Chromium build and checking that the expected errors are generated. BUG=angle:921 Change-Id: I064b3e0c4c1b724a083cf5bc78eebfdd3794eb1b Reviewed-on: https://chromium-review.googlesource.com/250380 Reviewed-by: Olli Etuaho <oetuaho@nvidia.com> Tested-by: Olli Etuaho <oetuaho@nvidia.com>
This commit is contained in:
Родитель
a6d110e281
Коммит
a3a3666464
|
@ -244,6 +244,21 @@ bool TIntermSelection::replaceChildNode(
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TIntermSwitch::replaceChildNode(
|
||||
TIntermNode *original, TIntermNode *replacement)
|
||||
{
|
||||
REPLACE_IF_IS(mInit, TIntermTyped, original, replacement);
|
||||
REPLACE_IF_IS(mStatementList, TIntermAggregate, original, replacement);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TIntermCase::replaceChildNode(
|
||||
TIntermNode *original, TIntermNode *replacement)
|
||||
{
|
||||
REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Say whether or not an operation node changes the value of a variable.
|
||||
//
|
||||
|
|
|
@ -33,6 +33,8 @@ class TIntermBinary;
|
|||
class TIntermUnary;
|
||||
class TIntermConstantUnion;
|
||||
class TIntermSelection;
|
||||
class TIntermSwitch;
|
||||
class TIntermCase;
|
||||
class TIntermTyped;
|
||||
class TIntermSymbol;
|
||||
class TIntermLoop;
|
||||
|
@ -66,6 +68,8 @@ class TIntermNode
|
|||
virtual TIntermBinary *getAsBinaryNode() { return 0; }
|
||||
virtual TIntermUnary *getAsUnaryNode() { return 0; }
|
||||
virtual TIntermSelection *getAsSelectionNode() { return 0; }
|
||||
virtual TIntermSwitch *getAsSwitchNode() { return 0; }
|
||||
virtual TIntermCase *getAsCaseNode() { return 0; }
|
||||
virtual TIntermSymbol *getAsSymbolNode() { return 0; }
|
||||
virtual TIntermLoop *getAsLoopNode() { return 0; }
|
||||
virtual TIntermRaw *getAsRawNode() { return 0; }
|
||||
|
@ -453,7 +457,7 @@ class TIntermAggregate : public TIntermOperator
|
|||
};
|
||||
|
||||
//
|
||||
// For if tests. Simplified since there is no switch statement.
|
||||
// For if tests.
|
||||
//
|
||||
class TIntermSelection : public TIntermTyped
|
||||
{
|
||||
|
@ -489,6 +493,55 @@ protected:
|
|||
TIntermNode *mFalseBlock;
|
||||
};
|
||||
|
||||
//
|
||||
// Switch statement.
|
||||
//
|
||||
class TIntermSwitch : public TIntermNode
|
||||
{
|
||||
public:
|
||||
TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList)
|
||||
: TIntermNode(),
|
||||
mInit(init),
|
||||
mStatementList(statementList)
|
||||
{
|
||||
}
|
||||
|
||||
void traverse(TIntermTraverser *it) override;
|
||||
bool replaceChildNode(
|
||||
TIntermNode *original, TIntermNode *replacement) override;
|
||||
|
||||
TIntermSwitch *getAsSwitchNode() override { return this; }
|
||||
|
||||
protected:
|
||||
TIntermTyped *mInit;
|
||||
TIntermAggregate *mStatementList;
|
||||
};
|
||||
|
||||
//
|
||||
// Case label.
|
||||
//
|
||||
class TIntermCase : public TIntermNode
|
||||
{
|
||||
public:
|
||||
TIntermCase(TIntermTyped *condition)
|
||||
: TIntermNode(),
|
||||
mCondition(condition)
|
||||
{
|
||||
}
|
||||
|
||||
void traverse(TIntermTraverser *it) override;
|
||||
bool replaceChildNode(
|
||||
TIntermNode *original, TIntermNode *replacement) override;
|
||||
|
||||
TIntermCase *getAsCaseNode() override { return this; }
|
||||
|
||||
bool hasCondition() const { return mCondition != nullptr; }
|
||||
TIntermTyped *getCondition() const { return mCondition; }
|
||||
|
||||
protected:
|
||||
TIntermTyped *mCondition;
|
||||
};
|
||||
|
||||
enum Visit
|
||||
{
|
||||
PreVisit,
|
||||
|
@ -525,6 +578,8 @@ class TIntermTraverser
|
|||
virtual bool visitBinary(Visit, TIntermBinary *) { return true; }
|
||||
virtual bool visitUnary(Visit, TIntermUnary *) { return true; }
|
||||
virtual bool visitSelection(Visit, TIntermSelection *) { return true; }
|
||||
virtual bool visitSwitch(Visit, TIntermSwitch *) { return true; }
|
||||
virtual bool visitCase(Visit, TIntermCase *) { return true; }
|
||||
virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; }
|
||||
virtual bool visitLoop(Visit, TIntermLoop *) { return true; }
|
||||
virtual bool visitBranch(Visit, TIntermBranch *) { return true; }
|
||||
|
|
|
@ -193,6 +193,60 @@ void TIntermSelection::traverse(TIntermTraverser *it)
|
|||
it->visitSelection(PostVisit, this);
|
||||
}
|
||||
|
||||
//
|
||||
// Traverse a switch node. Same comments in binary node apply here.
|
||||
//
|
||||
void TIntermSwitch::traverse(TIntermTraverser *it)
|
||||
{
|
||||
bool visit = true;
|
||||
|
||||
if (it->preVisit)
|
||||
visit = it->visitSwitch(PreVisit, this);
|
||||
|
||||
if (visit)
|
||||
{
|
||||
it->incrementDepth(this);
|
||||
if (it->rightToLeft)
|
||||
{
|
||||
if (mStatementList)
|
||||
mStatementList->traverse(it);
|
||||
if (it->inVisit)
|
||||
visit = it->visitSwitch(InVisit, this);
|
||||
if (visit)
|
||||
mInit->traverse(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
mInit->traverse(it);
|
||||
if (it->inVisit)
|
||||
visit = it->visitSwitch(InVisit, this);
|
||||
if (visit && mStatementList)
|
||||
mStatementList->traverse(it);
|
||||
}
|
||||
it->decrementDepth();
|
||||
}
|
||||
|
||||
if (visit && it->postVisit)
|
||||
it->visitSwitch(PostVisit, this);
|
||||
}
|
||||
|
||||
//
|
||||
// Traverse a switch node. Same comments in binary node apply here.
|
||||
//
|
||||
void TIntermCase::traverse(TIntermTraverser *it)
|
||||
{
|
||||
bool visit = true;
|
||||
|
||||
if (it->preVisit)
|
||||
visit = it->visitCase(PreVisit, this);
|
||||
|
||||
if (visit && mCondition)
|
||||
mCondition->traverse(it);
|
||||
|
||||
if (visit && it->postVisit)
|
||||
it->visitCase(PostVisit, this);
|
||||
}
|
||||
|
||||
//
|
||||
// Traverse a loop node. Same comments in binary node apply here.
|
||||
//
|
||||
|
|
|
@ -458,6 +458,22 @@ TIntermTyped *TIntermediate::addSelection(
|
|||
return node;
|
||||
}
|
||||
|
||||
TIntermSwitch *TIntermediate::addSwitch(
|
||||
TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
|
||||
{
|
||||
mInfoSink.info.message(EPrefixInternalError, line,
|
||||
"Switch statements are disabled for now");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TIntermCase *TIntermediate::addCase(
|
||||
TIntermTyped *condition, const TSourceLoc &line)
|
||||
{
|
||||
mInfoSink.info.message(EPrefixInternalError, line,
|
||||
"Case labels and default labels are disabled for now");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//
|
||||
// Constant terminal nodes. Has a union that contains bool, float or int constants
|
||||
//
|
||||
|
|
|
@ -43,6 +43,10 @@ class TIntermediate
|
|||
TIntermNode *addSelection(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &);
|
||||
TIntermTyped *addSelection(
|
||||
TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &);
|
||||
TIntermSwitch *addSwitch(
|
||||
TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line);
|
||||
TIntermCase *addCase(
|
||||
TIntermTyped *condition, const TSourceLoc &line);
|
||||
TIntermTyped *addComma(
|
||||
TIntermTyped *left, TIntermTyped *right, const TSourceLoc &);
|
||||
TIntermConstantUnion *addConstantUnion(ConstantUnion *, const TType &, const TSourceLoc &);
|
||||
|
|
|
@ -2608,6 +2608,42 @@ TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSou
|
|||
return publicType;
|
||||
}
|
||||
|
||||
TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc)
|
||||
{
|
||||
TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
|
||||
if (node == nullptr)
|
||||
{
|
||||
error(loc, "erroneous switch statement", "switch");
|
||||
recover();
|
||||
return nullptr;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
|
||||
{
|
||||
TIntermCase *node = intermediate.addCase(condition, loc);
|
||||
if (node == nullptr)
|
||||
{
|
||||
error(loc, "erroneous case statement", "case");
|
||||
recover();
|
||||
return nullptr;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
|
||||
{
|
||||
TIntermCase *node = intermediate.addCase(nullptr, loc);
|
||||
if (node == nullptr)
|
||||
{
|
||||
error(loc, "erroneous default statement", "default");
|
||||
recover();
|
||||
return nullptr;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
|
||||
{
|
||||
TIntermTyped *node = intermediate.addUnaryMath(op, child, loc);
|
||||
|
|
|
@ -164,6 +164,10 @@ struct TParseContext {
|
|||
|
||||
bool structNestingErrorCheck(const TSourceLoc& line, const TField& field);
|
||||
|
||||
TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc);
|
||||
TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc);
|
||||
TIntermCase *addDefault(const TSourceLoc &loc);
|
||||
|
||||
TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &);
|
||||
TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &);
|
||||
TIntermTyped *addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right,
|
||||
|
|
|
@ -71,6 +71,8 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
|
|||
TIntermNodePair nodePair;
|
||||
TIntermTyped* intermTypedNode;
|
||||
TIntermAggregate* intermAggregate;
|
||||
TIntermSwitch* intermSwitch;
|
||||
TIntermCase* intermCase;
|
||||
};
|
||||
union {
|
||||
TPublicType type;
|
||||
|
@ -178,6 +180,8 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons
|
|||
%type <interm.intermNode> declaration external_declaration
|
||||
%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
|
||||
%type <interm.nodePair> selection_rest_statement for_rest_statement
|
||||
%type <interm.intermSwitch> switch_statement
|
||||
%type <interm.intermCase> case_label
|
||||
%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
|
||||
%type <interm> single_declaration init_declarator_list
|
||||
|
||||
|
@ -1521,12 +1525,14 @@ statement
|
|||
| simple_statement { $$ = $1; }
|
||||
;
|
||||
|
||||
// Grammar Note: No labeled statements; 'goto' is not supported.
|
||||
// Grammar Note: Labeled statements for SWITCH only; 'goto' is not supported.
|
||||
|
||||
simple_statement
|
||||
: declaration_statement { $$ = $1; }
|
||||
| expression_statement { $$ = $1; }
|
||||
| selection_statement { $$ = $1; }
|
||||
| switch_statement { $$ = $1; }
|
||||
| case_label { $$ = $1; }
|
||||
| iteration_statement { $$ = $1; }
|
||||
| jump_statement { $$ = $1; }
|
||||
;
|
||||
|
@ -1599,7 +1605,20 @@ selection_rest_statement
|
|||
}
|
||||
;
|
||||
|
||||
// Grammar Note: No 'switch'. Switch statements not supported.
|
||||
switch_statement
|
||||
: SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement {
|
||||
$$ = context->addSwitch($3, $5, @1);
|
||||
}
|
||||
;
|
||||
|
||||
case_label
|
||||
: CASE constant_expression COLON {
|
||||
$$ = context->addCase($2, @1);
|
||||
}
|
||||
| DEFAULT COLON {
|
||||
$$ = context->addDefault(@1);
|
||||
}
|
||||
;
|
||||
|
||||
condition
|
||||
// In 1996 c++ draft, conditions can include single declarations
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -204,6 +204,8 @@ union YYSTYPE
|
|||
TIntermNodePair nodePair;
|
||||
TIntermTyped* intermTypedNode;
|
||||
TIntermAggregate* intermAggregate;
|
||||
TIntermSwitch* intermSwitch;
|
||||
TIntermCase* intermCase;
|
||||
};
|
||||
union {
|
||||
TPublicType type;
|
||||
|
|
Загрузка…
Ссылка в новой задаче