X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fprogramparser.cpp;h=ddea96409dea4475e911e94fac01fda171451b57;hb=a0caabaed3aeb8947133d78986bfb4ae5ae3c893;hp=bf2d42daedbfd232dcc0dd194deb7c60ddf76625;hpb=73ce62f3b9c2bbfc1e655a9df343389a733dc795;p=libs%2Fgl.git diff --git a/source/programparser.cpp b/source/programparser.cpp index bf2d42da..ddea9640 100644 --- a/source/programparser.cpp +++ b/source/programparser.cpp @@ -58,11 +58,20 @@ ProgramParser::Operator ProgramParser::operators[] = { { 0 }, 18, NO_OPERATOR, LEFT_TO_RIGHT } }; +ProgramParser::ProgramParser(): + module(0) +{ } + +ProgramParser::~ProgramParser() +{ + delete module; +} + Module &ProgramParser::parse(const string &s) { source = s; - parse_source(main_module); - return main_module; + parse_source(); + return *module; } Module &ProgramParser::parse(IO::Base &io) @@ -74,35 +83,37 @@ Module &ProgramParser::parse(IO::Base &io) unsigned len = io.read(buffer, sizeof(buffer)); source.append(buffer, len); } - parse_source(main_module); - return main_module; + parse_source(); + return *module; } -void ProgramParser::parse_source(Module &module) +void ProgramParser::parse_source() { - cur_module = &module; + delete module; + module = new Module; + cur_stage = &module->shared; iter = source.begin(); - Context *cur_context = &module.global_context; while(1) { while(Node *statement = parse_global_declaration()) - cur_context->content.body.push_back(statement); - cur_context->present = !cur_context->content.body.empty(); + cur_stage->content.body.push_back(statement); parse_token(); string token = parse_token(); if(token.empty()) break; - else if(token=="global") - cur_context = &module.global_context; else if(token=="vertex") - cur_context = &module.vertex_context; + module->stages.push_back(VERTEX); else if(token=="geometry") - cur_context = &module.geometry_context; + module->stages.push_back(GEOMETRY); else if(token=="fragment") - cur_context = &module.fragment_context; + module->stages.push_back(FRAGMENT); else - throw runtime_error(format("Parse error at '%s': expected context identifier", token)); + throw runtime_error(format("Parse error at '%s': expected stage identifier", token)); + + if(cur_stage->type!=SHARED) + module->stages.back().previous = cur_stage; + cur_stage = &module->stages.back(); for(; (iter!=source.end() && *iter!='\n'); ++iter) ; } @@ -207,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=='/') @@ -310,7 +320,7 @@ bool ProgramParser::is_builtin_type(const string &token) bool ProgramParser::is_type(const string &token) { - return is_builtin_type(token) || cur_module->structs.count(token); + return is_builtin_type(token) || declared_types.count(token); } bool ProgramParser::is_identifier(const string &token) @@ -322,7 +332,9 @@ bool ProgramParser::is_identifier(const string &token) Node *ProgramParser::parse_global_declaration() { string token = peek_token(); - if(token=="layout") + if(token=="import") + return parse_import(); + else if(token=="layout") return parse_layout(); else if(token=="struct") return parse_struct_declaration(); @@ -355,6 +367,8 @@ Node *ProgramParser::parse_statement() return parse_conditional(); else if(token=="for") return parse_iteration(); + else if(token=="passthrough") + return parse_passthrough(); else if(token=="return") return parse_return(); else if(is_qualifier(token) || is_type(token)) @@ -371,6 +385,18 @@ Node *ProgramParser::parse_statement() throw runtime_error(format("Syntax error at '%s': expected a statement", token)); } +Import *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.release(); +} + Layout *ProgramParser::parse_layout() { expect("layout"); @@ -481,6 +507,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; @@ -496,12 +528,6 @@ 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)); } @@ -510,7 +536,7 @@ Expression *ProgramParser::parse_expression(unsigned precedence) BinaryExpression *ProgramParser::parse_binary(Expression *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=="[") @@ -521,7 +547,6 @@ 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(); } @@ -550,7 +575,7 @@ StructDeclaration *ProgramParser::parse_struct_declaration() parse_block(strct->members, true); expect(";"); - cur_module->structs[strct->name] = strct.get(); + declared_types.insert(strct->name); return strct.release(); } @@ -601,12 +626,23 @@ FunctionDeclaration *ProgramParser::parse_function_declaration() 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.release()); + } + expect(")"); string token = peek_token(); if(token=="{") { - func->definition = true; + func->definition = func.get(); parse_block(func->body, true); } else if(token==";") @@ -617,22 +653,6 @@ FunctionDeclaration *ProgramParser::parse_function_declaration() return func.release(); } -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 iface = new InterfaceBlock; @@ -643,7 +663,16 @@ 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(); } @@ -693,11 +722,26 @@ Iteration *ProgramParser::parse_iteration() return loop.release(); } +Passthrough *ProgramParser::parse_passthrough() +{ + expect("passthrough"); + RefPtr pass = new Passthrough; + if(cur_stage->type==GEOMETRY) + { + expect("["); + pass->subscript = parse_expression(); + expect("]"); + } + expect(";"); + return pass.release(); +} + Return *ProgramParser::parse_return() { expect("return"); RefPtr ret = new Return; - ret->expression = parse_expression(); + if(peek_token()!=";") + ret->expression = parse_expression(); expect(";"); return ret.release(); }