]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/parser.cpp
Slightly refactor layout qualifiers in the GLSL parser
[libs/gl.git] / source / glsl / parser.cpp
index eaf5706f25a6fd8b30935835efb32272943427e4..4b6bd7ed08992271f5ba73318a253b8a4ec2d6ab 100644 (file)
@@ -1,5 +1,6 @@
 #include <msp/strings/format.h>
 #include <msp/strings/regex.h>
+#include <msp/strings/utils.h>
 #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> 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<int>(token);
+}
+
 bool Parser::check(const string &token)
 {
        bool result = (tokenizer.peek_token()==token);
@@ -254,7 +278,7 @@ RefPtr<Statement> Parser::parse_statement()
 
 RefPtr<Import> 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<Layout> 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<Passthrough> Parser::parse_passthrough()
        RefPtr<Passthrough> 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();