X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fparser.cpp;h=0512c10b235ea6d384d17e319d9a4a5ce3e5c7b2;hb=91e65bc9e24a6889995081035f6f6f0a78a6c20e;hp=fd782648083bdb05a1aa700ca65d4ab8f15aa926;hpb=041ba4b1acd55337239c5ce24cc310118c621206;p=libs%2Fgl.git diff --git a/source/glsl/parser.cpp b/source/glsl/parser.cpp index fd782648..0512c10b 100644 --- a/source/glsl/parser.cpp +++ b/source/glsl/parser.cpp @@ -72,6 +72,7 @@ void Parser::parse_source(const string &name, int index) declared_types.insert("void"); declared_types.insert("bool"); declared_types.insert("int"); + declared_types.insert("uint"); declared_types.insert("float"); } @@ -268,11 +269,19 @@ RefPtr Parser::parse_global_declaration() if(is_interface_qualifier(token) && tokenizer.peek_token(1)==";") { RefPtr iface_lo = create_node(); + 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 iface = parse_interface_block(); + iface->layout = layout; + return iface; + } else { RefPtr var = parse_variable_declaration(); @@ -294,6 +303,8 @@ RefPtr 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 +398,8 @@ RefPtr 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("="))) { @@ -434,8 +444,9 @@ void Parser::parse_block(Block &block, bool require_braces, RefPtr (Parser::* tokenizer.expect("}"); } -RefPtr Parser::parse_expression(unsigned precedence) +RefPtr Parser::parse_expression(const Operator *outer_oper) { + unsigned outer_precedence = (outer_oper ? outer_oper->precedence+(outer_oper->assoc==Operator::RIGHT_TO_LEFT) : 20); RefPtr left; VariableReference *left_var = 0; while(1) @@ -447,8 +458,8 @@ RefPtr Parser::parse_expression(unsigned precedence) if(token==i->token && (!left || i->type!=Operator::PREFIX) && (left || i->type!=Operator::POSTFIX)) oper = i; - bool lower_precedence = (oper && oper->type!=Operator::PREFIX && precedence && oper->precedence>=precedence); - if(token==";" || token==")" || token=="]" || token=="," || lower_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; @@ -482,6 +493,8 @@ RefPtr 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; @@ -491,10 +504,8 @@ RefPtr Parser::parse_expression(unsigned precedence) if(token=="(") { tokenizer.parse_token(); - RefPtr parexpr = create_node(); - parexpr->expression = parse_expression(); + left = parse_expression(); tokenizer.expect(")"); - left = parexpr; } else if(isdigit(token[0]) || token=="true" || token=="false") left = parse_literal(); @@ -510,7 +521,7 @@ RefPtr Parser::parse_expression(unsigned precedence) RefPtr unary = create_node(); unary->oper = oper; tokenizer.parse_token(); - unary->expression = parse_expression(oper->precedence); + unary->expression = parse_expression(oper); left = unary; } else @@ -526,10 +537,14 @@ RefPtr Parser::parse_literal() if(isdigit(literal->token[0])) { // TODO have the tokenizer return the type of the token - if(isnumrc(literal->token)) - literal->value = lexical_cast(literal->token); - else + if(literal->token.back()=='u') + literal->value = lexical_cast(literal->token.substr(0, literal->token.size()-1)); + else if(literal->token.back()=='f') + literal->value = lexical_cast(literal->token.substr(0, literal->token.size()-1)); + else if(literal->token.find('.')!=string::npos) literal->value = lexical_cast(literal->token); + else + literal->value = lexical_cast(literal->token); } else if(literal->token=="true" || literal->token=="false") literal->value = (literal->token=="true"); @@ -546,21 +561,32 @@ RefPtr Parser::parse_binary(const RefPtr &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.precedence+(oper.assoc==Operator::RIGHT_TO_LEFT)); + binary->right = parse_expression(&oper); return binary; } +RefPtr Parser::parse_ternary(const RefPtr &cond, const Operator &oper) +{ + RefPtr ternary = create_node(); + 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 Parser::parse_function_call(const VariableReference &var) { RefPtr call = create_node(); call->name = var.name; - call->constructor = is_type(call->name); call->oper = &Operator::get_operator("(", Operator::POSTFIX); tokenizer.expect("("); while(tokenizer.peek_token()!=")") @@ -735,6 +761,7 @@ RefPtr Parser::parse_function_declaration() { RefPtr func = create_node(); + func->virtua = check("virtual"); func->return_type = expect_type(); func->name = expect_identifier(); tokenizer.expect("("); @@ -753,6 +780,8 @@ RefPtr Parser::parse_function_declaration() } tokenizer.expect(")"); + func->overrd = check("override"); + string token = tokenizer.peek_token(); if(token=="{") { @@ -775,7 +804,7 @@ RefPtr 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(";"))