#include <msp/strings/format.h>
#include <msp/strings/regex.h>
+#include <msp/strings/utils.h>
#include "glsl_error.h"
#include "parser.h"
{
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()
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);
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)
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();
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);
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;