Revision control

++ -- Copyright (C) 2021 The Qt Company Ltd.
++ -- SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ %decl glslparser.h
++ %impl glslparser.cpp
++ %parser GLSLParserTable
++ %token_prefix T_
++ %expect 1
++
++ %token FEED_GLSL "feed GLSL"
++ %token FEED_EXPRESSION "feed expression"
++
++ %token ADD_ASSIGN "+="
++ %token AMPERSAND "&"
++ %token AND_ASSIGN "&="
++ %token AND_OP "&&"
++ %token ATTRIBUTE "attribute"
++ %token BANG "!"
++ %token BOOL "bool"
++ %token BREAK "break"
++ %token BVEC2 "bvec2"
++ %token BVEC3 "bvec3"
++ %token BVEC4 "bvec4"
++ %token CARET "^"
++ %token CASE "case"
++ %token CENTROID "centroid"
++ %token COLON ":"
++ %token COMMA ","
++ %token CONST "const"
++ %token CONTINUE "continue"
++ %token DASH "-"
++ %token DEC_OP "--"
++ %token DEFAULT "default"
++ %token DISCARD "discard"
++ %token DIV_ASSIGN "/="
++ %token DMAT2 "dmat2"
++ %token DMAT2X2 "dmat2x2"
++ %token DMAT2X3 "dmat2x3"
++ %token DMAT2X4 "dmat2x4"
++ %token DMAT3 "dmat3"
++ %token DMAT3X2 "dmat3x2"
++ %token DMAT3X3 "dmat3x3"
++ %token DMAT3X4 "dmat3x4"
++ %token DMAT4 "dmat4"
++ %token DMAT4X2 "dmat4x2"
++ %token DMAT4X3 "dmat4x3"
++ %token DMAT4X4 "dmat4x4"
++ %token DO "do"
++ %token DOT "."
++ %token DOUBLE "double"
++ %token DVEC2 "dvec2"
++ %token DVEC3 "dvec3"
++ %token DVEC4 "dvec4"
++ %token ELSE "else"
++ %token EQUAL "="
++ %token EQ_OP "=="
++ %token FLAT "flat"
++ %token FLOAT "float"
++ %token FOR "for"
++ %token GE_OP ">="
++ %token HIGHP "highp"
++ %token IDENTIFIER "identifier"
++ %token IF "if"
++ %token IN "in"
++ %token INC_OP "++"
++ %token INOUT "inout"
++ %token INT "int"
++ %token INVARIANT "invariant"
++ %token ISAMPLER1D "isampler1D"
++ %token ISAMPLER1DARRAY "isampler1DArray"
++ %token ISAMPLER2D "isampler2D"
++ %token ISAMPLER2DARRAY "isampler2DArray"
++ %token ISAMPLER2DMS "isampler2DMS"
++ %token ISAMPLER2DMSARRAY "isampler2DMSArray"
++ %token ISAMPLER2DRECT "isampler2DRect"
++ %token ISAMPLER3D "isampler3D"
++ %token ISAMPLERBUFFER "isamplerBuffer"
++ %token ISAMPLERCUBE "isamplerCube"
++ %token ISAMPLERCUBEARRAY "isamplerCubeArray"
++ %token IVEC2 "ivec2"
++ %token IVEC3 "ivec3"
++ %token IVEC4 "ivec4"
++ %token LAYOUT "layout"
++ %token LEFT_ANGLE "<"
++ %token LEFT_ASSIGN "<<="
++ %token LEFT_BRACE "{"
++ %token LEFT_BRACKET "["
++ %token LEFT_OP "<<"
++ %token LEFT_PAREN "("
++ %token LE_OP "<="
++ %token LOWP "lowp"
++ %token MAT2 "mat2"
++ %token MAT2X2 "mat2x2"
++ %token MAT2X3 "mat2x3"
++ %token MAT2X4 "mat2x4"
++ %token MAT3 "mat3"
++ %token MAT3X2 "mat3x2"
++ %token MAT3X3 "mat3x3"
++ %token MAT3X4 "mat3x4"
++ %token MAT4 "mat4"
++ %token MAT4X2 "mat4x2"
++ %token MAT4X3 "mat4x3"
++ %token MAT4X4 "mat4x4"
++ %token MEDIUMP "mediump"
++ %token MOD_ASSIGN "%="
++ %token MUL_ASSIGN "*="
++ %token NE_OP "!="
++ %token NOPERSPECTIVE "noperspective"
++ %token NUMBER "number constant"
++ %token OR_ASSIGN "|="
++ %token OR_OP "||"
++ %token OUT "out"
++ %token PATCH "patch"
++ %token PERCENT "%"
++ %token PLUS "plus"
++ %token PRECISION "precision"
++ %token QUESTION "?"
++ %token RETURN "return"
++ %token RIGHT_ANGLE ">"
++ %token RIGHT_ASSIGN ">>="
++ %token RIGHT_BRACE "}"
++ %token RIGHT_BRACKET "]"
++ %token RIGHT_OP ">>"
++ %token RIGHT_PAREN ")"
++ %token SAMPLE "sample"
++ %token SAMPLER1D "sampler1D"
++ %token SAMPLER1DARRAY "sampler1DArray"
++ %token SAMPLER1DARRAYSHADOW "sampler1DArrayShadow"
++ %token SAMPLER1DSHADOW "sampler1DShadow"
++ %token SAMPLER2D "sampler2D"
++ %token SAMPLER2DARRAY "sampler2DArray"
++ %token SAMPLER2DARRAYSHADOW "sampler2DArrayShadow"
++ %token SAMPLER2DMS "sampler2DMS"
++ %token SAMPLER2DMSARRAY "sampler2DMSArray"
++ %token SAMPLER2DRECT "sampler2DRect"
++ %token SAMPLER2DRECTSHADOW "sampler2DRectShadow"
++ %token SAMPLER2DSHADOW "sampler2DShadow"
++ %token SAMPLER3D "sampler3D"
++ %token SAMPLERBUFFER "samplerBuffer"
++ %token SAMPLERCUBE "samplerCube"
++ %token SAMPLERCUBEARRAY "samplerCubeArray"
++ %token SAMPLERCUBEARRAYSHADOW "samplerCubeArrayShadow"
++ %token SAMPLERCUBESHADOW "samplerCubeShadow"
++ %token SEMICOLON ";"
++ %token SLASH "/"
++ %token SMOOTH "smooth"
++ %token STAR "*"
++ %token STRUCT "struct"
++ %token SUBROUTINE "subroutine"
++ %token SUB_ASSIGN "-="
++ %token SWITCH "switch"
++ %token TILDE "~"
++ %token TYPE_NAME "type_name"
++ %token UINT "uint"
++ %token UNIFORM "uniform"
++ %token USAMPLER1D "usampler1D"
++ %token USAMPLER1DARRAY "usampler1DArray"
++ %token USAMPLER2D "usampler2D"
++ %token USAMPLER2DARRAY "usampler2DArray"
++ %token USAMPLER2DMS "usampler2DMS"
++ %token USAMPLER2DMSARRAY "usampler2DMSarray"
++ %token USAMPLER2DRECT "usampler2DRect"
++ %token USAMPLER3D "usampler3D"
++ %token USAMPLERBUFFER "usamplerBuffer"
++ %token USAMPLERCUBE "usamplerCube"
++ %token USAMPLERCUBEARRAY "usamplerCubeArray"
++ %token UVEC2 "uvec2"
++ %token UVEC3 "uvec3"
++ %token UVEC4 "uvec4"
++ %token VARYING "varying"
++ %token VEC2 "vec2"
++ %token VEC3 "vec3"
++ %token VEC4 "vec4"
++ %token VERTICAL_BAR "|"
++ %token VOID "void"
++ %token WHILE "while"
++ %token XOR_ASSIGN "^="
++ %token XOR_OP "^^"
++ %token TRUE "true"
++ %token FALSE "false"
++ %token PREPROC "preprocessor directive"
++ %token COMMENT "comment"
++ %token ERROR "error"
++ %token RESERVED "reserved word"
++
++ %start toplevel
++
++ /:
++ // Copyright (C) 2021 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ #include "$header"
++ #include "glsllexer.h"
++ #include "glslast.h"
++ #include "glslengine.h"
++ #include <vector>
++ #include <stack>
++
++ namespace GLSL {
++
++ class GLSL_EXPORT Parser: public $table
++ {
++ public:
++ union Value {
++ void *ptr;
++ const QString *string;
++ AST *ast;
++ List<AST *> *ast_list;
++ DeclarationAST *declaration;
++ List<DeclarationAST *> *declaration_list;
++ ExpressionAST *expression;
++ List<ExpressionAST *> *expression_list;
++ StatementAST *statement;
++ List<StatementAST *> *statement_list;
++ TypeAST *type;
++ StructTypeAST::Field *field;
++ List<StructTypeAST::Field *> *field_list;
++ TranslationUnitAST *translation_unit;
++ FunctionIdentifierAST *function_identifier;
++ AST::Kind kind;
++ TypeAST::Precision precision;
++ struct {
++ StatementAST *thenClause;
++ StatementAST *elseClause;
++ } ifstmt;
++ struct {
++ ExpressionAST *condition;
++ ExpressionAST *increment;
++ } forstmt;
++ struct {
++ FunctionIdentifierAST *id;
++ List<ExpressionAST *> *arguments;
++ } function;
++ int qualifier;
++ LayoutQualifierAST *layout;
++ List<LayoutQualifierAST *> *layout_list;
++ struct {
++ int qualifier;
++ List<LayoutQualifierAST *> *layout_list;
++ } type_qualifier;
++ struct {
++ TypeAST *type;
++ const QString *name;
++ } param_declarator;
++ ParameterDeclarationAST *param_declaration;
++ FunctionDeclarationAST *function_declaration;
++ };
++
++ Parser(Engine *engine, const char *source, unsigned size, int variant);
++ ~Parser();
++
++ TranslationUnitAST *parse() {
++ if (AST *u = parse(T_FEED_GLSL))
++ return u->asTranslationUnit();
++ return nullptr;
++ }
++
++ ExpressionAST *parseExpression() {
++ if (AST *u = parse(T_FEED_EXPRESSION))
++ return u->asExpression();
++ return nullptr;
++ }
++
++ AST *parse(int startToken);
++
++ private:
++ // 1-based
++ int &location(int n) { return _locationStack[_tos + n - 1]; }
++ Value &sym(int n) { return _symStack[_tos + n - 1]; }
++ AST *&ast(int n) { return _symStack[_tos + n - 1].ast; }
++ const QString *&string(int n) { return _symStack[_tos + n - 1].string; }
++ ExpressionAST *&expression(int n) { return _symStack[_tos + n - 1].expression; }
++ StatementAST *&statement(int n) { return _symStack[_tos + n - 1].statement; }
++ TypeAST *&type(int n) { return _symStack[_tos + n - 1].type; }
++ FunctionDeclarationAST *&function(int n) { return _symStack[_tos + n - 1].function_declaration; }
++
++ inline int consumeToken() {
++ if (_index < int(_tokens.size()))
++ return _index++;
++ return static_cast<int>(_tokens.size()) - 1;
++ }
++ inline const Token &tokenAt(int index) const {
++ if (index == 0)
++ return _startToken;
++ return _tokens.at(index);
++ }
++ inline int tokenKind(int index) const {
++ if (index == 0)
++ return _startToken.kind;
++ return _tokens.at(index).kind;
++ }
++ void reduce(int ruleno);
++
++ void warning(int line, const QString &message)
++ {
++ _engine->warning(line, message);
++ }
++
++ void error(int line, const QString &message)
++ {
++ _engine->error(line, message);
++ }
++
++ template <typename T>
++ T *makeAstNode()
++ {
++ T *node = new (_engine->pool()) T ();
++ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
++ return node;
++ }
++
++ template <typename T, typename A1>
++ T *makeAstNode(A1 a1)
++ {
++ T *node = new (_engine->pool()) T (a1);
++ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
++ return node;
++ }
++
++ template <typename T, typename A1, typename A2>
++ T *makeAstNode(A1 a1, A2 a2)
++ {
++ T *node = new (_engine->pool()) T (a1, a2);
++ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
++ return node;
++ }
++
++ template <typename T, typename A1, typename A2, typename A3>
++ T *makeAstNode(A1 a1, A2 a2, A3 a3)
++ {
++ T *node = new (_engine->pool()) T (a1, a2, a3);
++ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
++ return node;
++ }
++
++ template <typename T, typename A1, typename A2, typename A3, typename A4>
++ T *makeAstNode(A1 a1, A2 a2, A3 a3, A4 a4)
++ {
++ T *node = new (_engine->pool()) T (a1, a2, a3, a4);
++ node->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
++ return node;
++ }
++
++ TypeAST *makeBasicType(int token)
++ {
++ TypeAST *type = new (_engine->pool()) BasicTypeAST(token, spell[token]);
++ type->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
++ return type;
++ }
++
++ private:
++ Engine *_engine;
++ int _tos;
++ int _index;
++ int yyloc;
++ int yytoken;
++ int yyrecovering;
++ bool _recovered;
++ Token _startToken;
++ std::vector<int> _stateStack;
++ std::vector<int> _locationStack;
++ std::vector<Value> _symStack;
++ std::vector<Token> _tokens;
++ };
++
++ } // namespace GLSL
++ :/
++
++ /.
++ // Copyright (C) 2021 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ #include "glslparser.h"
++ #include "glslengine.h"
++ #include <iostream>
++ #include <cstdio>
++ #include <cassert>
++ #include <QDebug>
++
++ using namespace GLSL;
++
++ Parser::Parser(Engine *engine, const char *source, unsigned size, int variant)
++ : _engine(engine), _tos(-1), _index(0), yyloc(-1), yytoken(-1), yyrecovering(0), _recovered(false)
++ {
++ _tokens.reserve(1024);
++
++ _stateStack.resize(128);
++ _locationStack.resize(128);
++ _symStack.resize(128);
++
++ _tokens.push_back(Token()); // invalid token
++
++ std::stack<int> parenStack;
++ std::stack<int> bracketStack;
++ std::stack<int> braceStack;
++
++ Lexer lexer(engine, source, size);
++ lexer.setVariant(variant);
++ Token tk;
++ do {
++ lexer.yylex(&tk);
++
++ switch (tk.kind) {
++ case T_LEFT_PAREN:
++ parenStack.push(static_cast<int>(_tokens.size()));
++ break;
++ case T_LEFT_BRACKET:
++ bracketStack.push(static_cast<int>(_tokens.size()));
++ break;
++ case T_LEFT_BRACE:
++ braceStack.push(static_cast<int>(_tokens.size()));
++ break;
++
++ case T_RIGHT_PAREN:
++ if (! parenStack.empty()) {
++ _tokens[parenStack.top()].matchingBrace = static_cast<int>(_tokens.size());
++ parenStack.pop();
++ }
++ break;
++ case T_RIGHT_BRACKET:
++ if (! bracketStack.empty()) {
++ _tokens[bracketStack.top()].matchingBrace = static_cast<int>(_tokens.size());
++ bracketStack.pop();
++ }
++ break;
++ case T_RIGHT_BRACE:
++ if (! braceStack.empty()) {
++ _tokens[braceStack.top()].matchingBrace = static_cast<int>(_tokens.size());
++ braceStack.pop();
++ }
++ break;
++ default:
++ break;
++ }
++
++ _tokens.push_back(tk);
++ } while (tk.isNot(EOF_SYMBOL));
++
++ _index = 0;
++ }
++
++ Parser::~Parser()
++ {
++ }
++
++ AST *Parser::parse(int startToken)
++ {
++ int action = 0;
++ yytoken = -1;
++ yyloc = -1;
++ void *yyval = 0; // value of the current token.
++
++ _recovered = false;
++ _tos = -1;
++ _startToken.kind = startToken;
++ int recoveryAttempts = 0;
++
++
++ do {
++ recoveryAttempts = 0;
++
++ againAfterRecovery:
++ if (unsigned(++_tos) == _stateStack.size()) {
++ _stateStack.resize(_tos * 2);
++ _locationStack.resize(_tos * 2);
++ _symStack.resize(_tos * 2);
++ }
++
++ _stateStack[_tos] = action;
++
++ if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) {
++ yyloc = consumeToken();
++ yytoken = tokenKind(yyloc);
++ if (yyrecovering)
++ --yyrecovering;
++ if (yytoken == T_IDENTIFIER && t_action(action, T_TYPE_NAME) != 0) {
++ const Token &la = tokenAt(_index);
++
++ if (la.is(T_IDENTIFIER)) {
++ yytoken = T_TYPE_NAME;
++ } else if (la.is(T_LEFT_BRACKET) && la.matchingBrace != 0 &&
++ tokenAt(la.matchingBrace + 1).is(T_IDENTIFIER)) {
++ yytoken = T_TYPE_NAME;
++ }
++ }
++ yyval = _tokens.at(yyloc).ptr;
++ }
++
++ action = t_action(action, yytoken);
++ if (action > 0) {
++ if (action == ACCEPT_STATE) {
++ --_tos;
++ return _symStack[0].translation_unit;
++ }
++ _symStack[_tos].ptr = yyval;
++ _locationStack[_tos] = yyloc;
++ yytoken = -1;
++ } else if (action < 0) {
++ const int ruleno = -action - 1;
++ const int N = rhs[ruleno];
++ _tos -= N;
++ reduce(ruleno);
++ action = nt_action(_stateStack[_tos], lhs[ruleno] - TERMINAL_COUNT);
++ } else if (action == 0) {
++ ++recoveryAttempts;
++ if (recoveryAttempts > 10)
++ break;
++ const int line = _tokens[yyloc].line + 1;
++ QString message = QLatin1String("Syntax error");
++ if (yytoken != -1) {
++ const QLatin1String s(spell[yytoken]);
++ message = QString::fromLatin1("Unexpected token `%1'").arg(s);
++ if (yytoken == 0) // do not freeze on unexpected end of file
++ return nullptr;
++ }
++
++ for (; _tos; --_tos) {
++ const int state = _stateStack[_tos];
++
++ static int tks1[] = {
++ T_RIGHT_BRACE, T_RIGHT_PAREN, T_RIGHT_BRACKET,
++ T_SEMICOLON, T_COLON, T_COMMA,
++ T_NUMBER, T_TYPE_NAME, T_IDENTIFIER,
++ T_LEFT_BRACE, T_LEFT_PAREN, T_LEFT_BRACKET,
++ T_WHILE,
++ 0
++ };
++ static int tks2[] = {
++ T_RIGHT_BRACE, T_RIGHT_PAREN, T_RIGHT_BRACKET,
++ T_SEMICOLON, T_COLON, T_COMMA,
++ 0
++ };
++ int *tks;
++ if (recoveryAttempts < 2)
++ tks = tks1;
++ else
++ tks = tks2; // Avoid running into an endless loop for e.g.: for(int x=0; x y
++
++ for (int *tptr = tks; *tptr; ++tptr) {
++ const int next = t_action(state, *tptr);
++ if (next > 0) {
++ if (! yyrecovering && ! _recovered) {
++ _recovered = true;
++ error(line, QString::fromLatin1("Expected `%1'").arg(QLatin1String(spell[*tptr])));
++ }
++
++ yyrecovering = 3;
++ if (*tptr == T_IDENTIFIER)
++ yyval = (void *) _engine->identifier(QLatin1String("$identifier"));
++ else if (*tptr == T_NUMBER || *tptr == T_TYPE_NAME)
++ yyval = (void *) _engine->identifier(QLatin1String("$0"));
++ else
++ yyval = 0;
++
++ _symStack[_tos].ptr = yyval;
++ _locationStack[_tos] = yyloc;
++ yytoken = -1;
++
++ action = next;
++ goto againAfterRecovery;
++ }
++ }
++ }
++
++ if (! _recovered) {
++ _recovered = true;
++ error(line, message);
++ }
++ }
++
++ } while (action);
++
++ return nullptr;
++ }
++ ./
++
++
++
++ /.
++ void Parser::reduce(int ruleno)
++ {
++ switch(ruleno) {
++ ./
++
++
++
++ variable_identifier ::= IDENTIFIER ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<IdentifierExpressionAST>(string(1));
++ } break;
++ ./
++
++ primary_expression ::= NUMBER ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<LiteralExpressionAST>(string(1));
++ } break;
++ ./
++
++ primary_expression ::= TRUE ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<LiteralExpressionAST>(_engine->identifier("true", 4));
++ } break;
++ ./
++
++ primary_expression ::= FALSE ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<LiteralExpressionAST>(_engine->identifier("false", 5));
++ } break;
++ ./
++
++ primary_expression ::= variable_identifier ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ primary_expression ::= LEFT_PAREN expression RIGHT_PAREN ;
++ /.
++ case $rule_number: {
++ ast(1) = ast(2);
++ } break;
++ ./
++
++ postfix_expression ::= primary_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ postfix_expression ::= postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_ArrayAccess, expression(1), expression(3));
++ } break;
++ ./
++
++ postfix_expression ::= function_call ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ postfix_expression ::= postfix_expression DOT IDENTIFIER ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<MemberAccessExpressionAST>(expression(1), string(3));
++ } break;
++ ./
++
++ postfix_expression ::= postfix_expression INC_OP ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<UnaryExpressionAST>(AST::Kind_PostIncrement, expression(1));
++ } break;
++ ./
++
++ postfix_expression ::= postfix_expression DEC_OP ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<UnaryExpressionAST>(AST::Kind_PostDecrement, expression(1));
++ } break;
++ ./
++
++ integer_expression ::= expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ function_call ::= function_call_or_method ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ function_call_or_method ::= function_call_generic ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<FunctionCallExpressionAST>
++ (sym(1).function.id, sym(1).function.arguments);
++ } break;
++ ./
++
++ function_call_or_method ::= postfix_expression DOT function_call_generic ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<FunctionCallExpressionAST>
++ (expression(1), sym(3).function.id, sym(3).function.arguments);
++ } break;
++ ./
++
++ function_call_generic ::= function_call_header_with_parameters RIGHT_PAREN ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ function_call_generic ::= function_call_header_no_parameters RIGHT_PAREN ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ function_call_header_no_parameters ::= function_call_header VOID ;
++ /.
++ case $rule_number: {
++ sym(1).function.id = sym(1).function_identifier;
++ sym(1).function.arguments = 0;
++ } break;
++ ./
++
++ function_call_header_no_parameters ::= function_call_header ;
++ /.
++ case $rule_number: {
++ sym(1).function.id = sym(1).function_identifier;
++ sym(1).function.arguments = 0;
++ } break;
++ ./
++
++ function_call_header_with_parameters ::= function_call_header assignment_expression ;
++ /.
++ case $rule_number: {
++ sym(1).function.id = sym(1).function_identifier;
++ sym(1).function.arguments =
++ makeAstNode< List<ExpressionAST *> >(expression(2));
++ } break;
++ ./
++
++ function_call_header_with_parameters ::= function_call_header_with_parameters COMMA assignment_expression ;
++ /.
++ case $rule_number: {
++ sym(1).function.arguments =
++ makeAstNode< List<ExpressionAST *> >
++ (sym(1).function.arguments, expression(3));
++ } break;
++ ./
++
++ function_call_header ::= function_identifier LEFT_PAREN ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ function_identifier ::= type_specifier ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<FunctionIdentifierAST>(type(1));
++ } break;
++ ./
++
++ function_identifier ::= IDENTIFIER ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<FunctionIdentifierAST>(string(1));
++ } break;
++ ./
++
++ unary_expression ::= postfix_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ unary_expression ::= INC_OP unary_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<UnaryExpressionAST>(AST::Kind_PreIncrement, expression(2));
++ } break;
++ ./
++
++ unary_expression ::= DEC_OP unary_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<UnaryExpressionAST>(AST::Kind_PreDecrement, expression(2));
++ } break;
++ ./
++
++ unary_expression ::= unary_operator unary_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<UnaryExpressionAST>(sym(1).kind, expression(2));
++ } break;
++ ./
++
++ unary_operator ::= PLUS ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_UnaryPlus;
++ } break;
++ ./
++
++ unary_operator ::= DASH ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_UnaryMinus;
++ } break;
++ ./
++
++ unary_operator ::= BANG ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_LogicalNot;
++ } break;
++ ./
++
++ unary_operator ::= TILDE ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_BitwiseNot;
++ } break;
++ ./
++
++ multiplicative_expression ::= unary_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ multiplicative_expression ::= multiplicative_expression STAR unary_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Multiply, expression(1), expression(3));
++ } break;
++ ./
++
++ multiplicative_expression ::= multiplicative_expression SLASH unary_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Divide, expression(1), expression(3));
++ } break;
++ ./
++
++ multiplicative_expression ::= multiplicative_expression PERCENT unary_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Modulus, expression(1), expression(3));
++ } break;
++ ./
++
++ additive_expression ::= multiplicative_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ additive_expression ::= additive_expression PLUS multiplicative_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Plus, expression(1), expression(3));
++ } break;
++ ./
++
++ additive_expression ::= additive_expression DASH multiplicative_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Minus, expression(1), expression(3));
++ } break;
++ ./
++
++ shift_expression ::= additive_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ shift_expression ::= shift_expression LEFT_OP additive_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_ShiftLeft, expression(1), expression(3));
++ } break;
++ ./
++
++ shift_expression ::= shift_expression RIGHT_OP additive_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_ShiftRight, expression(1), expression(3));
++ } break;
++ ./
++
++ relational_expression ::= shift_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ relational_expression ::= relational_expression LEFT_ANGLE shift_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LessThan, expression(1), expression(3));
++ } break;
++ ./
++
++ relational_expression ::= relational_expression RIGHT_ANGLE shift_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_GreaterThan, expression(1), expression(3));
++ } break;
++ ./
++
++ relational_expression ::= relational_expression LE_OP shift_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LessEqual, expression(1), expression(3));
++ } break;
++ ./
++
++ relational_expression ::= relational_expression GE_OP shift_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_GreaterEqual, expression(1), expression(3));
++ } break;
++ ./
++
++ equality_expression ::= relational_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ equality_expression ::= equality_expression EQ_OP relational_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Equal, expression(1), expression(3));
++ } break;
++ ./
++
++ equality_expression ::= equality_expression NE_OP relational_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_NotEqual, expression(1), expression(3));
++ } break;
++ ./
++
++ and_expression ::= equality_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ and_expression ::= and_expression AMPERSAND equality_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_BitwiseAnd, expression(1), expression(3));
++ } break;
++ ./
++
++ exclusive_or_expression ::= and_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ exclusive_or_expression ::= exclusive_or_expression CARET and_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_BitwiseXor, expression(1), expression(3));
++ } break;
++ ./
++
++ inclusive_or_expression ::= exclusive_or_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ inclusive_or_expression ::= inclusive_or_expression VERTICAL_BAR exclusive_or_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_BitwiseOr, expression(1), expression(3));
++ } break;
++ ./
++
++ logical_and_expression ::= inclusive_or_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ logical_and_expression ::= logical_and_expression AND_OP inclusive_or_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LogicalAnd, expression(1), expression(3));
++ } break;
++ ./
++
++ logical_xor_expression ::= logical_and_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ logical_xor_expression ::= logical_xor_expression XOR_OP logical_and_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LogicalXor, expression(1), expression(3));
++ } break;
++ ./
++
++ logical_or_expression ::= logical_xor_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ logical_or_expression ::= logical_or_expression OR_OP logical_xor_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_LogicalOr, expression(1), expression(3));
++ } break;
++ ./
++
++ conditional_expression ::= logical_or_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ conditional_expression ::= logical_or_expression QUESTION expression COLON assignment_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<TernaryExpressionAST>(AST::Kind_Conditional, expression(1), expression(3), expression(5));
++ } break;
++ ./
++
++ assignment_expression ::= conditional_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ assignment_expression ::= unary_expression assignment_operator assignment_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<AssignmentExpressionAST>(sym(2).kind, expression(1), expression(3));
++ } break;
++ ./
++
++ assignment_operator ::= EQUAL ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_Assign;
++ } break;
++ ./
++
++ assignment_operator ::= MUL_ASSIGN ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_AssignMultiply;
++ } break;
++ ./
++
++ assignment_operator ::= DIV_ASSIGN ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_AssignDivide;
++ } break;
++ ./
++
++ assignment_operator ::= MOD_ASSIGN ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_AssignModulus;
++ } break;
++ ./
++
++ assignment_operator ::= ADD_ASSIGN ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_AssignPlus;
++ } break;
++ ./
++
++ assignment_operator ::= SUB_ASSIGN ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_AssignMinus;
++ } break;
++ ./
++
++ assignment_operator ::= LEFT_ASSIGN ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_AssignShiftLeft;
++ } break;
++ ./
++
++ assignment_operator ::= RIGHT_ASSIGN ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_AssignShiftRight;
++ } break;
++ ./
++
++ assignment_operator ::= AND_ASSIGN ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_AssignAnd;
++ } break;
++ ./
++
++ assignment_operator ::= XOR_ASSIGN ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_AssignXor;
++ } break;
++ ./
++
++ assignment_operator ::= OR_ASSIGN ;
++ /.
++ case $rule_number: {
++ sym(1).kind = AST::Kind_AssignOr;
++ } break;
++ ./
++
++ expression ::= assignment_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ expression ::= expression COMMA assignment_expression ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<BinaryExpressionAST>(AST::Kind_Comma, expression(1), expression(3));
++ } break;
++ ./
++
++ constant_expression ::= conditional_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ declaration ::= function_prototype SEMICOLON ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ declaration ::= init_declarator_list SEMICOLON ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<InitDeclarationAST>(sym(1).declaration_list);
++ } break;
++ ./
++
++ declaration ::= PRECISION precision_qualifier type_specifier_no_prec SEMICOLON ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<PrecisionDeclarationAST>(sym(2).precision, type(3));
++ } break;
++ ./
++
++ declaration ::= type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON ;
++ /.
++ case $rule_number: {
++ if (sym(1).type_qualifier.qualifier != QualifiedTypeAST::Struct) {
++ // TODO: issue an error if the qualifier is not "struct".
++ }
++ TypeAST *type = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
++ ast(1) = makeAstNode<TypeDeclarationAST>(type);
++ } break;
++ ./
++
++ declaration ::= type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON ;
++ /.
++ case $rule_number: {
++ if ((sym(1).type_qualifier.qualifier & QualifiedTypeAST::Struct) == 0) {
++ // TODO: issue an error if the qualifier does not contain "struct".
++ }
++ TypeAST *type = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
++ TypeAST *qualtype = type;
++ if (sym(1).type_qualifier.qualifier != QualifiedTypeAST::Struct) {
++ qualtype = makeAstNode<QualifiedTypeAST>
++ (sym(1).type_qualifier.qualifier & ~QualifiedTypeAST::Struct, qualtype,
++ sym(1).type_qualifier.layout_list);
++ }
++ ast(1) = makeAstNode<TypeAndVariableDeclarationAST>
++ (makeAstNode<TypeDeclarationAST>(type),
++ makeAstNode<VariableDeclarationAST>(qualtype, string(6)));
++ } break;
++ ./
++
++ declaration ::= type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET RIGHT_BRACKET SEMICOLON ;
++ /.
++ case $rule_number: {
++ if ((sym(1).type_qualifier.qualifier & QualifiedTypeAST::Struct) == 0) {
++ // TODO: issue an error if the qualifier does not contain "struct".
++ }
++ TypeAST *type = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
++ TypeAST *qualtype = type;
++ if (sym(1).type_qualifier.qualifier != QualifiedTypeAST::Struct) {
++ qualtype = makeAstNode<QualifiedTypeAST>
++ (sym(1).type_qualifier.qualifier & ~QualifiedTypeAST::Struct, qualtype,
++ sym(1).type_qualifier.layout_list);
++ }
++ ast(1) = makeAstNode<TypeAndVariableDeclarationAST>
++ (makeAstNode<TypeDeclarationAST>(type),
++ makeAstNode<VariableDeclarationAST>
++ (makeAstNode<ArrayTypeAST>(qualtype), string(6)));
++ } break;
++ ./
++
++ declaration ::= type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON ;
++ /.
++ case $rule_number: {
++ if ((sym(1).type_qualifier.qualifier & QualifiedTypeAST::Struct) == 0) {
++ // TODO: issue an error if the qualifier does not contain "struct".
++ }
++ TypeAST *type = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
++ TypeAST *qualtype = type;
++ if (sym(1).type_qualifier.qualifier != QualifiedTypeAST::Struct) {
++ qualtype = makeAstNode<QualifiedTypeAST>
++ (sym(1).type_qualifier.qualifier & ~QualifiedTypeAST::Struct, qualtype,
++ sym(1).type_qualifier.layout_list);
++ }
++ ast(1) = makeAstNode<TypeAndVariableDeclarationAST>
++ (makeAstNode<TypeDeclarationAST>(type),
++ makeAstNode<VariableDeclarationAST>
++ (makeAstNode<ArrayTypeAST>(qualtype, expression(8)), string(6)));
++ } break;
++ ./
++
++ declaration ::= type_qualifier SEMICOLON ;
++ /.
++ case $rule_number: {
++ TypeAST *type = makeAstNode<QualifiedTypeAST>
++ (sym(1).type_qualifier.qualifier, (TypeAST *)0,
++ sym(1).type_qualifier.layout_list);
++ ast(1) = makeAstNode<TypeDeclarationAST>(type);
++ } break;
++ ./
++
++ function_prototype ::= function_declarator RIGHT_PAREN ;
++ /.
++ case $rule_number: {
++ function(1)->finishParams();
++ } break;
++ ./
++
++ function_declarator ::= function_header ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ function_declarator ::= function_header_with_parameters ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ function_header_with_parameters ::= function_header parameter_declaration ;
++ /.
++ case $rule_number: {
++ function(1)->params = makeAstNode< List<ParameterDeclarationAST *> >
++ (sym(2).param_declaration);
++ } break;
++ ./
++
++ function_header_with_parameters ::= function_header_with_parameters COMMA parameter_declaration ;
++ /.
++ case $rule_number: {
++ function(1)->params = makeAstNode< List<ParameterDeclarationAST *> >
++ (function(1)->params, sym(3).param_declaration);
++ } break;
++ ./
++
++ function_header ::= fully_specified_type IDENTIFIER LEFT_PAREN ;
++ /.
++ case $rule_number: {
++ function(1) = makeAstNode<FunctionDeclarationAST>(type(1), string(2));
++ } break;
++ ./
++
++ parameter_declarator ::= type_specifier IDENTIFIER ;
++ /.
++ case $rule_number: {
++ sym(1).param_declarator.type = type(1);
++ sym(1).param_declarator.name = string(2);
++ } break;
++ ./
++
++ parameter_declarator ::= type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ;
++ /.
++ case $rule_number: {
++ sym(1).param_declarator.type = makeAstNode<ArrayTypeAST>(type(1), expression(4));
++ sym(1).param_declarator.name = string(2);
++ } break;
++ ./
++
++ parameter_declaration ::= parameter_type_qualifier parameter_qualifier parameter_declarator ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<ParameterDeclarationAST>
++ (makeAstNode<QualifiedTypeAST>
++ (sym(1).qualifier, sym(3).param_declarator.type,
++ (List<LayoutQualifierAST *> *)0),
++ ParameterDeclarationAST::Qualifier(sym(2).qualifier),
++ sym(3).param_declarator.name);
++ } break;
++ ./
++
++ parameter_declaration ::= parameter_qualifier parameter_declarator ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<ParameterDeclarationAST>
++ (sym(2).param_declarator.type,
++ ParameterDeclarationAST::Qualifier(sym(1).qualifier),
++ sym(2).param_declarator.name);
++ } break;
++ ./
++
++ parameter_declaration ::= parameter_type_qualifier parameter_qualifier parameter_type_specifier ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<ParameterDeclarationAST>
++ (makeAstNode<QualifiedTypeAST>
++ (sym(1).qualifier, type(3), (List<LayoutQualifierAST *> *)0),
++ ParameterDeclarationAST::Qualifier(sym(2).qualifier),
++ (const QString *)0);
++ } break;
++ ./
++
++ parameter_declaration ::= parameter_qualifier parameter_type_specifier ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<ParameterDeclarationAST>
++ (type(2), ParameterDeclarationAST::Qualifier(sym(1).qualifier),
++ (const QString *)0);
++ } break;
++ ./
++
++ parameter_qualifier ::= empty ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = ParameterDeclarationAST::In;
++ } break;
++ ./
++
++ parameter_qualifier ::= IN ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = ParameterDeclarationAST::In;
++ } break;
++ ./
++
++ parameter_qualifier ::= OUT ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = ParameterDeclarationAST::Out;
++ } break;
++ ./
++
++ parameter_qualifier ::= INOUT ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = ParameterDeclarationAST::InOut;
++ } break;
++ ./
++
++ parameter_type_specifier ::= type_specifier ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ init_declarator_list ::= single_declaration ;
++ /.
++ case $rule_number: {
++ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
++ (sym(1).declaration);
++ } break;
++ ./
++
++ init_declarator_list ::= init_declarator_list COMMA IDENTIFIER ;
++ /.
++ case $rule_number: {
++ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
++ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>(type, string(3));
++ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
++ (sym(1).declaration_list, decl);
++ } break;
++ ./
++
++ init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ;
++ /.
++ case $rule_number: {
++ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
++ type = makeAstNode<ArrayTypeAST>(type);
++ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>(type, string(3));
++ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
++ (sym(1).declaration_list, decl);
++ } break;
++ ./
++
++ init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ;
++ /.
++ case $rule_number: {
++ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
++ type = makeAstNode<ArrayTypeAST>(type, expression(5));
++ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>(type, string(3));
++ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
++ (sym(1).declaration_list, decl);
++ } break;
++ ./
++
++ init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer ;
++ /.
++ case $rule_number: {
++ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
++ type = makeAstNode<ArrayTypeAST>(type);
++ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>
++ (type, string(3), expression(7));
++ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
++ (sym(1).declaration_list, decl);
++ } break;
++ ./
++
++ init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer ;
++ /.
++ case $rule_number: {
++ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
++ type = makeAstNode<ArrayTypeAST>(type, expression(5));
++ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>
++ (type, string(3), expression(8));
++ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
++ (sym(1).declaration_list, decl);
++ } break;
++ ./
++
++ init_declarator_list ::= init_declarator_list COMMA IDENTIFIER EQUAL initializer ;
++ /.
++ case $rule_number: {
++ TypeAST *type = VariableDeclarationAST::declarationType(sym(1).declaration_list);
++ DeclarationAST *decl = makeAstNode<VariableDeclarationAST>
++ (type, string(3), expression(5));
++ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
++ (sym(1).declaration_list, decl);
++ } break;
++ ./
++
++ single_declaration ::= fully_specified_type ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<TypeDeclarationAST>(type(1));
++ } break;
++ ./
++
++ single_declaration ::= fully_specified_type IDENTIFIER ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<VariableDeclarationAST>(type(1), string(2));
++ } break;
++ ./
++
++ single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<VariableDeclarationAST>
++ (makeAstNode<ArrayTypeAST>(type(1)), string(2));
++ } break;
++ ./
++
++ single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<VariableDeclarationAST>
++ (makeAstNode<ArrayTypeAST>(type(1), expression(4)), string(2));
++ } break;
++ ./
++
++ single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<VariableDeclarationAST>
++ (makeAstNode<ArrayTypeAST>(type(1)), string(2), expression(6));
++ } break;
++ ./
++
++ single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<VariableDeclarationAST>
++ (makeAstNode<ArrayTypeAST>(type(1), expression(4)),
++ string(2), expression(7));
++ } break;
++ ./
++
++ single_declaration ::= fully_specified_type IDENTIFIER EQUAL initializer ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<VariableDeclarationAST>
++ (type(1), string(2), expression(4));
++ } break;
++ ./
++
++ single_declaration ::= INVARIANT IDENTIFIER ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<InvariantDeclarationAST>(string(2));
++ } break;
++ ./
++
++ fully_specified_type ::= type_specifier ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<QualifiedTypeAST>(0, type(1), (List<LayoutQualifierAST *> *)0);
++ } break;
++ ./
++
++ fully_specified_type ::= type_qualifier type_specifier ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<QualifiedTypeAST>
++ (sym(1).type_qualifier.qualifier, type(2),
++ sym(1).type_qualifier.layout_list);
++ } break;
++ ./
++
++ invariant_qualifier ::= INVARIANT ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::Invariant;
++ } break;
++ ./
++
++ interpolation_qualifier ::= SMOOTH ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::Smooth;
++ } break;
++ ./
++
++ interpolation_qualifier ::= FLAT ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::Flat;
++ } break;
++ ./
++
++ interpolation_qualifier ::= NOPERSPECTIVE ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::NoPerspective;
++ } break;
++ ./
++
++ layout_qualifier ::= LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN ;
++ /.
++ case $rule_number: {
++ sym(1) = sym(3);
++ } break;
++ ./
++
++ layout_qualifier_id_list ::= layout_qualifier_id ;
++ /.
++ case $rule_number: {
++ sym(1).layout_list = makeAstNode< List<LayoutQualifierAST *> >(sym(1).layout);
++ } break;
++ ./
++
++ layout_qualifier_id_list ::= layout_qualifier_id_list COMMA layout_qualifier_id ;
++ /.
++ case $rule_number: {
++ sym(1).layout_list = makeAstNode< List<LayoutQualifierAST *> >(sym(1).layout_list, sym(3).layout);
++ } break;
++ ./
++
++ layout_qualifier_id ::= IDENTIFIER ;
++ /.
++ case $rule_number: {
++ sym(1).layout = makeAstNode<LayoutQualifierAST>(string(1), (const QString *)0);
++ } break;
++ ./
++
++ layout_qualifier_id ::= IDENTIFIER EQUAL NUMBER ;
++ /.
++ case $rule_number: {
++ sym(1).layout = makeAstNode<LayoutQualifierAST>(string(1), string(3));
++ } break;
++ ./
++
++ parameter_type_qualifier ::= CONST ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::Const;
++ } break;
++ ./
++
++ type_qualifier ::= storage_qualifier ;
++ /.
++ case $rule_number: {
++ sym(1).type_qualifier.qualifier = sym(1).qualifier;
++ sym(1).type_qualifier.layout_list = 0;
++ } break;
++ ./
++
++ type_qualifier ::= layout_qualifier ;
++ /.
++ case $rule_number: {
++ sym(1).type_qualifier.layout_list = sym(1).layout_list;
++ sym(1).type_qualifier.qualifier = 0;
++ } break;
++ ./
++
++ type_qualifier ::= layout_qualifier storage_qualifier ;
++ /.
++ case $rule_number: {
++ sym(1).type_qualifier.layout_list = sym(1).layout_list;
++ sym(1).type_qualifier.qualifier = sym(2).qualifier;
++ } break;
++ ./
++
++ type_qualifier ::= interpolation_qualifier storage_qualifier ;
++ /.
++ case $rule_number: {
++ sym(1).type_qualifier.qualifier = sym(1).qualifier | sym(2).qualifier;
++ sym(1).type_qualifier.layout_list = 0;
++ } break;
++ ./
++
++ type_qualifier ::= interpolation_qualifier ;
++ /.
++ case $rule_number: {
++ sym(1).type_qualifier.qualifier = sym(1).qualifier;
++ sym(1).type_qualifier.layout_list = 0;
++ } break;
++ ./
++
++ type_qualifier ::= invariant_qualifier storage_qualifier ;
++ /.
++ case $rule_number: {
++ sym(1).type_qualifier.qualifier = sym(1).qualifier | sym(2).qualifier;
++ sym(1).type_qualifier.layout_list = 0;
++ } break;
++ ./
++
++ type_qualifier ::= invariant_qualifier interpolation_qualifier storage_qualifier ;
++ /.
++ case $rule_number: {
++ sym(1).type_qualifier.qualifier = sym(1).qualifier | sym(2).qualifier | sym(3).qualifier;
++ sym(1).type_qualifier.layout_list = 0;
++ } break;
++ ./
++
++ type_qualifier ::= INVARIANT ;
++ /.
++ case $rule_number: {
++ sym(1).type_qualifier.qualifier = QualifiedTypeAST::Invariant;
++ sym(1).type_qualifier.layout_list = 0;
++ } break;
++ ./
++
++ storage_qualifier ::= CONST ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::Const;
++ } break;
++ ./
++
++ storage_qualifier ::= ATTRIBUTE ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::Attribute;
++ } break;
++ ./
++
++ storage_qualifier ::= VARYING ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::Varying;
++ } break;
++ ./
++
++ storage_qualifier ::= CENTROID VARYING ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::CentroidVarying;
++ } break;
++ ./
++
++ storage_qualifier ::= IN ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::In;
++ } break;
++ ./
++
++ storage_qualifier ::= OUT ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::Out;
++ } break;
++ ./
++
++ storage_qualifier ::= CENTROID IN ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::CentroidIn;
++ } break;
++ ./
++
++ storage_qualifier ::= CENTROID OUT ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::CentroidOut;
++ } break;
++ ./
++
++ storage_qualifier ::= PATCH IN ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::PatchIn;
++ } break;
++ ./
++
++ storage_qualifier ::= PATCH OUT ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::PatchOut;
++ } break;
++ ./
++
++ storage_qualifier ::= SAMPLE IN ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::SampleIn;
++ } break;
++ ./
++
++ storage_qualifier ::= SAMPLE OUT ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::SampleOut;
++ } break;
++ ./
++
++ storage_qualifier ::= UNIFORM ;
++ /.
++ case $rule_number: {
++ sym(1).qualifier = QualifiedTypeAST::Uniform;
++ } break;
++ ./
++
++ type_specifier ::= type_specifier_no_prec ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ type_specifier ::= precision_qualifier type_specifier_no_prec ;
++ /.
++ case $rule_number: {
++ if (!type(2)->setPrecision(sym(1).precision)) {
++ // TODO: issue an error about precision not allowed on this type.
++ }
++ ast(1) = type(2);
++ } break;
++ ./
++
++ type_specifier_no_prec ::= type_specifier_nonarray ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ type_specifier_no_prec ::= type_specifier_nonarray LEFT_BRACKET RIGHT_BRACKET ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<ArrayTypeAST>(type(1));
++ } break;
++ ./
++
++ type_specifier_no_prec ::= type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<ArrayTypeAST>(type(1), expression(3));
++ } break;
++ ./
++
++ type_specifier_nonarray ::= VOID ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_VOID);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= FLOAT ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_FLOAT);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DOUBLE ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DOUBLE);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= INT ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_INT);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= UINT ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_UINT);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= BOOL ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_BOOL);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= VEC2 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_VEC2);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= VEC3 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_VEC3);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= VEC4 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_VEC4);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DVEC2 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DVEC2);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DVEC3 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DVEC3);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DVEC4 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DVEC4);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= BVEC2 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_BVEC2);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= BVEC3 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_BVEC3);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= BVEC4 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_BVEC4);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= IVEC2 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_IVEC2);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= IVEC3 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_IVEC3);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= IVEC4 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_IVEC4);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= UVEC2 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_UVEC2);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= UVEC3 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_UVEC3);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= UVEC4 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_UVEC4);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= MAT2 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_MAT2);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= MAT3 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_MAT3);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= MAT4 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_MAT4);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= MAT2X2 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_MAT2);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= MAT2X3 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_MAT2X3);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= MAT2X4 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_MAT2X4);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= MAT3X2 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_MAT3X2);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= MAT3X3 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_MAT3);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= MAT3X4 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_MAT3X4);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= MAT4X2 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_MAT4X2);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= MAT4X3 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_MAT4X3);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= MAT4X4 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_MAT4);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DMAT2 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DMAT2);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DMAT3 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DMAT3);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DMAT4 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DMAT4);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DMAT2X2 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DMAT2);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DMAT2X3 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DMAT2X3);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DMAT2X4 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DMAT2X4);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DMAT3X2 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DMAT3X2);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DMAT3X3 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DMAT3);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DMAT3X4 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DMAT3X4);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DMAT4X2 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DMAT4X2);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DMAT4X3 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DMAT4X3);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= DMAT4X4 ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_DMAT4);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLER1D ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLER1D);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLER2D ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLER2D);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLER3D ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLER3D);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLERCUBE ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLERCUBE);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLER1DSHADOW ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLER1DSHADOW);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLER2DSHADOW ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLER2DSHADOW);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLERCUBESHADOW ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLERCUBESHADOW);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLER1DARRAY ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLER1DARRAY);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLER2DARRAY ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLER2DARRAY);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLER1DARRAYSHADOW ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLER1DARRAYSHADOW);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLER2DARRAYSHADOW ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLER2DARRAYSHADOW);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLERCUBEARRAY ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLERCUBEARRAY);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLERCUBEARRAYSHADOW ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLERCUBEARRAYSHADOW);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= ISAMPLER1D ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_ISAMPLER1D);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= ISAMPLER2D ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_ISAMPLER2D);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= ISAMPLER3D ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_ISAMPLER3D);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= ISAMPLERCUBE ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_ISAMPLERCUBE);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= ISAMPLER1DARRAY ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_ISAMPLER1DARRAY);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= ISAMPLER2DARRAY ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_ISAMPLER2DARRAY);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= ISAMPLERCUBEARRAY ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_ISAMPLERCUBEARRAY);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= USAMPLER1D ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_USAMPLER1D);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= USAMPLER2D ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_USAMPLER2D);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= USAMPLER3D ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_USAMPLER3D);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= USAMPLERCUBE ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_USAMPLERCUBE);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= USAMPLER1DARRAY ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_USAMPLER1DARRAY);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= USAMPLER2DARRAY ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_USAMPLER2DARRAY);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= USAMPLERCUBEARRAY ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_USAMPLERCUBEARRAY);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLER2DRECT ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLER2DRECT);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLER2DRECTSHADOW ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLER2DRECTSHADOW);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= ISAMPLER2DRECT ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_ISAMPLER2DRECT);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= USAMPLER2DRECT ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_USAMPLER2DRECT);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLERBUFFER ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLERBUFFER);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= ISAMPLERBUFFER ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_ISAMPLERBUFFER);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= USAMPLERBUFFER ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_USAMPLERBUFFER);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLER2DMS ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLER2DMS);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= ISAMPLER2DMS ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_ISAMPLER2DMS);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= USAMPLER2DMS ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_USAMPLER2DMS);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= SAMPLER2DMSARRAY ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_SAMPLER2DMSARRAY);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= ISAMPLER2DMSARRAY ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_ISAMPLER2DMSARRAY);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= USAMPLER2DMSARRAY ;
++ /.
++ case $rule_number: {
++ ast(1) = makeBasicType(T_USAMPLER2DMSARRAY);
++ } break;
++ ./
++
++ type_specifier_nonarray ::= struct_specifier ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ type_specifier_nonarray ::= TYPE_NAME ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<NamedTypeAST>(string(1));
++ } break;
++ ./
++
++ precision_qualifier ::= HIGHP ;
++ /.
++ case $rule_number: {
++ sym(1).precision = TypeAST::Highp;
++ } break;
++ ./
++
++ precision_qualifier ::= MEDIUMP ;
++ /.
++ case $rule_number: {
++ sym(1).precision = TypeAST::Mediump;
++ } break;
++ ./
++
++ precision_qualifier ::= LOWP ;
++ /.
++ case $rule_number: {
++ sym(1).precision = TypeAST::Lowp;
++ } break;
++ ./
++
++ struct_specifier ::= STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<StructTypeAST>(string(2), sym(4).field_list);
++ } break;
++ ./
++
++ struct_specifier ::= STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<StructTypeAST>(sym(3).field_list);
++ } break;
++ ./
++
++ struct_declaration_list ::= struct_declaration ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ struct_declaration_list ::= struct_declaration_list struct_declaration ;
++ /.
++ case $rule_number: {
++ sym(1).field_list = appendLists(sym(1).field_list, sym(2).field_list);
++ } break;
++ ./
++
++ struct_declaration ::= type_specifier struct_declarator_list SEMICOLON ;
++ /.
++ case $rule_number: {
++ sym(1).field_list = StructTypeAST::fixInnerTypes(type(1), sym(2).field_list);
++ } break;
++ ./
++
++ struct_declaration ::= type_qualifier type_specifier struct_declarator_list SEMICOLON ;
++ /.
++ case $rule_number: {
++ sym(1).field_list = StructTypeAST::fixInnerTypes
++ (makeAstNode<QualifiedTypeAST>
++ (sym(1).type_qualifier.qualifier, type(2),
++ sym(1).type_qualifier.layout_list), sym(3).field_list);
++ } break;
++ ./
++
++ struct_declarator_list ::= struct_declarator ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ sym(1).field_list = makeAstNode< List<StructTypeAST::Field *> >(sym(1).field);
++ } break;
++ ./
++
++ struct_declarator_list ::= struct_declarator_list COMMA struct_declarator ;
++ /.
++ case $rule_number: {
++ sym(1).field_list = makeAstNode< List<StructTypeAST::Field *> >(sym(1).field_list, sym(3).field);
++ } break;
++ ./
++
++ struct_declarator ::= IDENTIFIER ;
++ /.
++ case $rule_number: {
++ sym(1).field = makeAstNode<StructTypeAST::Field>(string(1));
++ } break;
++ ./
++
++ struct_declarator ::= IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ;
++ /.
++ case $rule_number: {
++ sym(1).field = makeAstNode<StructTypeAST::Field>
++ (string(1), makeAstNode<ArrayTypeAST>((TypeAST *)0));
++ } break;
++ ./
++
++ struct_declarator ::= IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ;
++ /.
++ case $rule_number: {
++ sym(1).field = makeAstNode<StructTypeAST::Field>
++ (string(1), makeAstNode<ArrayTypeAST>((TypeAST *)0, expression(3)));
++ } break;
++ ./
++
++ initializer ::= assignment_expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ declaration_statement ::= declaration ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<DeclarationStatementAST>(sym(1).declaration);
++ } break;
++ ./
++
++ statement ::= compound_statement ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ statement ::= simple_statement ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ simple_statement ::= declaration_statement ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ simple_statement ::= expression_statement ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ simple_statement ::= selection_statement ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ simple_statement ::= switch_statement ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ simple_statement ::= case_label ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ simple_statement ::= iteration_statement ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ simple_statement ::= jump_statement ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ compound_statement ::= LEFT_BRACE RIGHT_BRACE ;
++ /.
++ case $rule_number: {
++ CompoundStatementAST *stmt = makeAstNode<CompoundStatementAST>();
++ stmt->start = tokenAt(location(1)).begin();
++ stmt->end = tokenAt(location(2)).end();
++ ast(1) = stmt;
++ } break;
++ ./
++
++ compound_statement ::= LEFT_BRACE statement_list RIGHT_BRACE ;
++ /.
++ case $rule_number: {
++ CompoundStatementAST *stmt = makeAstNode<CompoundStatementAST>(sym(2).statement_list);
++ stmt->start = tokenAt(location(1)).begin();
++ stmt->end = tokenAt(location(3)).end();
++ ast(1) = stmt;
++ } break;
++ ./
++
++ statement_no_new_scope ::= compound_statement_no_new_scope ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ statement_no_new_scope ::= simple_statement ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ compound_statement_no_new_scope ::= LEFT_BRACE RIGHT_BRACE ;
++ /.
++ case $rule_number: {
++ CompoundStatementAST *stmt = makeAstNode<CompoundStatementAST>();
++ stmt->start = tokenAt(location(1)).begin();
++ stmt->end = tokenAt(location(2)).end();
++ ast(1) = stmt;
++ } break;
++ ./
++
++ compound_statement_no_new_scope ::= LEFT_BRACE statement_list RIGHT_BRACE ;
++ /.
++ case $rule_number: {
++ CompoundStatementAST *stmt = makeAstNode<CompoundStatementAST>(sym(2).statement_list);
++ stmt->start = tokenAt(location(1)).begin();
++ stmt->end = tokenAt(location(3)).end();
++ ast(1) = stmt;
++ } break;
++ ./
++
++ statement_list ::= statement ;
++ /.
++ case $rule_number: {
++ sym(1).statement_list = makeAstNode< List<StatementAST *> >(sym(1).statement);
++ } break;
++ ./
++
++ statement_list ::= statement_list statement ;
++ /.
++ case $rule_number: {
++ sym(1).statement_list = makeAstNode< List<StatementAST *> >(sym(1).statement_list, sym(2).statement);
++ } break;
++ ./
++
++ expression_statement ::= SEMICOLON ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<CompoundStatementAST>(); // Empty statement
++ } break;
++ ./
++
++ expression_statement ::= expression SEMICOLON ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<ExpressionStatementAST>(expression(1));
++ } break;
++ ./
++
++ selection_statement ::= IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<IfStatementAST>(expression(3), sym(5).ifstmt.thenClause, sym(5).ifstmt.elseClause);
++ } break;
++ ./
++
++ selection_rest_statement ::= statement ELSE statement ;
++ /.
++ case $rule_number: {
++ sym(1).ifstmt.thenClause = statement(1);
++ sym(1).ifstmt.elseClause = statement(3);
++ } break;
++ ./
++
++ selection_rest_statement ::= statement ;
++ /.
++ case $rule_number: {
++ sym(1).ifstmt.thenClause = statement(1);
++ sym(1).ifstmt.elseClause = 0;
++ } break;
++ ./
++
++ condition ::= expression ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ condition ::= fully_specified_type IDENTIFIER EQUAL initializer ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<DeclarationExpressionAST>
++ (type(1), string(2), expression(4));
++ } break;
++ ./
++
++ switch_statement ::= SWITCH LEFT_PAREN expression RIGHT_PAREN LEFT_BRACE switch_statement_list RIGHT_BRACE ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<SwitchStatementAST>(expression(3), statement(6));
++ } break;
++ ./
++
++ switch_statement_list ::= empty ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<CompoundStatementAST>();
++ } break;
++ ./
++
++ switch_statement_list ::= statement_list ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<CompoundStatementAST>(sym(1).statement_list);
++ } break;
++ ./
++
++ case_label ::= CASE expression COLON ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<CaseLabelStatementAST>(expression(2));
++ } break;
++ ./
++
++ case_label ::= DEFAULT COLON ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<CaseLabelStatementAST>();
++ } break;
++ ./
++
++ iteration_statement ::= WHILE LEFT_PAREN condition RIGHT_PAREN statement_no_new_scope ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<WhileStatementAST>(expression(3), statement(5));
++ } break;
++ ./
++
++ iteration_statement ::= DO statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<DoStatementAST>(statement(2), expression(5));
++ } break;
++ ./
++
++ iteration_statement ::= FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<ForStatementAST>(statement(3), sym(4).forstmt.condition, sym(4).forstmt.increment, statement(6));
++ } break;
++ ./
++
++ for_init_statement ::= expression_statement ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ for_init_statement ::= declaration_statement ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ conditionopt ::= empty ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ conditionopt ::= condition ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ for_rest_statement ::= conditionopt SEMICOLON ;
++ /.
++ case $rule_number: {
++ sym(1).forstmt.condition = expression(1);
++ sym(1).forstmt.increment = 0;
++ } break;
++ ./
++
++ for_rest_statement ::= conditionopt SEMICOLON expression ;
++ /.
++ case $rule_number: {
++ sym(1).forstmt.condition = expression(1);
++ sym(1).forstmt.increment = expression(3);
++ } break;
++ ./
++
++ jump_statement ::= CONTINUE SEMICOLON ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<JumpStatementAST>(AST::Kind_Continue);
++ } break;
++ ./
++
++ jump_statement ::= BREAK SEMICOLON ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<JumpStatementAST>(AST::Kind_Break);
++ } break;
++ ./
++
++ jump_statement ::= RETURN SEMICOLON ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<ReturnStatementAST>();
++ } break;
++ ./
++
++ jump_statement ::= RETURN expression SEMICOLON ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<ReturnStatementAST>(expression(2));
++ } break;
++ ./
++
++ jump_statement ::= DISCARD SEMICOLON ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<JumpStatementAST>(AST::Kind_Discard);
++ } break;
++ ./
++
++ translation_unit ::= external_declaration_list ;
++ /.
++ case $rule_number: {
++ ast(1) = makeAstNode<TranslationUnitAST>(sym(1).declaration_list);
++ } break;
++ ./
++
++ external_declaration_list ::= external_declaration ;
++ /.
++ case $rule_number: {
++ if (sym(1).declaration) {
++ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
++ (sym(1).declaration);
++ } else {
++ sym(1).declaration_list = 0;
++ }
++ } break;
++ ./
++
++ external_declaration_list ::= external_declaration_list external_declaration ;
++ /.
++ case $rule_number: {
++ if (sym(1).declaration_list && sym(2).declaration) {
++ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
++ (sym(1).declaration_list, sym(2).declaration);
++ } else if (!sym(1).declaration_list) {
++ if (sym(2).declaration) {
++ sym(1).declaration_list = makeAstNode< List<DeclarationAST *> >
++ (sym(2).declaration);
++ } else {
++ sym(1).declaration_list = 0;
++ }
++ }
++ } break;
++ ./
++
++ external_declaration ::= function_definition ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ external_declaration ::= declaration ;
++ /.
++ case $rule_number: {
++ // nothing to do.
++ } break;
++ ./
++
++ external_declaration ::= SEMICOLON ;
++ /.
++ case $rule_number: {
++ ast(1) = 0;
++ } break;
++ ./
++
++ function_definition ::= function_prototype compound_statement_no_new_scope ;
++ /.
++ case $rule_number: {
++ function(1)->body = statement(2);
++ } break;
++ ./
++
++ empty ::= ;
++ /.
++ case $rule_number: {
++ ast(1) = 0;
++ } break;
++ ./
++
++
++ toplevel ::= FEED_GLSL translation_unit ;
++ /.
++ case $rule_number: {
++ ast(1) = ast(2);
++ } break;
++ ./
++
++ toplevel ::= FEED_EXPRESSION expression ;
++ /.
++ case $rule_number: {
++ ast(1) = ast(2);
++ } break;
++ ./
++
++ /.
++ } // end switch
++ } // end Parser::reduce()
++ ./