]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/parser.cpp
Validate GLSL flow control
[libs/gl.git] / source / glsl / parser.cpp
index b4631daf6d1c4e5b3cafa638400bd94e9d157074..6a055c0cd3ebb718830e65175efa15aa3bf10ca1 100644 (file)
@@ -268,11 +268,19 @@ RefPtr<Statement> Parser::parse_global_declaration()
                if(is_interface_qualifier(token) && tokenizer.peek_token(1)==";")
                {
                        RefPtr<InterfaceLayout> iface_lo = create_node<InterfaceLayout>();
+                       iface_lo->layout.source = layout->source;
+                       iface_lo->layout.line = layout->line;
                        iface_lo->layout.qualifiers = layout->qualifiers;
                        iface_lo->interface = tokenizer.parse_token();
                        tokenizer.expect(";");
                        return iface_lo;
                }
+               else if(is_interface_qualifier(token) && tokenizer.peek_token(2)=="{")
+               {
+                       RefPtr<InterfaceBlock> iface = parse_interface_block();
+                       iface->layout = layout;
+                       return iface;
+               }
                else
                {
                        RefPtr<VariableDeclaration> var = parse_variable_declaration();
@@ -294,6 +302,8 @@ RefPtr<Statement> Parser::parse_global_declaration()
        }
        else if(is_qualifier(token))
                return parse_variable_declaration();
+       else if(token=="virtual")
+               return parse_function_declaration();
        else if(is_type(token))
        {
                if(tokenizer.peek_token(2)=="(")
@@ -387,9 +397,8 @@ RefPtr<Layout> Parser::parse_layout()
                if(token==")")
                        throw parse_error(tokenizer.get_location(), token, "a layout qualifier name");
 
-               layout->qualifiers.push_back(Layout::Qualifier());
+               layout->qualifiers.push_back(token);
                Layout::Qualifier &qual = layout->qualifiers.back();
-               qual.name = token;
 
                if((qual.has_value = check("=")))
                {
@@ -449,7 +458,7 @@ RefPtr<Expression> Parser::parse_expression(const Operator *outer_oper)
                                oper = i;
 
                bool lower_precedence = (oper && oper->type!=Operator::PREFIX && oper->precedence>=outer_precedence);
-               if(token==";" || token==")" || token=="]" || token=="," || lower_precedence)
+               if(token==";" || token==")" || token=="]" || token=="," || token==":" || lower_precedence)
                {
                        if(left)
                                return left;
@@ -483,6 +492,8 @@ RefPtr<Expression> Parser::parse_expression(const Operator *outer_oper)
                        }
                        else if(oper && oper->type==Operator::BINARY)
                                left = parse_binary(left, *oper);
+                       else if(oper && oper->type==Operator::TERNARY)
+                               left = parse_ternary(left, *oper);
                        else
                                throw parse_error(tokenizer.get_location(), token, "an operator");
                        left_var = 0;
@@ -492,10 +503,8 @@ RefPtr<Expression> Parser::parse_expression(const Operator *outer_oper)
                        if(token=="(")
                        {
                                tokenizer.parse_token();
-                               RefPtr<ParenthesizedExpression> parexpr = create_node<ParenthesizedExpression>();
-                               parexpr->expression = parse_expression();
+                               left = parse_expression();
                                tokenizer.expect(")");
-                               left = parexpr;
                        }
                        else if(isdigit(token[0]) || token=="true" || token=="false")
                                left = parse_literal();
@@ -547,21 +556,32 @@ RefPtr<BinaryExpression> Parser::parse_binary(const RefPtr<Expression> &left, co
        binary->left = left;
        binary->oper = &oper;
        tokenizer.expect(oper.token);
-       if(oper.token[0]=='[')
+       if(oper.token2[0])
        {
                binary->right = parse_expression();
-               tokenizer.expect("]");
+               tokenizer.expect(oper.token2);
        }
        else
                binary->right = parse_expression(&oper);
        return binary;
 }
 
+RefPtr<TernaryExpression> Parser::parse_ternary(const RefPtr<Expression> &cond, const Operator &oper)
+{
+       RefPtr<TernaryExpression> ternary = create_node<TernaryExpression>();
+       ternary->condition = cond;
+       ternary->oper = &oper;
+       tokenizer.expect("?");
+       ternary->true_expr = parse_expression(&oper);
+       tokenizer.expect(":");
+       ternary->false_expr = parse_expression(&oper);
+       return ternary;
+}
+
 RefPtr<FunctionCall> Parser::parse_function_call(const VariableReference &var)
 {
        RefPtr<FunctionCall> call = create_node<FunctionCall>();
        call->name = var.name;
-       call->constructor = is_type(call->name);
        call->oper = &Operator::get_operator("(", Operator::POSTFIX);
        tokenizer.expect("(");
        while(tokenizer.peek_token()!=")")
@@ -736,6 +756,7 @@ RefPtr<FunctionDeclaration> Parser::parse_function_declaration()
 {
        RefPtr<FunctionDeclaration> func = create_node<FunctionDeclaration>();
 
+       func->virtua = check("virtual");
        func->return_type = expect_type();
        func->name = expect_identifier();
        tokenizer.expect("(");
@@ -754,6 +775,8 @@ RefPtr<FunctionDeclaration> Parser::parse_function_declaration()
        }
        tokenizer.expect(")");
 
+       func->overrd = check("override");
+
        string token = tokenizer.peek_token();
        if(token=="{")
        {
@@ -776,7 +799,7 @@ RefPtr<InterfaceBlock> Parser::parse_interface_block()
        if(!is_interface_qualifier(iface->interface))
                throw parse_error(tokenizer.get_location(), iface->interface, "an interface qualifier");
 
-       iface->name = expect_identifier();
+       iface->block_name = expect_identifier();
        iface->members = new Block;
        parse_block(*iface->members, true, &Parser::parse_variable_declaration_with_layout);
        if(!check(";"))