--- /dev/null
+#include "glsl_error.h"
+#include "preprocessor.h"
+#include "tokenizer.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+namespace SL {
+
+Preprocessor::Preprocessor(Tokenizer &t):
+ tokenizer(t)
+{ }
+
+void Preprocessor::preprocess()
+{
+ tokenizer.expect("#");
+
+ string token = tokenizer.peek_token();
+ if(token=="pragma")
+ preprocess_pragma();
+ else if(token=="version")
+ preprocess_version();
+ else if(token=="define" || token=="undef" || token=="if" || token=="ifdef" || token=="ifndef" || token=="else" ||
+ token=="elif" || token=="endif" || token=="error" || token=="extension" || token=="line")
+ throw invalid_shader_source(tokenizer.get_location(), "Unsupported preprocessor directive '%s'", token);
+ else if(!token.empty())
+ throw parse_error(tokenizer.get_location(), token, "a preprocessor directive");
+}
+
+void Preprocessor::preprocess_version()
+{
+ tokenizer.expect("version");
+ string token = tokenizer.parse_token();
+ unsigned version = lexical_cast<unsigned>(token);
+ signal_version.emit(Version(version/100, version%100));
+
+ token = tokenizer.parse_token();
+ if(!token.empty())
+ throw parse_error(tokenizer.get_location(), token, "end of line");
+}
+
+void Preprocessor::preprocess_pragma()
+{
+ tokenizer.expect("pragma");
+ string token = tokenizer.parse_token();
+ if(token=="MSP")
+ preprocess_pragma_msp();
+}
+
+void Preprocessor::preprocess_pragma_msp()
+{
+ string token = tokenizer.peek_token();
+ if(token=="stage")
+ preprocess_stage();
+ else
+ throw invalid_shader_source(tokenizer.get_location(), "Unrecognized MSP pragma '%s'", token);
+
+ token = tokenizer.parse_token();
+ if(!token.empty())
+ throw parse_error(tokenizer.get_location(), token, "end of line");
+}
+
+void Preprocessor::preprocess_stage()
+{
+ tokenizer.expect("stage");
+ tokenizer.expect("(");
+ string token = tokenizer.parse_token();
+ StageType stage = SHARED;
+ if(token=="vertex")
+ stage = VERTEX;
+ else if(token=="geometry")
+ stage = GEOMETRY;
+ else if(token=="fragment")
+ stage = FRAGMENT;
+ else
+ throw parse_error(tokenizer.get_location(), token, "stage identifier");
+ tokenizer.expect(")");
+
+ signal_stage_change.emit(stage);
+}
+
+} // namespace SL
+} // namespace GL
+} // namespace Msp