From 1f8f99df28c49b66a48c357f4565e9779de25394 Mon Sep 17 00:00:00 2001
From: Rhys Weatherley <rhys.weatherley@nokia.com>
Date: Fri, 12 Nov 2010 10:23:46 +1000
Subject: [PATCH] Build AST nodes from within the parser.

---
 src/libs/glsl/glsl.g           |  465 +++++++-------
 src/libs/glsl/glslast.cpp      |   24 +-
 src/libs/glsl/glslast.h        |  138 ++++-
 src/libs/glsl/glslastvisitor.h |    6 +
 src/libs/glsl/glsllexer.cpp    |    3 +
 src/libs/glsl/glslparser.cpp   | 1067 ++++++++++++++++----------------
 src/libs/glsl/glslparser.h     |   30 +
 7 files changed, 966 insertions(+), 767 deletions(-)

diff --git a/src/libs/glsl/glsl.g b/src/libs/glsl/glsl.g
index 9472eb4a10e..416ca7c1baf 100644
--- a/src/libs/glsl/glsl.g
+++ b/src/libs/glsl/glsl.g
@@ -260,7 +260,27 @@ public:
         List<Declaration *> *declaration_list;
         Expression *expression;
         List<Expression *> *expression_list;
+        Statement *statement;
+        List<Statement *> *statement_list;
+        Type *type;
+        StructType::Field *field;
+        List<StructType::Field *> *field_list;
         TranslationUnit *translation_unit;
+        FunctionIdentifier *function_identifier;
+        AST::Kind kind;
+        Type::Precision precision;
+        struct {
+            Statement *thenClause;
+            Statement *elseClause;
+        } ifstmt;
+        struct {
+            Expression *condition;
+            Expression *increment;
+        } forstmt;
+        struct {
+            FunctionIdentifier *id;
+            List<Expression *> *arguments;
+        } function;
         // ### ast nodes...
     };
 
@@ -274,6 +294,9 @@ private:
     Value &sym(int n) { return _symStack[_tos + n - 1]; }
     AST *&ast(int n) { return _symStack[_tos + n - 1].ast; }
     const std::string *&string(int n) { return _symStack[_tos + n - 1].string; }
+    Expression *&expression(int n) { return _symStack[_tos + n - 1].expression; }
+    Statement *&statement(int n) { return _symStack[_tos + n - 1].statement; }
+    Type *&type(int n) { return _symStack[_tos + n - 1].type; }
 
     inline int consumeToken() { return _index++; }
     inline const Token &tokenAt(int index) const { return _tokens.at(index); }
@@ -320,6 +343,13 @@ private:
         return node;
     }
 
+    Type *makeBasicType(int token, BasicType::Category category)
+    {
+        Type *type = new (_engine->pool()) BasicType(token, spell[token], category);
+        type->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+        return type;
+    }
+
 private:
     Engine *_engine;
     int _tos;
@@ -507,28 +537,28 @@ switch(ruleno) {
 variable_identifier ::= IDENTIFIER ;
 /.
 case $rule_number: {
-    ast(1) = makeAstNode<IdentifierExpression>(sym(1).string);
+    ast(1) = makeAstNode<IdentifierExpression>(string(1));
 }   break;
 ./
 
 primary_expression ::= NUMBER ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<LiteralExpression>(string(1));
 }   break;
 ./
 
 primary_expression ::= TRUE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<LiteralExpression>(_engine->identifier("true", 4));
 }   break;
 ./
 
 primary_expression ::= FALSE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<LiteralExpression>(_engine->identifier("false", 5));
 }   break;
 ./
 
@@ -556,7 +586,7 @@ case $rule_number: {
 postfix_expression ::= postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_ArrayAccess, expression(1), expression(3));
 }   break;
 ./
 
@@ -570,21 +600,21 @@ case $rule_number: {
 postfix_expression ::= postfix_expression DOT IDENTIFIER ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<MemberAccessExpression>(expression(1), string(3));
 }   break;
 ./
 
 postfix_expression ::= postfix_expression INC_OP ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<UnaryExpression>(AST::Kind_PostIncrement, expression(1));
 }   break;
 ./
 
 postfix_expression ::= postfix_expression DEC_OP ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<UnaryExpression>(AST::Kind_PostDecrement, expression(1));
 }   break;
 ./
 
@@ -605,77 +635,85 @@ case $rule_number: {
 function_call_or_method ::= function_call_generic ;
 /.
 case $rule_number: {
-    // nothing to do.
+    ast(1) = makeAstNode<FunctionCallExpression>
+        (sym(1).function.id, sym(1).function.arguments);
 }   break;
 ./
 
 function_call_or_method ::= postfix_expression DOT function_call_generic ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<FunctionCallExpression>
+        (expression(1), sym(3).function.id, sym(3).function.arguments);
 }   break;
 ./
 
 function_call_generic ::= function_call_header_with_parameters RIGHT_PAREN ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 function_call_generic ::= function_call_header_no_parameters RIGHT_PAREN ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 function_call_header_no_parameters ::= function_call_header VOID ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    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: {
-    // ast(1) = new ...AST(...);
+    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: {
-    // ast(1) = new ...AST(...);
+    sym(1).function.id = sym(1).function_identifier;
+    sym(1).function.arguments =
+        makeAstNode< List<Expression *> >(expression(2));
 }   break;
 ./
 
 function_call_header_with_parameters ::= function_call_header_with_parameters COMMA assignment_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).function.arguments =
+        makeAstNode< List<Expression *> >
+            (sym(1).function.arguments, expression(3));
 }   break;
 ./
 
 function_call_header ::= function_identifier LEFT_PAREN ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 function_identifier ::= type_specifier ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<FunctionIdentifier>(type(1));
 }   break;
 ./
 
 function_identifier ::= IDENTIFIER ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<FunctionIdentifier>(string(1));
 }   break;
 ./
 
@@ -689,49 +727,49 @@ case $rule_number: {
 unary_expression ::= INC_OP unary_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<UnaryExpression>(AST::Kind_PreIncrement, expression(1));
 }   break;
 ./
 
 unary_expression ::= DEC_OP unary_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<UnaryExpression>(AST::Kind_PreDecrement, expression(1));
 }   break;
 ./
 
 unary_expression ::= unary_operator unary_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<UnaryExpression>(sym(1).kind, expression(2));
 }   break;
 ./
 
 unary_operator ::= PLUS ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_UnaryPlus;
 }   break;
 ./
 
 unary_operator ::= DASH ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_UnaryMinus;
 }   break;
 ./
 
 unary_operator ::= BANG ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_LogicalNot;
 }   break;
 ./
 
 unary_operator ::= TILDE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_BitwiseNot;
 }   break;
 ./
 
@@ -745,21 +783,21 @@ case $rule_number: {
 multiplicative_expression ::= multiplicative_expression STAR unary_expression ;
 /.
 case $rule_number: {
-    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Multiply, sym(1).expression, sym(3).expression);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Multiply, expression(1), expression(3));
 }   break;
 ./
 
 multiplicative_expression ::= multiplicative_expression SLASH unary_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Divide, expression(1), expression(3));
 }   break;
 ./
 
 multiplicative_expression ::= multiplicative_expression PERCENT unary_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Modulus, expression(1), expression(3));
 }   break;
 ./
 
@@ -773,14 +811,14 @@ case $rule_number: {
 additive_expression ::= additive_expression PLUS multiplicative_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Plus, expression(1), expression(3));
 }   break;
 ./
 
 additive_expression ::= additive_expression DASH multiplicative_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Minus, expression(1), expression(3));
 }   break;
 ./
 
@@ -794,14 +832,14 @@ case $rule_number: {
 shift_expression ::= shift_expression LEFT_OP additive_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_ShiftLeft, expression(1), expression(3));
 }   break;
 ./
 
 shift_expression ::= shift_expression RIGHT_OP additive_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_ShiftRight, expression(1), expression(3));
 }   break;
 ./
 
@@ -815,28 +853,28 @@ case $rule_number: {
 relational_expression ::= relational_expression LEFT_ANGLE shift_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_LessThan, expression(1), expression(3));
 }   break;
 ./
 
 relational_expression ::= relational_expression RIGHT_ANGLE shift_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_GreaterThan, expression(1), expression(3));
 }   break;
 ./
 
 relational_expression ::= relational_expression LE_OP shift_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_LessEqual, expression(1), expression(3));
 }   break;
 ./
 
 relational_expression ::= relational_expression GE_OP shift_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_GreaterEqual, expression(1), expression(3));
 }   break;
 ./
 
@@ -850,14 +888,14 @@ case $rule_number: {
 equality_expression ::= equality_expression EQ_OP relational_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Equal, expression(1), expression(3));
 }   break;
 ./
 
 equality_expression ::= equality_expression NE_OP relational_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_NotEqual, expression(1), expression(3));
 }   break;
 ./
 
@@ -871,7 +909,7 @@ case $rule_number: {
 and_expression ::= and_expression AMPERSAND equality_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_BitwiseAnd, expression(1), expression(3));
 }   break;
 ./
 
@@ -885,7 +923,7 @@ case $rule_number: {
 exclusive_or_expression ::= exclusive_or_expression CARET and_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_BitwiseOr, expression(1), expression(3));
 }   break;
 ./
 
@@ -899,7 +937,7 @@ case $rule_number: {
 inclusive_or_expression ::= inclusive_or_expression VERTICAL_BAR exclusive_or_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_BitwiseXor, expression(1), expression(3));
 }   break;
 ./
 
@@ -913,7 +951,7 @@ case $rule_number: {
 logical_and_expression ::= logical_and_expression AND_OP inclusive_or_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_LogicalAnd, expression(1), expression(3));
 }   break;
 ./
 
@@ -927,7 +965,7 @@ case $rule_number: {
 logical_xor_expression ::= logical_xor_expression XOR_OP logical_and_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_LogicalXor, expression(1), expression(3));
 }   break;
 ./
 
@@ -941,7 +979,7 @@ case $rule_number: {
 logical_or_expression ::= logical_or_expression OR_OP logical_xor_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_LogicalOr, expression(1), expression(3));
 }   break;
 ./
 
@@ -955,7 +993,7 @@ case $rule_number: {
 conditional_expression ::= logical_or_expression QUESTION expression COLON assignment_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<TernaryExpression>(AST::Kind_Conditional, expression(1), expression(3), expression(5));
 }   break;
 ./
 
@@ -969,84 +1007,84 @@ case $rule_number: {
 assignment_expression ::= unary_expression assignment_operator assignment_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<AssignmentExpression>(sym(2).kind, expression(1), expression(3));
 }   break;
 ./
 
 assignment_operator ::= EQUAL ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_Assign;
 }   break;
 ./
 
 assignment_operator ::= MUL_ASSIGN ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignMultiply;
 }   break;
 ./
 
 assignment_operator ::= DIV_ASSIGN ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignDivide;
 }   break;
 ./
 
 assignment_operator ::= MOD_ASSIGN ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignModulus;
 }   break;
 ./
 
 assignment_operator ::= ADD_ASSIGN ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignPlus;
 }   break;
 ./
 
 assignment_operator ::= SUB_ASSIGN ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignMinus;
 }   break;
 ./
 
 assignment_operator ::= LEFT_ASSIGN ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignShiftLeft;
 }   break;
 ./
 
 assignment_operator ::= RIGHT_ASSIGN ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignShiftRight;
 }   break;
 ./
 
 assignment_operator ::= AND_ASSIGN ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignAnd;
 }   break;
 ./
 
 assignment_operator ::= XOR_ASSIGN ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignXor;
 }   break;
 ./
 
 assignment_operator ::= OR_ASSIGN ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignOr;
 }   break;
 ./
 
@@ -1060,7 +1098,7 @@ case $rule_number: {
 expression ::= expression COMMA assignment_expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Comma, expression(1), expression(3));
 }   break;
 ./
 
@@ -1088,7 +1126,7 @@ case $rule_number: {
 declaration ::= PRECISION precision_qualifier type_specifier_no_prec SEMICOLON ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<PrecisionDeclaration>(sym(2).precision, type(3));
 }   break;
 ./
 
@@ -1585,742 +1623,749 @@ case $rule_number: {
 type_specifier ::= type_specifier_no_prec ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 type_specifier ::= precision_qualifier type_specifier_no_prec ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    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: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 type_specifier_no_prec ::= type_specifier_nonarray LEFT_BRACKET RIGHT_BRACKET ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<ArrayType>(type(1));
 }   break;
 ./
 
 type_specifier_no_prec ::= type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<ArrayType>(type(1), expression(3));
 }   break;
 ./
 
 type_specifier_nonarray ::= VOID ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_VOID, Type::Void);
 }   break;
 ./
 
 type_specifier_nonarray ::= FLOAT ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_FLOAT, Type::Primitive);
 }   break;
 ./
 
 type_specifier_nonarray ::= DOUBLE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DOUBLE, Type::Primitive);
 }   break;
 ./
 
 type_specifier_nonarray ::= INT ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_INT, Type::Primitive);
 }   break;
 ./
 
 type_specifier_nonarray ::= UINT ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_UINT, Type::Primitive);
 }   break;
 ./
 
 type_specifier_nonarray ::= BOOL ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_BOOL, Type::Primitive);
 }   break;
 ./
 
 type_specifier_nonarray ::= VEC2 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_VEC2, Type::Vector2);
 }   break;
 ./
 
 type_specifier_nonarray ::= VEC3 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_VEC3, Type::Vector3);
 }   break;
 ./
 
 type_specifier_nonarray ::= VEC4 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_VEC4, Type::Vector4);
 }   break;
 ./
 
 type_specifier_nonarray ::= DVEC2 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DVEC2, Type::Vector2);
 }   break;
 ./
 
 type_specifier_nonarray ::= DVEC3 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DVEC3, Type::Vector3);
 }   break;
 ./
 
 type_specifier_nonarray ::= DVEC4 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DVEC4, Type::Vector4);
 }   break;
 ./
 
 type_specifier_nonarray ::= BVEC2 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_BVEC2, Type::Vector2);
 }   break;
 ./
 
 type_specifier_nonarray ::= BVEC3 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_BVEC3, Type::Vector3);
 }   break;
 ./
 
 type_specifier_nonarray ::= BVEC4 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_BVEC4, Type::Vector4);
 }   break;
 ./
 
 type_specifier_nonarray ::= IVEC2 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_IVEC2, Type::Vector2);
 }   break;
 ./
 
 type_specifier_nonarray ::= IVEC3 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_IVEC3, Type::Vector3);
 }   break;
 ./
 
 type_specifier_nonarray ::= IVEC4 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_IVEC4, Type::Vector4);
 }   break;
 ./
 
 type_specifier_nonarray ::= UVEC2 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_UVEC2, Type::Vector2);
 }   break;
 ./
 
 type_specifier_nonarray ::= UVEC3 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_UVEC3, Type::Vector3);
 }   break;
 ./
 
 type_specifier_nonarray ::= UVEC4 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_UVEC4, Type::Vector4);
 }   break;
 ./
 
 type_specifier_nonarray ::= MAT2 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT2, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= MAT3 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT3, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= MAT4 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT4, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= MAT2X2 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT2X2, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= MAT2X3 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT2X3, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= MAT2X4 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT2X4, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= MAT3X2 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT3X2, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= MAT3X3 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT3X3, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= MAT3X4 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT3X4, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= MAT4X2 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT4X2, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= MAT4X3 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT4X3, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= MAT4X4 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT4X4, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= DMAT2 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT2, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= DMAT3 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT3, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= DMAT4 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT4, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= DMAT2X2 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT2X2, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= DMAT2X3 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT2X3, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= DMAT2X4 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT2X4, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= DMAT3X2 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT3X2, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= DMAT3X3 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT3X3, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= DMAT3X4 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT3X4, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= DMAT4X2 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT4X2, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= DMAT4X3 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT4X3, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= DMAT4X4 ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT4X4, Type::Matrix);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLER1D ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER1D, Type::Sampler1D);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLER2D ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2D, Type::Sampler2D);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLER3D ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER3D, Type::Sampler3D);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLERCUBE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLERCUBE, Type::SamplerCube);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLER1DSHADOW ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER1DSHADOW, Type::Sampler1DShadow);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLER2DSHADOW ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DSHADOW, Type::Sampler2DShadow);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLERCUBESHADOW ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLERCUBESHADOW, Type::SamplerCubeShadow);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLER1DARRAY ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER1DARRAY, Type::Sampler1DArray);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLER2DARRAY ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DARRAY, Type::Sampler2DArray);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLER1DARRAYSHADOW ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER1DARRAYSHADOW, Type::Sampler1DArrayShadow);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLER2DARRAYSHADOW ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DARRAYSHADOW, Type::Sampler2DArrayShadow);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLERCUBEARRAY ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLERCUBEARRAY, Type::SamplerCubeShadow);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLERCUBEARRAYSHADOW ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLERCUBEARRAYSHADOW, Type::SamplerCubeArrayShadow);
 }   break;
 ./
 
 type_specifier_nonarray ::= ISAMPLER1D ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER1D, Type::Sampler1D);
 }   break;
 ./
 
 type_specifier_nonarray ::= ISAMPLER2D ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER2D, Type::Sampler2D);
 }   break;
 ./
 
 type_specifier_nonarray ::= ISAMPLER3D ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER3D, Type::Sampler3D);
 }   break;
 ./
 
 type_specifier_nonarray ::= ISAMPLERCUBE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLERCUBE, Type::SamplerCube);
 }   break;
 ./
 
 type_specifier_nonarray ::= ISAMPLER1DARRAY ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER1DARRAY, Type::Sampler1DArray);
 }   break;
 ./
 
 type_specifier_nonarray ::= ISAMPLER2DARRAY ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER2DARRAY, Type::Sampler2DArray);
 }   break;
 ./
 
 type_specifier_nonarray ::= ISAMPLERCUBEARRAY ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLERCUBEARRAY, Type::SamplerCubeArray);
 }   break;
 ./
 
 type_specifier_nonarray ::= USAMPLER1D ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER1D, Type::Sampler1D);
 }   break;
 ./
 
 type_specifier_nonarray ::= USAMPLER2D ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER2D, Type::Sampler2D);
 }   break;
 ./
 
 type_specifier_nonarray ::= USAMPLER3D ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER3D, Type::Sampler3D);
 }   break;
 ./
 
 type_specifier_nonarray ::= USAMPLERCUBE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLERCUBE, Type::SamplerCube);
 }   break;
 ./
 
 type_specifier_nonarray ::= USAMPLER1DARRAY ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER1DARRAY, Type::Sampler1DArray);
 }   break;
 ./
 
 type_specifier_nonarray ::= USAMPLER2DARRAY ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER2DARRAY, Type::Sampler2DArray);
 }   break;
 ./
 
 type_specifier_nonarray ::= USAMPLERCUBEARRAY ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLERCUBEARRAY, Type::SamplerCubeArray);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLER2DRECT ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DRECT, Type::Sampler2DRect);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLER2DRECTSHADOW ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DRECTSHADOW, Type::Sampler2DRectShadow);
 }   break;
 ./
 
 type_specifier_nonarray ::= ISAMPLER2DRECT ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER2DRECT, Type::Sampler2DRect);
 }   break;
 ./
 
 type_specifier_nonarray ::= USAMPLER2DRECT ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER2DRECT, Type::Sampler2DRect);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLERBUFFER ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLERBUFFER, Type::SamplerBuffer);
 }   break;
 ./
 
 type_specifier_nonarray ::= ISAMPLERBUFFER ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLERBUFFER, Type::SamplerBuffer);
 }   break;
 ./
 
 type_specifier_nonarray ::= USAMPLERBUFFER ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLERBUFFER, Type::SamplerBuffer);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLER2DMS ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DMS, Type::Sampler2DMS);
 }   break;
 ./
 
 type_specifier_nonarray ::= ISAMPLER2DMS ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER2DMS, Type::Sampler2DMS);
 }   break;
 ./
 
 type_specifier_nonarray ::= USAMPLER2DMS ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER2DMS, Type::Sampler2DMS);
 }   break;
 ./
 
 type_specifier_nonarray ::= SAMPLER2DMSARRAY ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DMSARRAY, Type::Sampler2DMSArray);
 }   break;
 ./
 
 type_specifier_nonarray ::= ISAMPLER2DMSARRAY ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER2DMSARRAY, Type::Sampler2DMSArray);
 }   break;
 ./
 
 type_specifier_nonarray ::= USAMPLER2DMSARRAY ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER2DMSARRAY, Type::Sampler2DMSArray);
 }   break;
 ./
 
 type_specifier_nonarray ::= struct_specifier ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 type_specifier_nonarray ::= TYPE_NAME ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<NamedType>(string(1));
 }   break;
 ./
 
 precision_qualifier ::= HIGHP ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).precision = Type::Highp;
 }   break;
 ./
 
 precision_qualifier ::= MEDIUMP ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).precision = Type::Mediump;
 }   break;
 ./
 
 precision_qualifier ::= LOWP ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).precision = Type::Lowp;
 }   break;
 ./
 
 struct_specifier ::= STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<StructType>(string(2), sym(4).field_list);
 }   break;
 ./
 
 struct_specifier ::= STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<StructType>(sym(3).field_list);
 }   break;
 ./
 
 struct_declaration_list ::= struct_declaration ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 struct_declaration_list ::= struct_declaration_list struct_declaration ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    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: {
-    // ast(1) = new ...AST(...);
+    sym(1).field_list = StructType::fixInnerTypes(type(1), sym(2).field_list);
 }   break;
 ./
 
 struct_declaration ::= type_qualifier type_specifier struct_declarator_list SEMICOLON ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // TODO: type qualifier
+    sym(1).field_list = StructType::fixInnerTypes(type(2), sym(3).field_list);
 }   break;
 ./
 
 struct_declarator_list ::= struct_declarator ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
+    sym(1).field_list = makeAstNode< List<StructType::Field *> >(sym(1).field);
 }   break;
 ./
 
 struct_declarator_list ::= struct_declarator_list COMMA struct_declarator ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).field_list = makeAstNode< List<StructType::Field *> >(sym(1).field_list, sym(3).field);
 }   break;
 ./
 
 struct_declarator ::= IDENTIFIER ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).field = makeAstNode<StructType::Field>(string(1));
 }   break;
 ./
 
 struct_declarator ::= IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).field = makeAstNode<StructType::Field>
+        (string(1), makeAstNode<ArrayType>((Type *)0));
 }   break;
 ./
 
 struct_declarator ::= IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).field = makeAstNode<StructType::Field>
+        (string(1), makeAstNode<ArrayType>((Type *)0, expression(3)));
 }   break;
 ./
 
@@ -2341,161 +2386,163 @@ case $rule_number: {
 statement ::= compound_statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 statement ::= simple_statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 simple_statement ::= declaration_statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 simple_statement ::= expression_statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 simple_statement ::= selection_statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 simple_statement ::= switch_statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 simple_statement ::= case_label ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 simple_statement ::= iteration_statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 simple_statement ::= jump_statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 compound_statement ::= LEFT_BRACE RIGHT_BRACE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>();
 }   break;
 ./
 
 compound_statement ::= LEFT_BRACE statement_list RIGHT_BRACE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>(sym(2).statement_list);
 }   break;
 ./
 
 statement_no_new_scope ::= compound_statement_no_new_scope ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 statement_no_new_scope ::= simple_statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 compound_statement_no_new_scope ::= LEFT_BRACE RIGHT_BRACE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>();
 }   break;
 ./
 
 compound_statement_no_new_scope ::= LEFT_BRACE statement_list RIGHT_BRACE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>(sym(2).statement_list);
 }   break;
 ./
 
 statement_list ::= statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).statement_list = makeAstNode< List<Statement *> >(sym(1).statement);
 }   break;
 ./
 
 statement_list ::= statement_list statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).statement_list = makeAstNode< List<Statement *> >(sym(1).statement_list, sym(2).statement);
 }   break;
 ./
 
 expression_statement ::= SEMICOLON ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>();  // Empty statement
 }   break;
 ./
 
 expression_statement ::= expression SEMICOLON ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<ExpressionStatement>(expression(1));
 }   break;
 ./
 
 selection_statement ::= IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<IfStatement>(expression(3), sym(5).ifstmt.thenClause, sym(5).ifstmt.elseClause);
 }   break;
 ./
 
 selection_rest_statement ::= statement ELSE statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).ifstmt.thenClause = statement(1);
+    sym(1).ifstmt.elseClause = statement(3);
 }   break;
 ./
 
 selection_rest_statement ::= statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).ifstmt.thenClause = statement(1);
+    sym(1).ifstmt.elseClause = 0;
 }   break;
 ./
 
 condition ::= expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
@@ -2509,133 +2556,135 @@ case $rule_number: {
 switch_statement ::= SWITCH LEFT_PAREN expression RIGHT_PAREN LEFT_BRACE switch_statement_list RIGHT_BRACE ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<SwitchStatement>(expression(3), statement(6));
 }   break;
 ./
 
 switch_statement_list ::= empty ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>();
 }   break;
 ./
 
 switch_statement_list ::= statement_list ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>(sym(1).statement_list);
 }   break;
 ./
 
 case_label ::= CASE expression COLON ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CaseLabelStatement>(expression(2));
 }   break;
 ./
 
 case_label ::= DEFAULT COLON ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CaseLabelStatement>();
 }   break;
 ./
 
 iteration_statement ::= WHILE LEFT_PAREN condition RIGHT_PAREN statement_no_new_scope ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<WhileStatement>(expression(3), statement(5));
 }   break;
 ./
 
 iteration_statement ::= DO statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<DoStatement>(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) = new ...AST(...);
+    ast(1) = makeAstNode<ForStatement>(statement(3), sym(4).forstmt.condition, sym(4).forstmt.increment, statement(6));
 }   break;
 ./
 
 for_init_statement ::= expression_statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 for_init_statement ::= declaration_statement ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 conditionopt ::= empty ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 conditionopt ::= condition ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 ./
 
 for_rest_statement ::= conditionopt SEMICOLON ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).forstmt.condition = expression(1);
+    sym(1).forstmt.increment = 0;
 }   break;
 ./
 
 for_rest_statement ::= conditionopt SEMICOLON expression ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    sym(1).forstmt.condition = expression(1);
+    sym(1).forstmt.increment = expression(3);
 }   break;
 ./
 
 jump_statement ::= CONTINUE SEMICOLON ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<JumpStatement>(AST::Kind_Continue);
 }   break;
 ./
 
 jump_statement ::= BREAK SEMICOLON ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<JumpStatement>(AST::Kind_Break);
 }   break;
 ./
 
 jump_statement ::= RETURN SEMICOLON ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<ReturnStatement>();
 }   break;
 ./
 
 jump_statement ::= RETURN expression SEMICOLON ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<ReturnStatement>(expression(2));
 }   break;
 ./
 
 jump_statement ::= DISCARD SEMICOLON ;
 /.
 case $rule_number: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<JumpStatement>(AST::Kind_Discard);
 }   break;
 ./
 
diff --git a/src/libs/glsl/glslast.cpp b/src/libs/glsl/glslast.cpp
index b6ab81930a6..b627edefd16 100644
--- a/src/libs/glsl/glslast.cpp
+++ b/src/libs/glsl/glslast.cpp
@@ -111,11 +111,19 @@ void FunctionCallExpression::accept0(Visitor *visitor)
 {
     if (visitor->visit(this)) {
         accept(expr, visitor);
+        accept(id, visitor);
         accept(arguments, visitor);
     }
     visitor->endVisit(this);
 }
 
+void FunctionIdentifier::accept0(Visitor *visitor)
+{
+    if (visitor->visit(this))
+        accept(type, visitor);
+    visitor->endVisit(this);
+}
+
 void ExpressionStatement::accept0(Visitor *visitor)
 {
     if (visitor->visit(this))
@@ -198,8 +206,8 @@ void CaseLabelStatement::accept0(Visitor *visitor)
     visitor->endVisit(this);
 }
 
-BasicType::BasicType(int _token)
-    : Type(Kind_BasicType), token(_token)
+BasicType::BasicType(int _token, const char *_name, Category _category)
+    : Type(Kind_BasicType), token(_token), name(_name), categ(_category)
 {
     switch (token) {
     case GLSLParserTable::T_VOID:
@@ -314,14 +322,22 @@ void StructType::Field::setInnerType(Type *innerType)
     *parent = innerType;
 }
 
-void StructType::fixInnerTypes(Type *innerType, List<Field *> *fields)
+List<StructType::Field *> *StructType::fixInnerTypes(Type *innerType, List<Field *> *fields)
 {
     if (!fields)
-        return;
+        return fields;
     List<Field *> *head = fields->next;
     List<Field *> *current = head;
     do {
         current->value->setInnerType(innerType);
         current = current->next;
     } while (current && current != head);
+    return fields;
+}
+
+void PrecisionDeclaration::accept0(Visitor *visitor)
+{
+    if (visitor->visit(this))
+        accept(type, visitor);
+    visitor->endVisit(this);
 }
diff --git a/src/libs/glsl/glslast.h b/src/libs/glsl/glslast.h
index 3fc5a961578..482ae88463a 100644
--- a/src/libs/glsl/glslast.h
+++ b/src/libs/glsl/glslast.h
@@ -37,7 +37,6 @@ namespace GLSL {
 
 class AST;
 class TranslationUnit;
-class Declaration;
 class Expression;
 class IdentifierExpression;
 class LiteralExpression;
@@ -47,6 +46,7 @@ class TernaryExpression;
 class AssignmentExpression;
 class MemberAccessExpression;
 class FunctionCallExpression;
+class FunctionIdentifier;
 class Statement;
 class ExpressionStatement;
 class CompoundStatement;
@@ -63,6 +63,8 @@ class BasicType;
 class NamedType;
 class ArrayType;
 class StructType;
+class Declaration;
+class PrecisionDeclaration;
 class Visitor;
 
 template <typename T>
@@ -145,6 +147,7 @@ public:
         Kind_GreaterEqual,
         Kind_LogicalAnd,
         Kind_LogicalOr,
+        Kind_LogicalXor,
         Kind_BitwiseAnd,
         Kind_BitwiseOr,
         Kind_BitwiseXor,
@@ -156,6 +159,7 @@ public:
         Kind_MemberAccess,
         Kind_FunctionCall,
         Kind_MemberFunctionCall,
+        Kind_FunctionIdentifier,
 
         // Assignment expressions
         Kind_Assign,
@@ -186,8 +190,6 @@ public:
         Kind_CaseLabel,
         Kind_DefaultLabel,
 
-        // Declarations
-
         // Types
         Kind_BasicType,
         Kind_NamedType,
@@ -195,13 +197,14 @@ public:
         Kind_OpenArrayType,
         Kind_StructType,
         Kind_AnonymousStructType,
-        Kind_StructField
+        Kind_StructField,
+
+        // Declarations
+        Kind_PrecisionDeclaration
     };
 
     virtual TranslationUnit *asTranslationUnit() { return 0; }
 
-    virtual Declaration *asDeclaration() { return 0; }
-
     virtual Expression *asExpression() { return 0; }
     virtual IdentifierExpression *asIdentifierExpression() { return 0; }
     virtual LiteralExpression *asLiteralExpression() { return 0; }
@@ -211,6 +214,7 @@ public:
     virtual AssignmentExpression *asAssignmentExpression() { return 0; }
     virtual MemberAccessExpression *asMemberAccessExpression() { return 0; }
     virtual FunctionCallExpression *asFunctionCallExpression() { return 0; }
+    virtual FunctionIdentifier *asFunctionIdentifier() { return 0; }
 
     virtual Statement *asStatement() { return 0; }
     virtual ExpressionStatement *asExpressionStatement() { return 0; }
@@ -230,6 +234,9 @@ public:
     virtual ArrayType *asArrayType() { return 0; }
     virtual StructType *asStructType() { return 0; }
 
+    virtual Declaration *asDeclaration() { return 0; }
+    virtual PrecisionDeclaration *asPrecisionDeclaration() { return 0; }
+
     void accept(Visitor *visitor);
     static void accept(AST *ast, Visitor *visitor);
 
@@ -275,15 +282,6 @@ public: // attributes
     List<Declaration *> *declarations;
 };
 
-class GLSL_EXPORT Declaration: public AST
-{
-protected:
-    Declaration(Kind _kind) : AST(_kind) {}
-
-public:
-    virtual Declaration *asDeclaration() { return this; }
-};
-
 class GLSL_EXPORT Expression: public AST
 {
 protected:
@@ -399,13 +397,13 @@ public: // attributes
 class GLSL_EXPORT FunctionCallExpression: public Expression
 {
 public:
-    FunctionCallExpression(const std::string *_name,
+    FunctionCallExpression(FunctionIdentifier *_id,
                            List<Expression *> *_arguments)
-        : Expression(Kind_FunctionCall), expr(0), name(_name)
+        : Expression(Kind_FunctionCall), expr(0), id(_id)
         , arguments(finish(_arguments)) {}
-    FunctionCallExpression(Expression *_expr, const std::string *_name,
+    FunctionCallExpression(Expression *_expr, FunctionIdentifier *_id,
                            List<Expression *> *_arguments)
-        : Expression(Kind_MemberFunctionCall), expr(_expr), name(_name)
+        : Expression(Kind_MemberFunctionCall), expr(_expr), id(_id)
         , arguments(finish(_arguments)) {}
 
     virtual FunctionCallExpression *asFunctionCallExpression() { return this; }
@@ -414,10 +412,27 @@ public:
 
 public: // attributes
     Expression *expr;
-    const std::string *name;
+    FunctionIdentifier *id;
     List<Expression *> *arguments;
 };
 
+class GLSL_EXPORT FunctionIdentifier: public AST
+{
+public:
+    FunctionIdentifier(const std::string *_name)
+        : AST(Kind_FunctionIdentifier), name(_name), type(0) {}
+    FunctionIdentifier(Type *_type)
+        : AST(Kind_FunctionIdentifier), name(0), type(_type) {}
+
+    virtual FunctionIdentifier *asFunctionIdentifier() { return this; }
+
+    virtual void accept0(Visitor *visitor);
+
+public: // attributes
+    const std::string *name;
+    Type *type;
+};
+
 class GLSL_EXPORT Statement: public AST
 {
 protected:
@@ -444,6 +459,8 @@ public: // attributes
 class GLSL_EXPORT CompoundStatement: public Statement
 {
 public:
+    CompoundStatement()
+        : Statement(Kind_CompoundStatement), statements(0) {}
     CompoundStatement(List<Statement *> *_statements)
         : Statement(Kind_CompoundStatement), statements(finish(_statements)) {}
 
@@ -582,29 +599,59 @@ protected:
 public:
     enum Precision
     {
-        PrecNotValid,       // Precision not valid (e.g. structs and samplers).
+        PrecNotValid,       // Precision not valid (e.g. structs).
         PrecUnspecified,    // Precision not known, but can be validly set.
         Lowp,
         Mediump,
         Highp
     };
 
+    enum Category
+    {
+        Void,
+        Primitive,
+        Vector2,
+        Vector3,
+        Vector4,
+        Matrix,
+        Sampler1D,
+        Sampler2D,
+        Sampler3D,
+        SamplerCube,
+        Sampler1DShadow,
+        Sampler2DShadow,
+        SamplerCubeShadow,
+        Sampler1DArray,
+        Sampler2DArray,
+        SamplerCubeArray,
+        Sampler1DArrayShadow,
+        Sampler2DArrayShadow,
+        SamplerCubeArrayShadow,
+        Sampler2DRect,
+        Sampler2DRectShadow,
+        Sampler2DMS,
+        Sampler2DMSArray,
+        SamplerBuffer,
+        Array,
+        Struct
+    };
+
     virtual Type *asType() { return this; }
 
     virtual Precision precision() const = 0;
 
     // Set the precision for the innermost basic type.  Returns false if it
-    // is not valid to set a precision (e.g. structs, samplers, etc).
+    // is not valid to set a precision (e.g. structs).
     virtual bool setPrecision(Precision precision) = 0;
+
+    virtual Category category() const = 0;
 };
 
 class GLSL_EXPORT BasicType: public Type
 {
 public:
     // Pass the parser's token code: T_VOID, T_VEC4, etc.
-    BasicType(int _token);
-    BasicType(int _token, Precision _prec)
-        : Type(Kind_BasicType), prec(_prec), token(_token) {}
+    BasicType(int _token, const char *_name, Category _category);
 
     virtual BasicType *asBasicType() { return this; }
 
@@ -613,9 +660,13 @@ public:
     virtual Precision precision() const;
     virtual bool setPrecision(Precision precision);
 
+    virtual Category category() const { return categ; }
+
 public: // attributes
     Precision prec;
     int token;
+    const char *name;
+    Category categ;
 };
 
 class GLSL_EXPORT NamedType: public Type
@@ -630,6 +681,8 @@ public:
     virtual Precision precision() const;
     virtual bool setPrecision(Precision precision);
 
+    virtual Category category() const { return Struct; }
+
 public: // attributes
     const std::string *name;
 };
@@ -649,6 +702,8 @@ public:
     virtual Precision precision() const;
     virtual bool setPrecision(Precision precision);
 
+    virtual Category category() const { return Array; }
+
 public: // attributes
     Type *elementType;
     Expression *size;
@@ -691,19 +746,40 @@ public:
 
     // Fix the inner types of a field list.  The "innerType" will
     // be copied into the "array holes" of all fields.
-    static void fixInnerTypes(Type *innerType, List<Field *> *fields);
+    static List<Field *> *fixInnerTypes(Type *innerType, List<Field *> *fields);
 
-    // Add a new group of fields after having their inner types fixed.
-    void addFields(List<Field *> *list)
-    {
-        fields = appendLists(fields, list);
-    }
+    virtual Category category() const { return Struct; }
 
 public: // attributes
     const std::string *name;
     List<Field *> *fields;
 };
 
+class GLSL_EXPORT Declaration: public AST
+{
+protected:
+    Declaration(Kind _kind) : AST(_kind) {}
+
+public:
+    virtual Declaration *asDeclaration() { return this; }
+};
+
+class GLSL_EXPORT PrecisionDeclaration: public Declaration
+{
+public:
+    PrecisionDeclaration(Type::Precision _precision, Type *_type)
+        : Declaration(Kind_PrecisionDeclaration)
+        , precision(_precision), type(_type) {}
+
+    virtual PrecisionDeclaration *asPrecisionDeclaration() { return this; }
+
+    virtual void accept0(Visitor *visitor);
+
+public: // attributes
+    Type::Precision precision;
+    Type *type;
+};
+
 } // namespace GLSL
 
 #endif // GLSLAST_H
diff --git a/src/libs/glsl/glslastvisitor.h b/src/libs/glsl/glslastvisitor.h
index 0acc69a1f8b..38d4a2363e5 100644
--- a/src/libs/glsl/glslastvisitor.h
+++ b/src/libs/glsl/glslastvisitor.h
@@ -69,6 +69,9 @@ public:
     virtual bool visit(FunctionCallExpression *) { return true; }
     virtual void endVisit(FunctionCallExpression *) {}
 
+    virtual bool visit(FunctionIdentifier *) { return true; }
+    virtual void endVisit(FunctionIdentifier *) {}
+
     virtual bool visit(ExpressionStatement *) { return true; }
     virtual void endVisit(ExpressionStatement *) {}
 
@@ -113,6 +116,9 @@ public:
 
     virtual bool visit(StructType::Field *) { return true; }
     virtual void endVisit(StructType::Field *) {}
+
+    virtual bool visit(PrecisionDeclaration *) { return true; }
+    virtual void endVisit(PrecisionDeclaration *) {}
 };
 
 } // namespace GLSL
diff --git a/src/libs/glsl/glsllexer.cpp b/src/libs/glsl/glsllexer.cpp
index fff1f828108..05f99f2ba9b 100644
--- a/src/libs/glsl/glsllexer.cpp
+++ b/src/libs/glsl/glsllexer.cpp
@@ -372,9 +372,12 @@ int Lexer::yylex_helper(const char **position, int *line)
                 _yyval.string = _engine->identifier(word, _it - word - 1);
             return Parser::T_IDENTIFIER;
         } else if (std::isdigit(ch)) {
+            const char *word = _it - 2;
             while (std::isalnum(_yychar) || _yychar == '.') {
                 yyinp();
             }
+            if (_engine)
+                _yyval.string = _engine->identifier(word, _it - word - 1);
             return Parser::T_NUMBER;
         }
 
diff --git a/src/libs/glsl/glslparser.cpp b/src/libs/glsl/glslparser.cpp
index e4da61befb3..3ca57e8b13f 100644
--- a/src/libs/glsl/glslparser.cpp
+++ b/src/libs/glsl/glslparser.cpp
@@ -1,5 +1,5 @@
 
-#line 337 "./glsl.g"
+#line 367 "./glsl.g"
 
 /**************************************************************************
 **
@@ -159,1891 +159,1910 @@ TranslationUnit *Parser::parse()
     return 0;
 }
 
-#line 499 "./glsl.g"
+#line 529 "./glsl.g"
 
 void Parser::reduce(int ruleno)
 {
 switch(ruleno) {
 
-#line 508 "./glsl.g"
+#line 538 "./glsl.g"
 
 case 0: {
-    ast(1) = makeAstNode<IdentifierExpression>(sym(1).string);
+    ast(1) = makeAstNode<IdentifierExpression>(string(1));
 }   break;
 
-#line 515 "./glsl.g"
+#line 545 "./glsl.g"
 
 case 1: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<LiteralExpression>(string(1));
 }   break;
 
-#line 522 "./glsl.g"
+#line 552 "./glsl.g"
 
 case 2: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<LiteralExpression>(_engine->identifier("true", 4));
 }   break;
 
-#line 529 "./glsl.g"
+#line 559 "./glsl.g"
 
 case 3: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<LiteralExpression>(_engine->identifier("false", 5));
 }   break;
 
-#line 536 "./glsl.g"
+#line 566 "./glsl.g"
 
 case 4: {
     // nothing to do.
 }   break;
 
-#line 543 "./glsl.g"
+#line 573 "./glsl.g"
 
 case 5: {
     ast(1) = ast(2);
 }   break;
 
-#line 550 "./glsl.g"
+#line 580 "./glsl.g"
 
 case 6: {
     // nothing to do.
 }   break;
 
-#line 557 "./glsl.g"
+#line 587 "./glsl.g"
 
 case 7: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_ArrayAccess, expression(1), expression(3));
 }   break;
 
-#line 564 "./glsl.g"
+#line 594 "./glsl.g"
 
 case 8: {
     // nothing to do.
 }   break;
 
-#line 571 "./glsl.g"
+#line 601 "./glsl.g"
 
 case 9: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<MemberAccessExpression>(expression(1), string(3));
 }   break;
 
-#line 578 "./glsl.g"
+#line 608 "./glsl.g"
 
 case 10: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<UnaryExpression>(AST::Kind_PostIncrement, expression(1));
 }   break;
 
-#line 585 "./glsl.g"
+#line 615 "./glsl.g"
 
 case 11: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<UnaryExpression>(AST::Kind_PostDecrement, expression(1));
 }   break;
 
-#line 592 "./glsl.g"
+#line 622 "./glsl.g"
 
 case 12: {
     // nothing to do.
 }   break;
 
-#line 599 "./glsl.g"
+#line 629 "./glsl.g"
 
 case 13: {
     // nothing to do.
 }   break;
 
-#line 606 "./glsl.g"
+#line 636 "./glsl.g"
 
 case 14: {
-    // nothing to do.
+    ast(1) = makeAstNode<FunctionCallExpression>
+        (sym(1).function.id, sym(1).function.arguments);
 }   break;
 
-#line 613 "./glsl.g"
+#line 644 "./glsl.g"
 
 case 15: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<FunctionCallExpression>
+        (expression(1), sym(3).function.id, sym(3).function.arguments);
 }   break;
 
-#line 620 "./glsl.g"
+#line 652 "./glsl.g"
 
 case 16: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 627 "./glsl.g"
+#line 659 "./glsl.g"
 
 case 17: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 634 "./glsl.g"
+#line 666 "./glsl.g"
 
 case 18: {
-    // ast(1) = new ...AST(...);
+    sym(1).function.id = sym(1).function_identifier;
+    sym(1).function.arguments = 0;
 }   break;
 
-#line 641 "./glsl.g"
+#line 674 "./glsl.g"
 
 case 19: {
-    // ast(1) = new ...AST(...);
+    sym(1).function.id = sym(1).function_identifier;
+    sym(1).function.arguments = 0;
 }   break;
 
-#line 648 "./glsl.g"
+#line 682 "./glsl.g"
 
 case 20: {
-    // ast(1) = new ...AST(...);
+    sym(1).function.id = sym(1).function_identifier;
+    sym(1).function.arguments =
+        makeAstNode< List<Expression *> >(expression(2));
 }   break;
 
-#line 655 "./glsl.g"
+#line 691 "./glsl.g"
 
 case 21: {
-    // ast(1) = new ...AST(...);
+    sym(1).function.arguments =
+        makeAstNode< List<Expression *> >
+            (sym(1).function.arguments, expression(3));
 }   break;
 
-#line 662 "./glsl.g"
+#line 700 "./glsl.g"
 
 case 22: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 669 "./glsl.g"
+#line 707 "./glsl.g"
 
 case 23: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<FunctionIdentifier>(type(1));
 }   break;
 
-#line 676 "./glsl.g"
+#line 714 "./glsl.g"
 
 case 24: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<FunctionIdentifier>(string(1));
 }   break;
 
-#line 683 "./glsl.g"
+#line 721 "./glsl.g"
 
 case 25: {
     // nothing to do.
 }   break;
 
-#line 690 "./glsl.g"
+#line 728 "./glsl.g"
 
 case 26: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<UnaryExpression>(AST::Kind_PreIncrement, expression(1));
 }   break;
 
-#line 697 "./glsl.g"
+#line 735 "./glsl.g"
 
 case 27: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<UnaryExpression>(AST::Kind_PreDecrement, expression(1));
 }   break;
 
-#line 704 "./glsl.g"
+#line 742 "./glsl.g"
 
 case 28: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<UnaryExpression>(sym(1).kind, expression(2));
 }   break;
 
-#line 711 "./glsl.g"
+#line 749 "./glsl.g"
 
 case 29: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_UnaryPlus;
 }   break;
 
-#line 718 "./glsl.g"
+#line 756 "./glsl.g"
 
 case 30: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_UnaryMinus;
 }   break;
 
-#line 725 "./glsl.g"
+#line 763 "./glsl.g"
 
 case 31: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_LogicalNot;
 }   break;
 
-#line 732 "./glsl.g"
+#line 770 "./glsl.g"
 
 case 32: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_BitwiseNot;
 }   break;
 
-#line 739 "./glsl.g"
+#line 777 "./glsl.g"
 
 case 33: {
     // nothing to do.
 }   break;
 
-#line 746 "./glsl.g"
+#line 784 "./glsl.g"
 
 case 34: {
-    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Multiply, sym(1).expression, sym(3).expression);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Multiply, expression(1), expression(3));
 }   break;
 
-#line 753 "./glsl.g"
+#line 791 "./glsl.g"
 
 case 35: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Divide, expression(1), expression(3));
 }   break;
 
-#line 760 "./glsl.g"
+#line 798 "./glsl.g"
 
 case 36: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Modulus, expression(1), expression(3));
 }   break;
 
-#line 767 "./glsl.g"
+#line 805 "./glsl.g"
 
 case 37: {
     // nothing to do.
 }   break;
 
-#line 774 "./glsl.g"
+#line 812 "./glsl.g"
 
 case 38: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Plus, expression(1), expression(3));
 }   break;
 
-#line 781 "./glsl.g"
+#line 819 "./glsl.g"
 
 case 39: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Minus, expression(1), expression(3));
 }   break;
 
-#line 788 "./glsl.g"
+#line 826 "./glsl.g"
 
 case 40: {
     // nothing to do.
 }   break;
 
-#line 795 "./glsl.g"
+#line 833 "./glsl.g"
 
 case 41: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_ShiftLeft, expression(1), expression(3));
 }   break;
 
-#line 802 "./glsl.g"
+#line 840 "./glsl.g"
 
 case 42: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_ShiftRight, expression(1), expression(3));
 }   break;
 
-#line 809 "./glsl.g"
+#line 847 "./glsl.g"
 
 case 43: {
     // nothing to do.
 }   break;
 
-#line 816 "./glsl.g"
+#line 854 "./glsl.g"
 
 case 44: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_LessThan, expression(1), expression(3));
 }   break;
 
-#line 823 "./glsl.g"
+#line 861 "./glsl.g"
 
 case 45: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_GreaterThan, expression(1), expression(3));
 }   break;
 
-#line 830 "./glsl.g"
+#line 868 "./glsl.g"
 
 case 46: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_LessEqual, expression(1), expression(3));
 }   break;
 
-#line 837 "./glsl.g"
+#line 875 "./glsl.g"
 
 case 47: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_GreaterEqual, expression(1), expression(3));
 }   break;
 
-#line 844 "./glsl.g"
+#line 882 "./glsl.g"
 
 case 48: {
     // nothing to do.
 }   break;
 
-#line 851 "./glsl.g"
+#line 889 "./glsl.g"
 
 case 49: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Equal, expression(1), expression(3));
 }   break;
 
-#line 858 "./glsl.g"
+#line 896 "./glsl.g"
 
 case 50: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_NotEqual, expression(1), expression(3));
 }   break;
 
-#line 865 "./glsl.g"
+#line 903 "./glsl.g"
 
 case 51: {
     // nothing to do.
 }   break;
 
-#line 872 "./glsl.g"
+#line 910 "./glsl.g"
 
 case 52: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_BitwiseAnd, expression(1), expression(3));
 }   break;
 
-#line 879 "./glsl.g"
+#line 917 "./glsl.g"
 
 case 53: {
     // nothing to do.
 }   break;
 
-#line 886 "./glsl.g"
+#line 924 "./glsl.g"
 
 case 54: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_BitwiseOr, expression(1), expression(3));
 }   break;
 
-#line 893 "./glsl.g"
+#line 931 "./glsl.g"
 
 case 55: {
     // nothing to do.
 }   break;
 
-#line 900 "./glsl.g"
+#line 938 "./glsl.g"
 
 case 56: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_BitwiseXor, expression(1), expression(3));
 }   break;
 
-#line 907 "./glsl.g"
+#line 945 "./glsl.g"
 
 case 57: {
     // nothing to do.
 }   break;
 
-#line 914 "./glsl.g"
+#line 952 "./glsl.g"
 
 case 58: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_LogicalAnd, expression(1), expression(3));
 }   break;
 
-#line 921 "./glsl.g"
+#line 959 "./glsl.g"
 
 case 59: {
     // nothing to do.
 }   break;
 
-#line 928 "./glsl.g"
+#line 966 "./glsl.g"
 
 case 60: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_LogicalXor, expression(1), expression(3));
 }   break;
 
-#line 935 "./glsl.g"
+#line 973 "./glsl.g"
 
 case 61: {
     // nothing to do.
 }   break;
 
-#line 942 "./glsl.g"
+#line 980 "./glsl.g"
 
 case 62: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_LogicalOr, expression(1), expression(3));
 }   break;
 
-#line 949 "./glsl.g"
+#line 987 "./glsl.g"
 
 case 63: {
     // nothing to do.
 }   break;
 
-#line 956 "./glsl.g"
+#line 994 "./glsl.g"
 
 case 64: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<TernaryExpression>(AST::Kind_Conditional, expression(1), expression(3), expression(5));
 }   break;
 
-#line 963 "./glsl.g"
+#line 1001 "./glsl.g"
 
 case 65: {
     // nothing to do.
 }   break;
 
-#line 970 "./glsl.g"
+#line 1008 "./glsl.g"
 
 case 66: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<AssignmentExpression>(sym(2).kind, expression(1), expression(3));
 }   break;
 
-#line 977 "./glsl.g"
+#line 1015 "./glsl.g"
 
 case 67: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_Assign;
 }   break;
 
-#line 984 "./glsl.g"
+#line 1022 "./glsl.g"
 
 case 68: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignMultiply;
 }   break;
 
-#line 991 "./glsl.g"
+#line 1029 "./glsl.g"
 
 case 69: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignDivide;
 }   break;
 
-#line 998 "./glsl.g"
+#line 1036 "./glsl.g"
 
 case 70: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignModulus;
 }   break;
 
-#line 1005 "./glsl.g"
+#line 1043 "./glsl.g"
 
 case 71: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignPlus;
 }   break;
 
-#line 1012 "./glsl.g"
+#line 1050 "./glsl.g"
 
 case 72: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignMinus;
 }   break;
 
-#line 1019 "./glsl.g"
+#line 1057 "./glsl.g"
 
 case 73: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignShiftLeft;
 }   break;
 
-#line 1026 "./glsl.g"
+#line 1064 "./glsl.g"
 
 case 74: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignShiftRight;
 }   break;
 
-#line 1033 "./glsl.g"
+#line 1071 "./glsl.g"
 
 case 75: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignAnd;
 }   break;
 
-#line 1040 "./glsl.g"
+#line 1078 "./glsl.g"
 
 case 76: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignXor;
 }   break;
 
-#line 1047 "./glsl.g"
+#line 1085 "./glsl.g"
 
 case 77: {
-    // ast(1) = new ...AST(...);
+    sym(1).kind = AST::Kind_AssignOr;
 }   break;
 
-#line 1054 "./glsl.g"
+#line 1092 "./glsl.g"
 
 case 78: {
     // nothing to do.
 }   break;
 
-#line 1061 "./glsl.g"
+#line 1099 "./glsl.g"
 
 case 79: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<BinaryExpression>(AST::Kind_Comma, expression(1), expression(3));
 }   break;
 
-#line 1068 "./glsl.g"
+#line 1106 "./glsl.g"
 
 case 80: {
     // nothing to do.
 }   break;
 
-#line 1075 "./glsl.g"
+#line 1113 "./glsl.g"
 
 case 81: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1082 "./glsl.g"
+#line 1120 "./glsl.g"
 
 case 82: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1089 "./glsl.g"
+#line 1127 "./glsl.g"
 
 case 83: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<PrecisionDeclaration>(sym(2).precision, type(3));
 }   break;
 
-#line 1096 "./glsl.g"
+#line 1134 "./glsl.g"
 
 case 84: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1103 "./glsl.g"
+#line 1141 "./glsl.g"
 
 case 85: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1110 "./glsl.g"
+#line 1148 "./glsl.g"
 
 case 86: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1117 "./glsl.g"
+#line 1155 "./glsl.g"
 
 case 87: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1124 "./glsl.g"
+#line 1162 "./glsl.g"
 
 case 88: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1131 "./glsl.g"
+#line 1169 "./glsl.g"
 
 case 89: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1138 "./glsl.g"
+#line 1176 "./glsl.g"
 
 case 90: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1145 "./glsl.g"
+#line 1183 "./glsl.g"
 
 case 91: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1152 "./glsl.g"
+#line 1190 "./glsl.g"
 
 case 92: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1159 "./glsl.g"
+#line 1197 "./glsl.g"
 
 case 93: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1166 "./glsl.g"
+#line 1204 "./glsl.g"
 
 case 94: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1173 "./glsl.g"
+#line 1211 "./glsl.g"
 
 case 95: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1180 "./glsl.g"
+#line 1218 "./glsl.g"
 
 case 96: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1187 "./glsl.g"
+#line 1225 "./glsl.g"
 
 case 97: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1194 "./glsl.g"
+#line 1232 "./glsl.g"
 
 case 98: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1201 "./glsl.g"
+#line 1239 "./glsl.g"
 
 case 99: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1208 "./glsl.g"
+#line 1246 "./glsl.g"
 
 case 100: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1215 "./glsl.g"
+#line 1253 "./glsl.g"
 
 case 101: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1222 "./glsl.g"
+#line 1260 "./glsl.g"
 
 case 102: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1229 "./glsl.g"
+#line 1267 "./glsl.g"
 
 case 103: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1236 "./glsl.g"
+#line 1274 "./glsl.g"
 
 case 104: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1243 "./glsl.g"
+#line 1281 "./glsl.g"
 
 case 105: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1250 "./glsl.g"
+#line 1288 "./glsl.g"
 
 case 106: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1257 "./glsl.g"
+#line 1295 "./glsl.g"
 
 case 107: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1264 "./glsl.g"
+#line 1302 "./glsl.g"
 
 case 108: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1271 "./glsl.g"
+#line 1309 "./glsl.g"
 
 case 109: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1278 "./glsl.g"
+#line 1316 "./glsl.g"
 
 case 110: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1285 "./glsl.g"
+#line 1323 "./glsl.g"
 
 case 111: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1292 "./glsl.g"
+#line 1330 "./glsl.g"
 
 case 112: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1299 "./glsl.g"
+#line 1337 "./glsl.g"
 
 case 113: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1306 "./glsl.g"
+#line 1344 "./glsl.g"
 
 case 114: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1313 "./glsl.g"
+#line 1351 "./glsl.g"
 
 case 115: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1320 "./glsl.g"
+#line 1358 "./glsl.g"
 
 case 116: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1327 "./glsl.g"
+#line 1365 "./glsl.g"
 
 case 117: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1334 "./glsl.g"
+#line 1372 "./glsl.g"
 
 case 118: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1341 "./glsl.g"
+#line 1379 "./glsl.g"
 
 case 119: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1348 "./glsl.g"
+#line 1386 "./glsl.g"
 
 case 120: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1355 "./glsl.g"
+#line 1393 "./glsl.g"
 
 case 121: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1362 "./glsl.g"
+#line 1400 "./glsl.g"
 
 case 122: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1369 "./glsl.g"
+#line 1407 "./glsl.g"
 
 case 123: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1376 "./glsl.g"
+#line 1414 "./glsl.g"
 
 case 124: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1383 "./glsl.g"
+#line 1421 "./glsl.g"
 
 case 125: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1390 "./glsl.g"
+#line 1428 "./glsl.g"
 
 case 126: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1397 "./glsl.g"
+#line 1435 "./glsl.g"
 
 case 127: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1404 "./glsl.g"
+#line 1442 "./glsl.g"
 
 case 128: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1411 "./glsl.g"
+#line 1449 "./glsl.g"
 
 case 129: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1418 "./glsl.g"
+#line 1456 "./glsl.g"
 
 case 130: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1425 "./glsl.g"
+#line 1463 "./glsl.g"
 
 case 131: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1432 "./glsl.g"
+#line 1470 "./glsl.g"
 
 case 132: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1439 "./glsl.g"
+#line 1477 "./glsl.g"
 
 case 133: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1446 "./glsl.g"
+#line 1484 "./glsl.g"
 
 case 134: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1453 "./glsl.g"
+#line 1491 "./glsl.g"
 
 case 135: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1460 "./glsl.g"
+#line 1498 "./glsl.g"
 
 case 136: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1467 "./glsl.g"
+#line 1505 "./glsl.g"
 
 case 137: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1474 "./glsl.g"
+#line 1512 "./glsl.g"
 
 case 138: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1481 "./glsl.g"
+#line 1519 "./glsl.g"
 
 case 139: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1488 "./glsl.g"
+#line 1526 "./glsl.g"
 
 case 140: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1495 "./glsl.g"
+#line 1533 "./glsl.g"
 
 case 141: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1502 "./glsl.g"
+#line 1540 "./glsl.g"
 
 case 142: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1509 "./glsl.g"
+#line 1547 "./glsl.g"
 
 case 143: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1516 "./glsl.g"
+#line 1554 "./glsl.g"
 
 case 144: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1523 "./glsl.g"
+#line 1561 "./glsl.g"
 
 case 145: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1530 "./glsl.g"
+#line 1568 "./glsl.g"
 
 case 146: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1537 "./glsl.g"
+#line 1575 "./glsl.g"
 
 case 147: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1544 "./glsl.g"
+#line 1582 "./glsl.g"
 
 case 148: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1551 "./glsl.g"
+#line 1589 "./glsl.g"
 
 case 149: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1558 "./glsl.g"
+#line 1596 "./glsl.g"
 
 case 150: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1565 "./glsl.g"
+#line 1603 "./glsl.g"
 
 case 151: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1572 "./glsl.g"
+#line 1610 "./glsl.g"
 
 case 152: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1579 "./glsl.g"
+#line 1617 "./glsl.g"
 
 case 153: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 1586 "./glsl.g"
+#line 1624 "./glsl.g"
 
 case 154: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 1593 "./glsl.g"
+#line 1631 "./glsl.g"
 
 case 155: {
-    // ast(1) = new ...AST(...);
+    if (!type(2)->setPrecision(sym(1).precision)) {
+        // TODO: issue an error about precision not allowed on this type.
+    }
+    ast(1) = type(2);
 }   break;
 
-#line 1600 "./glsl.g"
+#line 1641 "./glsl.g"
 
 case 156: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 1607 "./glsl.g"
+#line 1648 "./glsl.g"
 
 case 157: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<ArrayType>(type(1));
 }   break;
 
-#line 1614 "./glsl.g"
+#line 1655 "./glsl.g"
 
 case 158: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<ArrayType>(type(1), expression(3));
 }   break;
 
-#line 1621 "./glsl.g"
+#line 1662 "./glsl.g"
 
 case 159: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_VOID, Type::Void);
 }   break;
 
-#line 1628 "./glsl.g"
+#line 1669 "./glsl.g"
 
 case 160: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_FLOAT, Type::Primitive);
 }   break;
 
-#line 1635 "./glsl.g"
+#line 1676 "./glsl.g"
 
 case 161: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DOUBLE, Type::Primitive);
 }   break;
 
-#line 1642 "./glsl.g"
+#line 1683 "./glsl.g"
 
 case 162: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_INT, Type::Primitive);
 }   break;
 
-#line 1649 "./glsl.g"
+#line 1690 "./glsl.g"
 
 case 163: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_UINT, Type::Primitive);
 }   break;
 
-#line 1656 "./glsl.g"
+#line 1697 "./glsl.g"
 
 case 164: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_BOOL, Type::Primitive);
 }   break;
 
-#line 1663 "./glsl.g"
+#line 1704 "./glsl.g"
 
 case 165: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_VEC2, Type::Vector2);
 }   break;
 
-#line 1670 "./glsl.g"
+#line 1711 "./glsl.g"
 
 case 166: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_VEC3, Type::Vector3);
 }   break;
 
-#line 1677 "./glsl.g"
+#line 1718 "./glsl.g"
 
 case 167: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_VEC4, Type::Vector4);
 }   break;
 
-#line 1684 "./glsl.g"
+#line 1725 "./glsl.g"
 
 case 168: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DVEC2, Type::Vector2);
 }   break;
 
-#line 1691 "./glsl.g"
+#line 1732 "./glsl.g"
 
 case 169: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DVEC3, Type::Vector3);
 }   break;
 
-#line 1698 "./glsl.g"
+#line 1739 "./glsl.g"
 
 case 170: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DVEC4, Type::Vector4);
 }   break;
 
-#line 1705 "./glsl.g"
+#line 1746 "./glsl.g"
 
 case 171: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_BVEC2, Type::Vector2);
 }   break;
 
-#line 1712 "./glsl.g"
+#line 1753 "./glsl.g"
 
 case 172: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_BVEC3, Type::Vector3);
 }   break;
 
-#line 1719 "./glsl.g"
+#line 1760 "./glsl.g"
 
 case 173: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_BVEC4, Type::Vector4);
 }   break;
 
-#line 1726 "./glsl.g"
+#line 1767 "./glsl.g"
 
 case 174: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_IVEC2, Type::Vector2);
 }   break;
 
-#line 1733 "./glsl.g"
+#line 1774 "./glsl.g"
 
 case 175: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_IVEC3, Type::Vector3);
 }   break;
 
-#line 1740 "./glsl.g"
+#line 1781 "./glsl.g"
 
 case 176: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_IVEC4, Type::Vector4);
 }   break;
 
-#line 1747 "./glsl.g"
+#line 1788 "./glsl.g"
 
 case 177: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_UVEC2, Type::Vector2);
 }   break;
 
-#line 1754 "./glsl.g"
+#line 1795 "./glsl.g"
 
 case 178: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_UVEC3, Type::Vector3);
 }   break;
 
-#line 1761 "./glsl.g"
+#line 1802 "./glsl.g"
 
 case 179: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_UVEC4, Type::Vector4);
 }   break;
 
-#line 1768 "./glsl.g"
+#line 1809 "./glsl.g"
 
 case 180: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT2, Type::Matrix);
 }   break;
 
-#line 1775 "./glsl.g"
+#line 1816 "./glsl.g"
 
 case 181: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT3, Type::Matrix);
 }   break;
 
-#line 1782 "./glsl.g"
+#line 1823 "./glsl.g"
 
 case 182: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT4, Type::Matrix);
 }   break;
 
-#line 1789 "./glsl.g"
+#line 1830 "./glsl.g"
 
 case 183: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT2X2, Type::Matrix);
 }   break;
 
-#line 1796 "./glsl.g"
+#line 1837 "./glsl.g"
 
 case 184: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT2X3, Type::Matrix);
 }   break;
 
-#line 1803 "./glsl.g"
+#line 1844 "./glsl.g"
 
 case 185: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT2X4, Type::Matrix);
 }   break;
 
-#line 1810 "./glsl.g"
+#line 1851 "./glsl.g"
 
 case 186: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT3X2, Type::Matrix);
 }   break;
 
-#line 1817 "./glsl.g"
+#line 1858 "./glsl.g"
 
 case 187: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT3X3, Type::Matrix);
 }   break;
 
-#line 1824 "./glsl.g"
+#line 1865 "./glsl.g"
 
 case 188: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT3X4, Type::Matrix);
 }   break;
 
-#line 1831 "./glsl.g"
+#line 1872 "./glsl.g"
 
 case 189: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT4X2, Type::Matrix);
 }   break;
 
-#line 1838 "./glsl.g"
+#line 1879 "./glsl.g"
 
 case 190: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT4X3, Type::Matrix);
 }   break;
 
-#line 1845 "./glsl.g"
+#line 1886 "./glsl.g"
 
 case 191: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_MAT4X4, Type::Matrix);
 }   break;
 
-#line 1852 "./glsl.g"
+#line 1893 "./glsl.g"
 
 case 192: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT2, Type::Matrix);
 }   break;
 
-#line 1859 "./glsl.g"
+#line 1900 "./glsl.g"
 
 case 193: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT3, Type::Matrix);
 }   break;
 
-#line 1866 "./glsl.g"
+#line 1907 "./glsl.g"
 
 case 194: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT4, Type::Matrix);
 }   break;
 
-#line 1873 "./glsl.g"
+#line 1914 "./glsl.g"
 
 case 195: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT2X2, Type::Matrix);
 }   break;
 
-#line 1880 "./glsl.g"
+#line 1921 "./glsl.g"
 
 case 196: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT2X3, Type::Matrix);
 }   break;
 
-#line 1887 "./glsl.g"
+#line 1928 "./glsl.g"
 
 case 197: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT2X4, Type::Matrix);
 }   break;
 
-#line 1894 "./glsl.g"
+#line 1935 "./glsl.g"
 
 case 198: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT3X2, Type::Matrix);
 }   break;
 
-#line 1901 "./glsl.g"
+#line 1942 "./glsl.g"
 
 case 199: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT3X3, Type::Matrix);
 }   break;
 
-#line 1908 "./glsl.g"
+#line 1949 "./glsl.g"
 
 case 200: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT3X4, Type::Matrix);
 }   break;
 
-#line 1915 "./glsl.g"
+#line 1956 "./glsl.g"
 
 case 201: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT4X2, Type::Matrix);
 }   break;
 
-#line 1922 "./glsl.g"
+#line 1963 "./glsl.g"
 
 case 202: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT4X3, Type::Matrix);
 }   break;
 
-#line 1929 "./glsl.g"
+#line 1970 "./glsl.g"
 
 case 203: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_DMAT4X4, Type::Matrix);
 }   break;
 
-#line 1936 "./glsl.g"
+#line 1977 "./glsl.g"
 
 case 204: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER1D, Type::Sampler1D);
 }   break;
 
-#line 1943 "./glsl.g"
+#line 1984 "./glsl.g"
 
 case 205: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2D, Type::Sampler2D);
 }   break;
 
-#line 1950 "./glsl.g"
+#line 1991 "./glsl.g"
 
 case 206: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER3D, Type::Sampler3D);
 }   break;
 
-#line 1957 "./glsl.g"
+#line 1998 "./glsl.g"
 
 case 207: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLERCUBE, Type::SamplerCube);
 }   break;
 
-#line 1964 "./glsl.g"
+#line 2005 "./glsl.g"
 
 case 208: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER1DSHADOW, Type::Sampler1DShadow);
 }   break;
 
-#line 1971 "./glsl.g"
+#line 2012 "./glsl.g"
 
 case 209: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DSHADOW, Type::Sampler2DShadow);
 }   break;
 
-#line 1978 "./glsl.g"
+#line 2019 "./glsl.g"
 
 case 210: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLERCUBESHADOW, Type::SamplerCubeShadow);
 }   break;
 
-#line 1985 "./glsl.g"
+#line 2026 "./glsl.g"
 
 case 211: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER1DARRAY, Type::Sampler1DArray);
 }   break;
 
-#line 1992 "./glsl.g"
+#line 2033 "./glsl.g"
 
 case 212: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DARRAY, Type::Sampler2DArray);
 }   break;
 
-#line 1999 "./glsl.g"
+#line 2040 "./glsl.g"
 
 case 213: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER1DARRAYSHADOW, Type::Sampler1DArrayShadow);
 }   break;
 
-#line 2006 "./glsl.g"
+#line 2047 "./glsl.g"
 
 case 214: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DARRAYSHADOW, Type::Sampler2DArrayShadow);
 }   break;
 
-#line 2013 "./glsl.g"
+#line 2054 "./glsl.g"
 
 case 215: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLERCUBEARRAY, Type::SamplerCubeShadow);
 }   break;
 
-#line 2020 "./glsl.g"
+#line 2061 "./glsl.g"
 
 case 216: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLERCUBEARRAYSHADOW, Type::SamplerCubeArrayShadow);
 }   break;
 
-#line 2027 "./glsl.g"
+#line 2068 "./glsl.g"
 
 case 217: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER1D, Type::Sampler1D);
 }   break;
 
-#line 2034 "./glsl.g"
+#line 2075 "./glsl.g"
 
 case 218: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER2D, Type::Sampler2D);
 }   break;
 
-#line 2041 "./glsl.g"
+#line 2082 "./glsl.g"
 
 case 219: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER3D, Type::Sampler3D);
 }   break;
 
-#line 2048 "./glsl.g"
+#line 2089 "./glsl.g"
 
 case 220: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLERCUBE, Type::SamplerCube);
 }   break;
 
-#line 2055 "./glsl.g"
+#line 2096 "./glsl.g"
 
 case 221: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER1DARRAY, Type::Sampler1DArray);
 }   break;
 
-#line 2062 "./glsl.g"
+#line 2103 "./glsl.g"
 
 case 222: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER2DARRAY, Type::Sampler2DArray);
 }   break;
 
-#line 2069 "./glsl.g"
+#line 2110 "./glsl.g"
 
 case 223: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLERCUBEARRAY, Type::SamplerCubeArray);
 }   break;
 
-#line 2076 "./glsl.g"
+#line 2117 "./glsl.g"
 
 case 224: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER1D, Type::Sampler1D);
 }   break;
 
-#line 2083 "./glsl.g"
+#line 2124 "./glsl.g"
 
 case 225: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER2D, Type::Sampler2D);
 }   break;
 
-#line 2090 "./glsl.g"
+#line 2131 "./glsl.g"
 
 case 226: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER3D, Type::Sampler3D);
 }   break;
 
-#line 2097 "./glsl.g"
+#line 2138 "./glsl.g"
 
 case 227: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLERCUBE, Type::SamplerCube);
 }   break;
 
-#line 2104 "./glsl.g"
+#line 2145 "./glsl.g"
 
 case 228: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER1DARRAY, Type::Sampler1DArray);
 }   break;
 
-#line 2111 "./glsl.g"
+#line 2152 "./glsl.g"
 
 case 229: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER2DARRAY, Type::Sampler2DArray);
 }   break;
 
-#line 2118 "./glsl.g"
+#line 2159 "./glsl.g"
 
 case 230: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLERCUBEARRAY, Type::SamplerCubeArray);
 }   break;
 
-#line 2125 "./glsl.g"
+#line 2166 "./glsl.g"
 
 case 231: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DRECT, Type::Sampler2DRect);
 }   break;
 
-#line 2132 "./glsl.g"
+#line 2173 "./glsl.g"
 
 case 232: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DRECTSHADOW, Type::Sampler2DRectShadow);
 }   break;
 
-#line 2139 "./glsl.g"
+#line 2180 "./glsl.g"
 
 case 233: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER2DRECT, Type::Sampler2DRect);
 }   break;
 
-#line 2146 "./glsl.g"
+#line 2187 "./glsl.g"
 
 case 234: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER2DRECT, Type::Sampler2DRect);
 }   break;
 
-#line 2153 "./glsl.g"
+#line 2194 "./glsl.g"
 
 case 235: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLERBUFFER, Type::SamplerBuffer);
 }   break;
 
-#line 2160 "./glsl.g"
+#line 2201 "./glsl.g"
 
 case 236: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLERBUFFER, Type::SamplerBuffer);
 }   break;
 
-#line 2167 "./glsl.g"
+#line 2208 "./glsl.g"
 
 case 237: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLERBUFFER, Type::SamplerBuffer);
 }   break;
 
-#line 2174 "./glsl.g"
+#line 2215 "./glsl.g"
 
 case 238: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DMS, Type::Sampler2DMS);
 }   break;
 
-#line 2181 "./glsl.g"
+#line 2222 "./glsl.g"
 
 case 239: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER2DMS, Type::Sampler2DMS);
 }   break;
 
-#line 2188 "./glsl.g"
+#line 2229 "./glsl.g"
 
 case 240: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER2DMS, Type::Sampler2DMS);
 }   break;
 
-#line 2195 "./glsl.g"
+#line 2236 "./glsl.g"
 
 case 241: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_SAMPLER2DMSARRAY, Type::Sampler2DMSArray);
 }   break;
 
-#line 2202 "./glsl.g"
+#line 2243 "./glsl.g"
 
 case 242: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_ISAMPLER2DMSARRAY, Type::Sampler2DMSArray);
 }   break;
 
-#line 2209 "./glsl.g"
+#line 2250 "./glsl.g"
 
 case 243: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeBasicType(T_USAMPLER2DMSARRAY, Type::Sampler2DMSArray);
 }   break;
 
-#line 2216 "./glsl.g"
+#line 2257 "./glsl.g"
 
 case 244: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2223 "./glsl.g"
+#line 2264 "./glsl.g"
 
 case 245: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<NamedType>(string(1));
 }   break;
 
-#line 2230 "./glsl.g"
+#line 2271 "./glsl.g"
 
 case 246: {
-    // ast(1) = new ...AST(...);
+    sym(1).precision = Type::Highp;
 }   break;
 
-#line 2237 "./glsl.g"
+#line 2278 "./glsl.g"
 
 case 247: {
-    // ast(1) = new ...AST(...);
+    sym(1).precision = Type::Mediump;
 }   break;
 
-#line 2244 "./glsl.g"
+#line 2285 "./glsl.g"
 
 case 248: {
-    // ast(1) = new ...AST(...);
+    sym(1).precision = Type::Lowp;
 }   break;
 
-#line 2251 "./glsl.g"
+#line 2292 "./glsl.g"
 
 case 249: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<StructType>(string(2), sym(4).field_list);
 }   break;
 
-#line 2258 "./glsl.g"
+#line 2299 "./glsl.g"
 
 case 250: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<StructType>(sym(3).field_list);
 }   break;
 
-#line 2265 "./glsl.g"
+#line 2306 "./glsl.g"
 
 case 251: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2272 "./glsl.g"
+#line 2313 "./glsl.g"
 
 case 252: {
-    // ast(1) = new ...AST(...);
+    sym(1).field_list = appendLists(sym(1).field_list, sym(2).field_list);
 }   break;
 
-#line 2279 "./glsl.g"
+#line 2320 "./glsl.g"
 
 case 253: {
-    // ast(1) = new ...AST(...);
+    sym(1).field_list = StructType::fixInnerTypes(type(1), sym(2).field_list);
 }   break;
 
-#line 2286 "./glsl.g"
+#line 2327 "./glsl.g"
 
 case 254: {
-    // ast(1) = new ...AST(...);
+    // TODO: type qualifier
+    sym(1).field_list = StructType::fixInnerTypes(type(2), sym(3).field_list);
 }   break;
 
-#line 2293 "./glsl.g"
+#line 2335 "./glsl.g"
 
 case 255: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
+    sym(1).field_list = makeAstNode< List<StructType::Field *> >(sym(1).field);
 }   break;
 
-#line 2300 "./glsl.g"
+#line 2343 "./glsl.g"
 
 case 256: {
-    // ast(1) = new ...AST(...);
+    sym(1).field_list = makeAstNode< List<StructType::Field *> >(sym(1).field_list, sym(3).field);
 }   break;
 
-#line 2307 "./glsl.g"
+#line 2350 "./glsl.g"
 
 case 257: {
-    // ast(1) = new ...AST(...);
+    sym(1).field = makeAstNode<StructType::Field>(string(1));
 }   break;
 
-#line 2314 "./glsl.g"
+#line 2357 "./glsl.g"
 
 case 258: {
-    // ast(1) = new ...AST(...);
+    sym(1).field = makeAstNode<StructType::Field>
+        (string(1), makeAstNode<ArrayType>((Type *)0));
 }   break;
 
-#line 2321 "./glsl.g"
+#line 2365 "./glsl.g"
 
 case 259: {
-    // ast(1) = new ...AST(...);
+    sym(1).field = makeAstNode<StructType::Field>
+        (string(1), makeAstNode<ArrayType>((Type *)0, expression(3)));
 }   break;
 
-#line 2328 "./glsl.g"
+#line 2373 "./glsl.g"
 
 case 260: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 2335 "./glsl.g"
+#line 2380 "./glsl.g"
 
 case 261: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 2342 "./glsl.g"
+#line 2387 "./glsl.g"
 
 case 262: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2349 "./glsl.g"
+#line 2394 "./glsl.g"
 
 case 263: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2356 "./glsl.g"
+#line 2401 "./glsl.g"
 
 case 264: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2363 "./glsl.g"
+#line 2408 "./glsl.g"
 
 case 265: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2370 "./glsl.g"
+#line 2415 "./glsl.g"
 
 case 266: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2377 "./glsl.g"
+#line 2422 "./glsl.g"
 
 case 267: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2384 "./glsl.g"
+#line 2429 "./glsl.g"
 
 case 268: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2391 "./glsl.g"
+#line 2436 "./glsl.g"
 
 case 269: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2398 "./glsl.g"
+#line 2443 "./glsl.g"
 
 case 270: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2405 "./glsl.g"
+#line 2450 "./glsl.g"
 
 case 271: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>();
 }   break;
 
-#line 2412 "./glsl.g"
+#line 2457 "./glsl.g"
 
 case 272: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>(sym(2).statement_list);
 }   break;
 
-#line 2419 "./glsl.g"
+#line 2464 "./glsl.g"
 
 case 273: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2426 "./glsl.g"
+#line 2471 "./glsl.g"
 
 case 274: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2433 "./glsl.g"
+#line 2478 "./glsl.g"
 
 case 275: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>();
 }   break;
 
-#line 2440 "./glsl.g"
+#line 2485 "./glsl.g"
 
 case 276: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>(sym(2).statement_list);
 }   break;
 
-#line 2447 "./glsl.g"
+#line 2492 "./glsl.g"
 
 case 277: {
-    // ast(1) = new ...AST(...);
+    sym(1).statement_list = makeAstNode< List<Statement *> >(sym(1).statement);
 }   break;
 
-#line 2454 "./glsl.g"
+#line 2499 "./glsl.g"
 
 case 278: {
-    // ast(1) = new ...AST(...);
+    sym(1).statement_list = makeAstNode< List<Statement *> >(sym(1).statement_list, sym(2).statement);
 }   break;
 
-#line 2461 "./glsl.g"
+#line 2506 "./glsl.g"
 
 case 279: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>();  // Empty statement
 }   break;
 
-#line 2468 "./glsl.g"
+#line 2513 "./glsl.g"
 
 case 280: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<ExpressionStatement>(expression(1));
 }   break;
 
-#line 2475 "./glsl.g"
+#line 2520 "./glsl.g"
 
 case 281: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<IfStatement>(expression(3), sym(5).ifstmt.thenClause, sym(5).ifstmt.elseClause);
 }   break;
 
-#line 2482 "./glsl.g"
+#line 2527 "./glsl.g"
 
 case 282: {
-    // ast(1) = new ...AST(...);
+    sym(1).ifstmt.thenClause = statement(1);
+    sym(1).ifstmt.elseClause = statement(3);
 }   break;
 
-#line 2489 "./glsl.g"
+#line 2535 "./glsl.g"
 
 case 283: {
-    // ast(1) = new ...AST(...);
+    sym(1).ifstmt.thenClause = statement(1);
+    sym(1).ifstmt.elseClause = 0;
 }   break;
 
-#line 2496 "./glsl.g"
+#line 2543 "./glsl.g"
 
 case 284: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2503 "./glsl.g"
+#line 2550 "./glsl.g"
 
 case 285: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 2510 "./glsl.g"
+#line 2557 "./glsl.g"
 
 case 286: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<SwitchStatement>(expression(3), statement(6));
 }   break;
 
-#line 2517 "./glsl.g"
+#line 2564 "./glsl.g"
 
 case 287: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>();
 }   break;
 
-#line 2524 "./glsl.g"
+#line 2571 "./glsl.g"
 
 case 288: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CompoundStatement>(sym(1).statement_list);
 }   break;
 
-#line 2531 "./glsl.g"
+#line 2578 "./glsl.g"
 
 case 289: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CaseLabelStatement>(expression(2));
 }   break;
 
-#line 2538 "./glsl.g"
+#line 2585 "./glsl.g"
 
 case 290: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<CaseLabelStatement>();
 }   break;
 
-#line 2545 "./glsl.g"
+#line 2592 "./glsl.g"
 
 case 291: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<WhileStatement>(expression(3), statement(5));
 }   break;
 
-#line 2552 "./glsl.g"
+#line 2599 "./glsl.g"
 
 case 292: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<DoStatement>(statement(2), expression(5));
 }   break;
 
-#line 2559 "./glsl.g"
+#line 2606 "./glsl.g"
 
 case 293: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<ForStatement>(statement(3), sym(4).forstmt.condition, sym(4).forstmt.increment, statement(6));
 }   break;
 
-#line 2566 "./glsl.g"
+#line 2613 "./glsl.g"
 
 case 294: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2573 "./glsl.g"
+#line 2620 "./glsl.g"
 
 case 295: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2580 "./glsl.g"
+#line 2627 "./glsl.g"
 
 case 296: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2587 "./glsl.g"
+#line 2634 "./glsl.g"
 
 case 297: {
-    // ast(1) = new ...AST(...);
+    // nothing to do.
 }   break;
 
-#line 2594 "./glsl.g"
+#line 2641 "./glsl.g"
 
 case 298: {
-    // ast(1) = new ...AST(...);
+    sym(1).forstmt.condition = expression(1);
+    sym(1).forstmt.increment = 0;
 }   break;
 
-#line 2601 "./glsl.g"
+#line 2649 "./glsl.g"
 
 case 299: {
-    // ast(1) = new ...AST(...);
+    sym(1).forstmt.condition = expression(1);
+    sym(1).forstmt.increment = expression(3);
 }   break;
 
-#line 2608 "./glsl.g"
+#line 2657 "./glsl.g"
 
 case 300: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<JumpStatement>(AST::Kind_Continue);
 }   break;
 
-#line 2615 "./glsl.g"
+#line 2664 "./glsl.g"
 
 case 301: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<JumpStatement>(AST::Kind_Break);
 }   break;
 
-#line 2622 "./glsl.g"
+#line 2671 "./glsl.g"
 
 case 302: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<ReturnStatement>();
 }   break;
 
-#line 2629 "./glsl.g"
+#line 2678 "./glsl.g"
 
 case 303: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<ReturnStatement>(expression(2));
 }   break;
 
-#line 2636 "./glsl.g"
+#line 2685 "./glsl.g"
 
 case 304: {
-    // ast(1) = new ...AST(...);
+    ast(1) = makeAstNode<JumpStatement>(AST::Kind_Discard);
 }   break;
 
-#line 2643 "./glsl.g"
+#line 2692 "./glsl.g"
 
 case 305: {
     ast(1) = makeAstNode<TranslationUnit>(sym(1).declaration_list);
 }   break;
 
-#line 2650 "./glsl.g"
+#line 2699 "./glsl.g"
 
 case 306: {
     sym(1).declaration_list = makeAstNode< List<Declaration *> >(sym(1).declaration);
 }   break;
 
-#line 2657 "./glsl.g"
+#line 2706 "./glsl.g"
 
 case 307: {
     sym(1).declaration_list = makeAstNode< List<Declaration *> >(sym(1).declaration_list, sym(2).declaration);
 }   break;
 
-#line 2664 "./glsl.g"
+#line 2713 "./glsl.g"
 
 case 308: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 2671 "./glsl.g"
+#line 2720 "./glsl.g"
 
 case 309: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 2678 "./glsl.g"
+#line 2727 "./glsl.g"
 
 case 310: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 2685 "./glsl.g"
+#line 2734 "./glsl.g"
 
 case 311: {
     // ast(1) = new ...AST(...);
 }   break;
 
-#line 2692 "./glsl.g"
+#line 2741 "./glsl.g"
 
 case 312: {
     ast(1) = 0;
 }   break;
 
-#line 2700 "./glsl.g"
+#line 2749 "./glsl.g"
 
 } // end switch
 } // end Parser::reduce()
diff --git a/src/libs/glsl/glslparser.h b/src/libs/glsl/glslparser.h
index 69d8008bf18..544d9f6fd3d 100644
--- a/src/libs/glsl/glslparser.h
+++ b/src/libs/glsl/glslparser.h
@@ -51,7 +51,27 @@ public:
         List<Declaration *> *declaration_list;
         Expression *expression;
         List<Expression *> *expression_list;
+        Statement *statement;
+        List<Statement *> *statement_list;
+        Type *type;
+        StructType::Field *field;
+        List<StructType::Field *> *field_list;
         TranslationUnit *translation_unit;
+        FunctionIdentifier *function_identifier;
+        AST::Kind kind;
+        Type::Precision precision;
+        struct {
+            Statement *thenClause;
+            Statement *elseClause;
+        } ifstmt;
+        struct {
+            Expression *condition;
+            Expression *increment;
+        } forstmt;
+        struct {
+            FunctionIdentifier *id;
+            List<Expression *> *arguments;
+        } function;
         // ### ast nodes...
     };
 
@@ -65,6 +85,9 @@ private:
     Value &sym(int n) { return _symStack[_tos + n - 1]; }
     AST *&ast(int n) { return _symStack[_tos + n - 1].ast; }
     const std::string *&string(int n) { return _symStack[_tos + n - 1].string; }
+    Expression *&expression(int n) { return _symStack[_tos + n - 1].expression; }
+    Statement *&statement(int n) { return _symStack[_tos + n - 1].statement; }
+    Type *&type(int n) { return _symStack[_tos + n - 1].type; }
 
     inline int consumeToken() { return _index++; }
     inline const Token &tokenAt(int index) const { return _tokens.at(index); }
@@ -111,6 +134,13 @@ private:
         return node;
     }
 
+    Type *makeBasicType(int token, BasicType::Category category)
+    {
+        Type *type = new (_engine->pool()) BasicType(token, spell[token], category);
+        type->lineno = yyloc >= 0 ? (_tokens[yyloc].line + 1) : 0;
+        return type;
+    }
+
 private:
     Engine *_engine;
     int _tos;
-- 
GitLab