X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fprogramparser.cpp;h=bf5d5dffb103fea9b554afa0940f607d12b21ac4;hp=16299d20cf157f8281fc2face34d55a21712eee1;hb=4fe225bf15048fcb7a678370f87d09f2de37031a;hpb=a29cc14162e911b36d18d1d1896216697c7dc0c1 diff --git a/source/programparser.cpp b/source/programparser.cpp index 16299d20..bf5d5dff 100644 --- a/source/programparser.cpp +++ b/source/programparser.cpp @@ -95,7 +95,7 @@ void ProgramParser::parse_source() iter = source.begin(); while(1) { - while(Node *statement = parse_global_declaration()) + while(RefPtr statement = parse_global_declaration()) cur_stage->content.body.push_back(statement); parse_token(); @@ -218,7 +218,6 @@ bool ProgramParser::skip_comment_and_whitespace() unsigned slashes = 0; while(iter!=source.end()) { - //IO::print("%d '%c'\n", comment, *iter); if(comment==0) { if(*iter=='/') @@ -330,11 +329,30 @@ bool ProgramParser::is_identifier(const string &token) return re.match(token); } -Node *ProgramParser::parse_global_declaration() +RefPtr ProgramParser::parse_global_declaration() { string token = peek_token(); - if(token=="layout") - return parse_layout(); + if(token=="import") + return parse_import(); + else if(token=="layout") + { + RefPtr layout = parse_layout(); + token = peek_token(); + if(is_interface_qualifier(token) && peek_token(1)==";") + { + RefPtr iface_lo = new InterfaceLayout; + iface_lo->layout.qualifiers = layout->qualifiers; + iface_lo->interface = parse_token(); + expect(";"); + return iface_lo; + } + else + { + RefPtr var = parse_variable_declaration(); + var->layout = layout; + return var; + } + } else if(token=="struct") return parse_struct_declaration(); else if(is_sampling_qualifier(token) || token=="const") @@ -359,7 +377,7 @@ Node *ProgramParser::parse_global_declaration() throw runtime_error(format("Syntax error at '%s': expected a global declaration", token)); } -Node *ProgramParser::parse_statement() +RefPtr ProgramParser::parse_statement() { string token = peek_token(); if(token=="if") @@ -370,6 +388,14 @@ Node *ProgramParser::parse_statement() return parse_passthrough(); else if(token=="return") return parse_return(); + else if(token=="break" || token=="continue" || token=="discard") + { + RefPtr jump = new Jump; + jump->keyword = parse_token(); + expect(";"); + + return jump; + } else if(is_qualifier(token) || is_type(token)) return parse_variable_declaration(); else if(!token.empty()) @@ -378,13 +404,25 @@ Node *ProgramParser::parse_statement() expr->expression = parse_expression(); expect(";"); - return expr.release(); + return expr; } else throw runtime_error(format("Syntax error at '%s': expected a statement", token)); } -Layout *ProgramParser::parse_layout() +RefPtr ProgramParser::parse_import() +{ + if(cur_stage->type!=SHARED) + throw runtime_error("Imports are only allowed in the shared section"); + + expect("import"); + RefPtr import = new Import; + import->module = parse_token(); + expect(";"); + return import; +} + +RefPtr ProgramParser::parse_layout() { expect("layout"); expect("("); @@ -408,10 +446,8 @@ Layout *ProgramParser::parse_layout() expect(","); } expect(")"); - layout->interface = parse_token(); - expect(";"); - return layout.release(); + return layout; } void ProgramParser::parse_block(Block &block, bool require_braces) @@ -434,7 +470,7 @@ void ProgramParser::parse_block(Block &block, bool require_braces) expect("}"); } -Expression *ProgramParser::parse_expression(unsigned precedence) +RefPtr ProgramParser::parse_expression(unsigned precedence) { RefPtr left; VariableReference *left_var = 0; @@ -450,7 +486,7 @@ Expression *ProgramParser::parse_expression(unsigned precedence) if(token==";" || token==")" || token=="]" || token=="," || (oper && precedence && oper->precedence>=precedence)) { if(left) - return left.release(); + return left; else throw runtime_error(format("Parse error at '%s': expected an expression", token)); } @@ -460,12 +496,12 @@ Expression *ProgramParser::parse_expression(unsigned precedence) { if(!left_var) throw runtime_error(format("Parse error at '%s': function name must be an identifier", token)); - left = parse_function_call(left_var); + left = parse_function_call(*left_var); } else if(token==".") { RefPtr memacc = new MemberAccess; - memacc->left = left.release(); + memacc->left = left; parse_token(); memacc->member = expect_identifier(); left = memacc; @@ -475,11 +511,11 @@ Expression *ProgramParser::parse_expression(unsigned precedence) RefPtr unary = new UnaryExpression; unary->oper = parse_token(); unary->prefix = false; - unary->expression = left.release(); + unary->expression = left; left = unary; } else if(oper && oper->type==BINARY) - left = parse_binary(left.release(), oper); + left = parse_binary(left, oper); else throw runtime_error(format("Parse error at '%s': expected an operator", token)); left_var = 0; @@ -494,6 +530,12 @@ Expression *ProgramParser::parse_expression(unsigned precedence) expect(")"); left = parexpr; } + else if(isdigit(token[0]) || token=="true" || token=="false") + { + RefPtr literal = new Literal; + literal->token = parse_token(); + left = literal; + } else if(is_identifier(token)) { RefPtr var = new VariableReference; @@ -509,21 +551,15 @@ Expression *ProgramParser::parse_expression(unsigned precedence) unary->expression = parse_expression(oper->precedence); left = unary; } - else if(isdigit(token[0])) - { - RefPtr literal = new Literal; - literal->token = parse_token(); - left = literal; - } else throw runtime_error(format("Parse error at '%s': expected an expression", token)); } } } -BinaryExpression *ProgramParser::parse_binary(Expression *left, const Operator *oper) +RefPtr ProgramParser::parse_binary(const RefPtr &left, const Operator *oper) { - RefPtr binary = new BinaryExpression; + RefPtr binary = (oper->precedence==16 ? new Assignment : new BinaryExpression); binary->left = left; binary->oper = parse_token(); if(binary->oper=="[") @@ -534,14 +570,13 @@ BinaryExpression *ProgramParser::parse_binary(Expression *left, const Operator * } else binary->right = parse_expression(oper->precedence+(oper->assoc==RIGHT_TO_LEFT)); - binary->assignment = (oper->precedence==16); - return binary.release(); + return binary; } -FunctionCall *ProgramParser::parse_function_call(VariableReference *var) +RefPtr ProgramParser::parse_function_call(const VariableReference &var) { RefPtr call = new FunctionCall; - call->name = var->name; + call->name = var.name; call->constructor = is_type(call->name); expect("("); while(peek_token()!=")") @@ -551,10 +586,10 @@ FunctionCall *ProgramParser::parse_function_call(VariableReference *var) call->arguments.push_back(parse_expression()); } expect(")"); - return call.release(); + return call; } -StructDeclaration *ProgramParser::parse_struct_declaration() +RefPtr ProgramParser::parse_struct_declaration() { expect("struct"); RefPtr strct = new StructDeclaration; @@ -564,10 +599,10 @@ StructDeclaration *ProgramParser::parse_struct_declaration() expect(";"); declared_types.insert(strct->name); - return strct.release(); + return strct; } -VariableDeclaration *ProgramParser::parse_variable_declaration() +RefPtr ProgramParser::parse_variable_declaration() { RefPtr var = new VariableDeclaration; @@ -605,21 +640,32 @@ VariableDeclaration *ProgramParser::parse_variable_declaration() var->init_expression = parse_expression(); expect(";"); - return var.release(); + return var; } -FunctionDeclaration *ProgramParser::parse_function_declaration() +RefPtr ProgramParser::parse_function_declaration() { RefPtr func = new FunctionDeclaration; func->return_type = expect_type(); func->name = expect_identifier(); - parse_function_parameter_list(*func); + expect("("); + while(peek_token()!=")") + { + if(!func->parameters.empty()) + expect(","); + + RefPtr var = new VariableDeclaration; + var->type = expect_type(); + var->name = expect_identifier(); + func->parameters.push_back(var); + } + expect(")"); string token = peek_token(); if(token=="{") { - func->definition = true; + func->definition = func.get(); parse_block(func->body, true); } else if(token==";") @@ -627,26 +673,10 @@ FunctionDeclaration *ProgramParser::parse_function_declaration() else throw runtime_error(format("Parse error at '%s': expected '{' or ';'", token)); - return func.release(); + return func; } -void ProgramParser::parse_function_parameter_list(FunctionDeclaration &func) -{ - expect("("); - while(peek_token()!=")") - { - if(!func.parameters.empty()) - expect(","); - - RefPtr var = new VariableDeclaration; - var->type = expect_type(); - var->name = expect_identifier(); - func.parameters.push_back(var.release()); - } - expect(")"); -} - -InterfaceBlock *ProgramParser::parse_interface_block() +RefPtr ProgramParser::parse_interface_block() { RefPtr iface = new InterfaceBlock; @@ -656,12 +686,21 @@ InterfaceBlock *ProgramParser::parse_interface_block() iface->name = expect_identifier(); parse_block(iface->members, true); - expect(";"); + if(!check(";")) + { + iface->instance_name = expect_identifier(); + if(check("[")) + { + iface->array = true; + expect("]"); + } + expect(";"); + } - return iface.release(); + return iface; } -Conditional *ProgramParser::parse_conditional() +RefPtr ProgramParser::parse_conditional() { expect("if"); expect("("); @@ -678,10 +717,10 @@ Conditional *ProgramParser::parse_conditional() parse_block(cond->else_body, false); } - return cond.release(); + return cond; } -Iteration *ProgramParser::parse_iteration() +RefPtr ProgramParser::parse_iteration() { expect("for"); expect("("); @@ -694,7 +733,7 @@ Iteration *ProgramParser::parse_iteration() RefPtr expr = new ExpressionStatement; expr->expression = parse_expression(); expect(";"); - loop->init_statement = expr.release(); + loop->init_statement = expr; } loop->condition = parse_expression(); expect(";"); @@ -703,10 +742,10 @@ Iteration *ProgramParser::parse_iteration() parse_block(loop->body, false); - return loop.release(); + return loop; } -Passthrough *ProgramParser::parse_passthrough() +RefPtr ProgramParser::parse_passthrough() { expect("passthrough"); RefPtr pass = new Passthrough; @@ -717,16 +756,17 @@ Passthrough *ProgramParser::parse_passthrough() expect("]"); } expect(";"); - return pass.release(); + return pass; } -Return *ProgramParser::parse_return() +RefPtr ProgramParser::parse_return() { expect("return"); RefPtr ret = new Return; - ret->expression = parse_expression(); + if(peek_token()!=";") + ret->expression = parse_expression(); expect(";"); - return ret.release(); + return ret; } } // namespace GL