]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/preprocessor.cpp
Clear load ID when assigning to a component
[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=="tess_control")
93                 stage = Stage::TESS_CONTROL;
94         else if(token=="tess_eval")
95                 stage = Stage::TESS_EVAL;
96         else if(token=="geometry")
97                 stage = Stage::GEOMETRY;
98         else if(token=="fragment")
99                 stage = Stage::FRAGMENT;
100         else if(token=="compute")
101                 stage = Stage::COMPUTE;
102         else
103                 throw parse_error(tokenizer.get_location(), token, "stage identifier");
104         tokenizer.expect(")");
105
106         signal_stage_change.emit(stage);
107 }
108
109 void Preprocessor::preprocess_source()
110 {
111         tokenizer.expect("source");
112         tokenizer.expect("(");
113         unsigned source_index = lexical_cast<unsigned>(tokenizer.parse_token());
114         tokenizer.expect(",");
115         string filename = tokenizer.parse_token();
116         if(filename[0]!='"')
117                 throw parse_error(tokenizer.get_location(), filename, "a string literal");
118         filename = c_unescape(filename.substr(1, filename.size()-2));
119         tokenizer.expect(")");
120
121         signal_source.emit(source_index, filename);
122 }
123
124 } // namespace SL
125 } // namespace GL
126 } // namespace Msp