]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/parser.cpp
Add GLSL keywords for overriding functions
[libs/gl.git] / source / glsl / parser.cpp
index c9a812ddbd62f8c45184d565186404b33541f410..31f9fcb65cc7ffe4da48cacd8cc41e0c7787dba5 100644 (file)
@@ -294,6 +294,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)=="(")
@@ -434,8 +436,9 @@ void Parser::parse_block(Block &block, bool require_braces, RefPtr<T> (Parser::*
                tokenizer.expect("}");
 }
 
-RefPtr<Expression> Parser::parse_expression(unsigned precedence)
+RefPtr<Expression> Parser::parse_expression(const Operator *outer_oper)
 {
+       unsigned outer_precedence = (outer_oper ? outer_oper->precedence+(outer_oper->assoc==Operator::RIGHT_TO_LEFT) : 20);
        RefPtr<Expression> left;
        VariableReference *left_var = 0;
        while(1)
@@ -447,7 +450,8 @@ RefPtr<Expression> Parser::parse_expression(unsigned precedence)
                        if(token==i->token && (!left || i->type!=Operator::PREFIX) && (left || i->type!=Operator::POSTFIX))
                                oper = i;
 
-               if(token==";" || token==")" || token=="]" || token=="," || (oper && precedence && oper->precedence>=precedence))
+               bool lower_precedence = (oper && oper->type!=Operator::PREFIX && oper->precedence>=outer_precedence);
+               if(token==";" || token==")" || token=="]" || token=="," || token==":" || lower_precedence)
                {
                        if(left)
                                return left;
@@ -481,6 +485,8 @@ RefPtr<Expression> Parser::parse_expression(unsigned precedence)
                        }
                        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;
@@ -496,11 +502,7 @@ RefPtr<Expression> Parser::parse_expression(unsigned precedence)
                                left = parexpr;
                        }
                        else if(isdigit(token[0]) || token=="true" || token=="false")
-                       {
-                               RefPtr<Literal> literal = new Literal;
-                               literal->token = tokenizer.parse_token();
-                               left = literal;
-                       }
+                               left = parse_literal();
                        else if(is_identifier(token))
                        {
                                RefPtr<VariableReference> var = create_node<VariableReference>();
@@ -513,7 +515,7 @@ RefPtr<Expression> Parser::parse_expression(unsigned precedence)
                                RefPtr<UnaryExpression> unary = create_node<UnaryExpression>();
                                unary->oper = oper;
                                tokenizer.parse_token();
-                               unary->expression = parse_expression(oper->precedence);
+                               unary->expression = parse_expression(oper);
                                left = unary;
                        }
                        else
@@ -522,6 +524,26 @@ RefPtr<Expression> Parser::parse_expression(unsigned precedence)
        }
 }
 
+RefPtr<Literal> Parser::parse_literal()
+{
+       RefPtr<Literal> literal = create_node<Literal>();
+       literal->token = tokenizer.parse_token();
+       if(isdigit(literal->token[0]))
+       {
+               // TODO have the tokenizer return the type of the token
+               if(isnumrc(literal->token))
+                       literal->value = lexical_cast<int>(literal->token);
+               else
+                       literal->value = lexical_cast<float>(literal->token);
+       }
+       else if(literal->token=="true" || literal->token=="false")
+               literal->value = (literal->token=="true");
+       else
+               throw parse_error(tokenizer.get_location(), literal->token, "a literal");
+
+       return literal;
+}
+
 RefPtr<BinaryExpression> Parser::parse_binary(const RefPtr<Expression> &left, const Operator &oper)
 {
        RefPtr<BinaryExpression> binary = (oper.precedence==16 ?
@@ -535,10 +557,22 @@ RefPtr<BinaryExpression> Parser::parse_binary(const RefPtr<Expression> &left, co
                tokenizer.expect("]");
        }
        else
-               binary->right = parse_expression(oper.precedence+(oper.assoc==Operator::RIGHT_TO_LEFT));
+               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>();
@@ -718,6 +752,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("(");
@@ -736,6 +771,8 @@ RefPtr<FunctionDeclaration> Parser::parse_function_declaration()
        }
        tokenizer.expect(")");
 
+       func->overrd = check("override");
+
        string token = tokenizer.peek_token();
        if(token=="{")
        {
@@ -759,7 +796,8 @@ RefPtr<InterfaceBlock> Parser::parse_interface_block()
                throw parse_error(tokenizer.get_location(), iface->interface, "an interface qualifier");
 
        iface->name = expect_identifier();
-       parse_block(iface->members, true, &Parser::parse_variable_declaration_with_layout);
+       iface->members = new Block;
+       parse_block(*iface->members, true, &Parser::parse_variable_declaration_with_layout);
        if(!check(";"))
        {
                iface->instance_name = expect_identifier();