X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fparser.cpp;h=5ffc2a9b023f284b2837990e06f7a8533955d5fc;hb=6288c42adde9ee7d39a47de51fa2856cf965dccc;hp=eee6212930f5dccabdac77b4a32467f91fb89727;hpb=9d798ac368bfd236a7632a3a15e51bd1112ea63d;p=libs%2Fgl.git diff --git a/source/glsl/parser.cpp b/source/glsl/parser.cpp index eee62129..5ffc2a9b 100644 --- a/source/glsl/parser.cpp +++ b/source/glsl/parser.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "glsl_error.h" #include "parser.h" @@ -17,7 +18,9 @@ Parser::Parser(): { tokenizer.signal_preprocess.connect(sigc::mem_fun(&preprocessor, &Preprocessor::preprocess)); preprocessor.signal_version.connect(sigc::mem_fun(this, &Parser::set_required_version)); + preprocessor.signal_source.connect(sigc::mem_fun(this, &Parser::source_reference)); preprocessor.signal_stage_change.connect(sigc::mem_fun(this, &Parser::stage_change)); + preprocessor.signal_line.connect(sigc::mem_fun(this, &Parser::line_change)); } Parser::~Parser() @@ -50,8 +53,9 @@ void Parser::parse_source(const string &name, unsigned index) delete module; module = new Module; cur_stage = &module->shared; + base_index = index; source_index = index; - module->source_map.set_name(source_index, name); + source_reference(1, name); tokenizer.begin(name, source); while(RefPtr statement = parse_global_declaration()) cur_stage->content.body.push_back(statement); @@ -59,7 +63,15 @@ void Parser::parse_source(const string &name, unsigned index) void Parser::set_required_version(const Version &ver) { - cur_stage->required_version = ver; + cur_stage->required_features.glsl_version = ver; +} + +void Parser::source_reference(unsigned index, const string &name) +{ + if(index<1) + throw invalid_shader_source(tokenizer.get_location(), "Invalid source reference"); + + module->source_map.set_name(base_index+index-1, name); } void Parser::stage_change(Stage::Type stage) @@ -76,6 +88,21 @@ void Parser::stage_change(Stage::Type stage) cur_stage = &module->stages.back(); } +void Parser::line_change(int index, unsigned line) +{ + if(index>0) + source_index = base_index+index-1; + else if(index==0) + source_index = 0; + else + index = source_index; + + string name = module->source_map.get_name(index); + if(name.empty()) + name = format("<%d>", index); + tokenizer.set_location(Location(name, line)); +} + string Parser::expect_type() { string token = tokenizer.parse_token(); @@ -92,6 +119,14 @@ string Parser::expect_identifier() return token; } +int Parser::expect_integer() +{ + string token = tokenizer.parse_token(); + if(!isnumrc(token)) + throw parse_error(tokenizer.get_location(), token, "an integer literal"); + return lexical_cast(token); +} + bool Parser::check(const string &token) { bool result = (tokenizer.peek_token()==token); @@ -289,10 +324,18 @@ RefPtr Parser::parse_layout() layout->qualifiers.push_back(Layout::Qualifier()); Layout::Qualifier &qual = layout->qualifiers.back(); - qual.identifier = token; + qual.name = token; - if(check("=")) - qual.value = tokenizer.parse_token(); + if((qual.has_value = check("="))) + { + if(qual.name=="constant_id" && tokenizer.peek_token()=="auto") + { + qual.value = -1; + tokenizer.parse_token(); + } + else + qual.value = expect_integer(); + } if(tokenizer.peek_token()==")") break; @@ -304,7 +347,8 @@ RefPtr Parser::parse_layout() return layout; } -void Parser::parse_block(Block &block, bool require_braces) +template +void Parser::parse_block(Block &block, bool require_braces, RefPtr (Parser::*parse_content)()) { bool have_braces = (require_braces || tokenizer.peek_token()=="{"); if(have_braces) @@ -313,10 +357,10 @@ void Parser::parse_block(Block &block, bool require_braces) if(have_braces) { while(tokenizer.peek_token()!="}") - block.body.push_back(parse_statement()); + block.body.push_back((this->*parse_content)()); } else - block.body.push_back(parse_statement()); + block.body.push_back((this->*parse_content)()); block.use_braces = (require_braces || block.body.size()!=1); @@ -451,7 +495,7 @@ RefPtr Parser::parse_struct_declaration() strct->line = tokenizer.get_location().line; strct->name = expect_identifier(); - parse_block(strct->members, true); + parse_block(strct->members, true, &Parser::parse_variable_declaration); tokenizer.expect(";"); declared_types.insert(strct->name); @@ -501,6 +545,18 @@ RefPtr Parser::parse_variable_declaration() return var; } +RefPtr Parser::parse_variable_declaration_with_layout() +{ + RefPtr layout; + if(tokenizer.peek_token()=="layout") + layout = parse_layout(); + + RefPtr var = parse_variable_declaration(); + var->layout = layout; + + return var; +} + RefPtr Parser::parse_function_declaration() { RefPtr func = new FunctionDeclaration; @@ -529,7 +585,7 @@ RefPtr Parser::parse_function_declaration() if(token=="{") { func->definition = func.get(); - parse_block(func->body, true); + parse_block(func->body, true, &Parser::parse_statement); } else if(token==";") tokenizer.parse_token(); @@ -550,7 +606,7 @@ RefPtr Parser::parse_interface_block() throw parse_error(tokenizer.get_location(), iface->interface, "an interface qualifier"); iface->name = expect_identifier(); - parse_block(iface->members, true); + parse_block(iface->members, true, &Parser::parse_variable_declaration_with_layout); if(!check(";")) { iface->instance_name = expect_identifier(); @@ -575,13 +631,13 @@ RefPtr Parser::parse_conditional() cond->condition = parse_expression(); tokenizer.expect(")"); - parse_block(cond->body, false); + parse_block(cond->body, false, &Parser::parse_statement); string token = tokenizer.peek_token(); if(token=="else") { tokenizer.parse_token(); - parse_block(cond->else_body, false); + parse_block(cond->else_body, false, &Parser::parse_statement); } return cond; @@ -614,7 +670,7 @@ RefPtr Parser::parse_for() loop->loop_expression = parse_expression(); tokenizer.expect(")"); - parse_block(loop->body, false); + parse_block(loop->body, false, &Parser::parse_statement); return loop; } @@ -629,7 +685,7 @@ RefPtr Parser::parse_while() loop->condition = parse_expression(); tokenizer.expect(")"); - parse_block(loop->body, false); + parse_block(loop->body, false, &Parser::parse_statement); return loop; }