]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/preprocessor.cpp
Redesign framebuffer attachment management
[libs/gl.git] / source / glsl / preprocessor.cpp
1 #include <msp/strings/utils.h>
2 #include "glsl_error.h"
3 #include "preprocessor.h"
4 #include "tokenizer.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace GL {
10 namespace SL {
11
12 Preprocessor::Preprocessor(Tokenizer &t):
13         tokenizer(t)
14 { }
15
16 void Preprocessor::preprocess()
17 {
18         string token = tokenizer.peek_token();
19         if(token=="pragma")
20                 preprocess_pragma();
21         else if(token=="version")
22                 preprocess_version();
23         else if(token=="line")
24                 preprocess_line();
25         else if(token=="define" || token=="undef" || token=="if" || token=="ifdef" || token=="ifndef" || token=="else" ||
26                 token=="elif" || token=="endif" || token=="error" || token=="extension")
27                 throw invalid_shader_source(tokenizer.get_location(), "Unsupported preprocessor directive '%s'", token);
28         else if(!token.empty())
29                 throw parse_error(tokenizer.get_location(), token, "a preprocessor directive");
30 }
31
32 void Preprocessor::preprocess_version()
33 {
34         tokenizer.expect("version");
35         string token = tokenizer.parse_token();
36         unsigned version = lexical_cast<unsigned>(token);
37         signal_version.emit(Version(version/100, version%100));
38
39         token = tokenizer.parse_token();
40         if(!token.empty())
41                 throw parse_error(tokenizer.get_location(), token, "end of line");
42 }
43
44 void Preprocessor::preprocess_line()
45 {
46         tokenizer.expect("line");
47         unsigned line_number = lexical_cast<unsigned>(tokenizer.parse_token());
48
49         int source_index = -1;
50         string token = tokenizer.parse_token();
51         if(!token.empty())
52                 source_index = lexical_cast<unsigned>(token);
53
54         token = tokenizer.parse_token();
55         if(!token.empty())
56                 throw parse_error(tokenizer.get_location(), token, "end of line");
57
58         signal_line.emit(source_index, line_number);
59 }
60
61 void Preprocessor::preprocess_pragma()
62 {
63         tokenizer.expect("pragma");
64         string token = tokenizer.parse_token();
65         if(token=="MSP")
66                 preprocess_pragma_msp();
67 }
68
69 void Preprocessor::preprocess_pragma_msp()
70 {
71         string token = tokenizer.peek_token();
72         if(token=="stage")
73                 preprocess_stage();
74         else if(token=="source")
75                 preprocess_source();
76         else
77                 throw invalid_shader_source(tokenizer.get_location(), "Unrecognized MSP pragma '%s'", token);
78
79         token = tokenizer.parse_token();
80         if(!token.empty())
81                 throw parse_error(tokenizer.get_location(), token, "end of line");
82 }
83
84 void Preprocessor::preprocess_stage()
85 {
86         tokenizer.expect("stage");
87         tokenizer.expect("(");
88         string token = tokenizer.parse_token();
89         Stage::Type stage = Stage::SHARED;
90         if(token=="vertex")
91                 stage = Stage::VERTEX;
92         else if(token=="geometry")
93                 stage = Stage::GEOMETRY;
94         else if(token=="fragment")
95                 stage = Stage::FRAGMENT;
96         else
97                 throw parse_error(tokenizer.get_location(), token, "stage identifier");
98         tokenizer.expect(")");
99
100         signal_stage_change.emit(stage);
101 }
102
103 void Preprocessor::preprocess_source()
104 {
105         tokenizer.expect("source");
106         tokenizer.expect("(");
107         unsigned source_index = lexical_cast<unsigned>(tokenizer.parse_token());
108         tokenizer.expect(",");
109         string filename = tokenizer.parse_token();
110         if(filename[0]!='"')
111                 throw parse_error(tokenizer.get_location(), filename, "a string literal");
112         filename = c_unescape(filename.substr(1, filename.size()-2));
113         tokenizer.expect(")");
114
115         signal_source.emit(source_index, filename);
116 }
117
118 } // namespace SL
119 } // namespace GL
120 } // namespace Msp