X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fparser.cpp;h=4b6bd7ed08992271f5ba73318a253b8a4ec2d6ab;hb=ffdb126a55467245da08a9e6f5669f86e1899bb0;hp=eaf5706f25a6fd8b30935835efb32272943427e4;hpb=d3ceb2186dc79130508093b3d0c944771a53534f;p=libs%2Fgl.git diff --git a/source/glsl/parser.cpp b/source/glsl/parser.cpp index eaf5706f..4b6bd7ed 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() @@ -28,41 +31,31 @@ Parser::~Parser() Module &Parser::parse(const string &s, const string &n, unsigned i) { source = s; - source_index = i; - parse_source(n); + parse_source(n, i); return *module; } Module &Parser::parse(IO::Base &io, const string &n, unsigned i) { source = string(); - source_index = i; while(!io.eof()) { char buffer[4096]; unsigned len = io.read(buffer, sizeof(buffer)); source.append(buffer, len); } - parse_source(n); + parse_source(n, i); return *module; } -void Parser::parse_source(const string &name) +void Parser::parse_source(const string &name, unsigned index) { - while(1) - { - string::size_type slashes = source.find("//////"); - if(slashes==string::npos) - break; - - string::size_type newline = source.find('\n', slashes); - string pragma = format("#pragma MSP stage(%s)", source.substr(slashes+6, newline-slashes-6)); - source.replace(slashes, newline-slashes, pragma); - } - delete module; module = new Module; cur_stage = &module->shared; + base_index = index; + source_index = index; + source_reference(1, name); tokenizer.begin(name, source); while(RefPtr statement = parse_global_declaration()) cur_stage->content.body.push_back(statement); @@ -70,23 +63,46 @@ void Parser::parse_source(const string &name) 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(StageType stage) +void Parser::stage_change(Stage::Type stage) { if(!allow_stage_change) throw invalid_shader_source(tokenizer.get_location(), "Changing stage not allowed here"); else if(stage<=cur_stage->type) - throw invalid_shader_source(tokenizer.get_location(), "Stage '%s' not allowed here", stage); + throw invalid_shader_source(tokenizer.get_location(), "Stage '%s' not allowed here", Stage::get_stage_name(stage)); module->stages.push_back(stage); - if(cur_stage->type!=SHARED) + if(cur_stage->type!=Stage::SHARED) module->stages.back().previous = cur_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(); @@ -103,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); @@ -254,7 +278,7 @@ RefPtr Parser::parse_statement() RefPtr Parser::parse_import() { - if(cur_stage->type!=SHARED) + if(cur_stage->type!=Stage::SHARED) throw invalid_shader_source(tokenizer.get_location(), "Imports are only allowed in the shared section"); tokenizer.expect("import"); @@ -300,10 +324,10 @@ 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("="))) + qual.value = expect_integer(); if(tokenizer.peek_token()==")") break; @@ -651,7 +675,7 @@ RefPtr Parser::parse_passthrough() RefPtr pass = new Passthrough; pass->source = source_index; pass->line = tokenizer.get_location().line; - if(cur_stage->type==GEOMETRY) + if(cur_stage->type==Stage::GEOMETRY) { tokenizer.expect("["); pass->subscript = parse_expression();