1 #include <msp/strings/format.h>
2 #include <msp/strings/regex.h>
3 #include "glsl_error.h"
15 preprocessor(tokenizer),
18 tokenizer.signal_preprocess.connect(sigc::mem_fun(&preprocessor, &Preprocessor::preprocess));
19 preprocessor.signal_version.connect(sigc::mem_fun(this, &Parser::set_required_version));
20 preprocessor.signal_stage_change.connect(sigc::mem_fun(this, &Parser::stage_change));
28 Module &Parser::parse(const string &s, const string &n, unsigned i)
36 Module &Parser::parse(IO::Base &io, const string &n, unsigned i)
43 unsigned len = io.read(buffer, sizeof(buffer));
44 source.append(buffer, len);
50 void Parser::parse_source(const string &name)
54 cur_stage = &module->shared;
55 tokenizer.begin(name, source);
56 while(RefPtr<Statement> statement = parse_global_declaration())
57 cur_stage->content.body.push_back(statement);
60 void Parser::set_required_version(const Version &ver)
62 cur_stage->required_version = ver;
65 void Parser::stage_change(Stage::Type stage)
67 if(!allow_stage_change)
68 throw invalid_shader_source(tokenizer.get_location(), "Changing stage not allowed here");
69 else if(stage<=cur_stage->type)
70 throw invalid_shader_source(tokenizer.get_location(), "Stage '%s' not allowed here", Stage::get_stage_name(stage));
72 module->stages.push_back(stage);
74 if(cur_stage->type!=Stage::SHARED)
75 module->stages.back().previous = cur_stage;
76 cur_stage = &module->stages.back();
79 string Parser::expect_type()
81 string token = tokenizer.parse_token();
83 throw parse_error(tokenizer.get_location(), token, "a type");
87 string Parser::expect_identifier()
89 string token = tokenizer.parse_token();
90 if(!is_identifier(token))
91 throw parse_error(tokenizer.get_location(), token, "an identifier");
95 bool Parser::check(const string &token)
97 bool result = (tokenizer.peek_token()==token);
99 tokenizer.parse_token();
103 bool Parser::is_interface_qualifier(const string &token)
105 return (token=="uniform" || token=="in" || token=="out");
108 bool Parser::is_sampling_qualifier(const string &token)
110 return (token=="centroid" || token=="sample");
113 bool Parser::is_interpolation_qualifier(const string &token)
115 return (token=="smooth" || token=="flat" || token=="noperspective");
118 bool Parser::is_precision_qualifier(const string &token)
120 return (token=="highp" || token=="mediump" || token=="lowp");
123 bool Parser::is_qualifier(const string &token)
125 return (token=="const" ||
126 is_interface_qualifier(token) ||
127 is_sampling_qualifier(token) ||
128 is_interpolation_qualifier(token) ||
129 is_precision_qualifier(token));
132 bool Parser::is_builtin_type(const string &token)
134 static Regex re("^(void|float|int|bool|[ib]?vec[234]|mat[234](x[234])?|sampler((1D|2D|Cube)(Array)?(Shadow)?|3D))$");
135 return re.match(token);
138 bool Parser::is_type(const string &token)
140 return is_builtin_type(token) || declared_types.count(token);
143 bool Parser::is_identifier(const string &token)
145 static Regex re("^[a-zA-Z_][a-zA-Z0-9_]*$");
146 return re.match(token);
149 RefPtr<Statement> Parser::parse_global_declaration()
151 allow_stage_change = true;
152 string token = tokenizer.peek_token();
153 allow_stage_change = false;
156 return parse_import();
157 else if(token=="precision")
158 return parse_precision();
159 else if(token=="layout")
161 RefPtr<Layout> layout = parse_layout();
162 token = tokenizer.peek_token();
163 if(is_interface_qualifier(token) && tokenizer.peek_token(1)==";")
165 RefPtr<InterfaceLayout> iface_lo = new InterfaceLayout;
166 iface_lo->source = source_index;
167 iface_lo->line = tokenizer.get_location().line;
168 iface_lo->layout.qualifiers = layout->qualifiers;
169 iface_lo->interface = tokenizer.parse_token();
170 tokenizer.expect(";");
175 RefPtr<VariableDeclaration> var = parse_variable_declaration();
176 var->layout = layout;
180 else if(token=="struct")
181 return parse_struct_declaration();
182 else if(is_interface_qualifier(token))
184 string next = tokenizer.peek_token(1);
185 if(is_type(next) || is_qualifier(next))
186 return parse_variable_declaration();
188 return parse_interface_block();
190 else if(is_qualifier(token))
191 return parse_variable_declaration();
192 else if(is_type(token))
194 if(tokenizer.peek_token(2)=="(")
195 return parse_function_declaration();
197 return parse_variable_declaration();
199 else if(token.empty())
202 throw parse_error(tokenizer.get_location(), token, "a global declaration");
205 RefPtr<Statement> Parser::parse_statement()
207 string token = tokenizer.peek_token();
209 return parse_conditional();
210 else if(token=="for")
212 else if(token=="while")
213 return parse_while();
214 else if(token=="passthrough")
215 return parse_passthrough();
216 else if(token=="return")
217 return parse_return();
218 else if(token=="break" || token=="continue" || token=="discard")
220 RefPtr<Jump> jump = new Jump;
221 jump->source = source_index;
222 jump->line = tokenizer.get_location().line;
223 jump->keyword = tokenizer.parse_token();
224 tokenizer.expect(";");
228 else if(is_qualifier(token) || is_type(token))
229 return parse_variable_declaration();
230 else if(!token.empty())
232 RefPtr<ExpressionStatement> expr = new ExpressionStatement;
233 expr->source = source_index;
234 expr->line = tokenizer.get_location().line;
235 expr->expression = parse_expression();
236 tokenizer.expect(";");
241 throw parse_error(tokenizer.get_location(), token, "a statement");
244 RefPtr<Import> Parser::parse_import()
246 if(cur_stage->type!=Stage::SHARED)
247 throw invalid_shader_source(tokenizer.get_location(), "Imports are only allowed in the shared section");
249 tokenizer.expect("import");
250 RefPtr<Import> import = new Import;
251 import->source = source_index;
252 import->line = tokenizer.get_location().line;
253 import->module = expect_identifier();
254 tokenizer.expect(";");
258 RefPtr<Precision> Parser::parse_precision()
260 tokenizer.expect("precision");
261 RefPtr<Precision> precision = new Precision;
262 precision->source = source_index;
263 precision->line = tokenizer.get_location().line;
265 precision->precision = tokenizer.parse_token();
266 if(!is_precision_qualifier(precision->precision))
267 throw parse_error(tokenizer.get_location(), precision->precision, "a precision qualifier");
269 precision->type = tokenizer.parse_token();
270 // Not entirely accurate; only float, int and sampler types are allowed
271 if(!is_builtin_type(precision->type))
272 throw parse_error(tokenizer.get_location(), precision->type, "a builtin type");
274 tokenizer.expect(";");
279 RefPtr<Layout> Parser::parse_layout()
281 tokenizer.expect("layout");
282 tokenizer.expect("(");
283 RefPtr<Layout> layout = new Layout;
286 string token = tokenizer.parse_token();
288 throw parse_error(tokenizer.get_location(), token, "a layout qualifier name");
290 layout->qualifiers.push_back(Layout::Qualifier());
291 Layout::Qualifier &qual = layout->qualifiers.back();
292 qual.identifier = token;
295 qual.value = tokenizer.parse_token();
297 if(tokenizer.peek_token()==")")
300 tokenizer.expect(",");
302 tokenizer.expect(")");
307 void Parser::parse_block(Block &block, bool require_braces)
309 bool have_braces = (require_braces || tokenizer.peek_token()=="{");
311 tokenizer.expect("{");
315 while(tokenizer.peek_token()!="}")
316 block.body.push_back(parse_statement());
319 block.body.push_back(parse_statement());
321 block.use_braces = (require_braces || block.body.size()!=1);
324 tokenizer.expect("}");
327 RefPtr<Expression> Parser::parse_expression(unsigned precedence)
329 RefPtr<Expression> left;
330 VariableReference *left_var = 0;
333 string token = tokenizer.peek_token();
335 const Operator *oper = 0;
336 for(const Operator *i=Operator::operators; (!oper && i->type); ++i)
337 if(token==i->token && (!left || i->type!=Operator::PREFIX) && (left || i->type!=Operator::POSTFIX))
340 if(token==";" || token==")" || token=="]" || token=="," || (oper && precedence && oper->precedence>=precedence))
345 throw parse_error(tokenizer.get_location(), token, "an expression");
352 throw invalid_shader_source(tokenizer.get_location(), "Syntax error before '(': function name must be an identifier");
353 left = parse_function_call(*left_var);
357 RefPtr<MemberAccess> memacc = new MemberAccess;
359 tokenizer.parse_token();
360 memacc->member = expect_identifier();
363 else if(oper && oper->type==Operator::POSTFIX)
365 RefPtr<UnaryExpression> unary = new UnaryExpression;
366 unary->oper = tokenizer.parse_token();
367 unary->prefix = false;
368 unary->expression = left;
371 else if(oper && oper->type==Operator::BINARY)
372 left = parse_binary(left, oper);
374 throw parse_error(tokenizer.get_location(), token, "an operator");
381 tokenizer.parse_token();
382 RefPtr<ParenthesizedExpression> parexpr = new ParenthesizedExpression;
383 parexpr->expression = parse_expression();
384 tokenizer.expect(")");
387 else if(isdigit(token[0]) || token=="true" || token=="false")
389 RefPtr<Literal> literal = new Literal;
390 literal->token = tokenizer.parse_token();
393 else if(is_identifier(token))
395 RefPtr<VariableReference> var = new VariableReference;
396 var->name = expect_identifier();
398 left_var = var.get();
400 else if(oper && oper->type==Operator::PREFIX)
402 RefPtr<UnaryExpression> unary = new UnaryExpression;
403 unary->oper = tokenizer.parse_token();
404 unary->prefix = true;
405 unary->expression = parse_expression(oper->precedence);
409 throw parse_error(tokenizer.get_location(), token, "an expression");
414 RefPtr<BinaryExpression> Parser::parse_binary(const RefPtr<Expression> &left, const Operator *oper)
416 RefPtr<BinaryExpression> binary = (oper->precedence==16 ? new Assignment : new BinaryExpression);
418 binary->oper = tokenizer.parse_token();
419 if(binary->oper=="[")
421 binary->right = parse_expression();
422 tokenizer.expect("]");
426 binary->right = parse_expression(oper->precedence+(oper->assoc==Operator::RIGHT_TO_LEFT));
430 RefPtr<FunctionCall> Parser::parse_function_call(const VariableReference &var)
432 RefPtr<FunctionCall> call = new FunctionCall;
433 call->name = var.name;
434 call->constructor = is_type(call->name);
435 tokenizer.expect("(");
436 while(tokenizer.peek_token()!=")")
438 if(!call->arguments.empty())
439 tokenizer.expect(",");
440 call->arguments.push_back(parse_expression());
442 tokenizer.expect(")");
446 RefPtr<StructDeclaration> Parser::parse_struct_declaration()
448 tokenizer.expect("struct");
449 RefPtr<StructDeclaration> strct = new StructDeclaration;
450 strct->source = source_index;
451 strct->line = tokenizer.get_location().line;
453 strct->name = expect_identifier();
454 parse_block(strct->members, true);
455 tokenizer.expect(";");
457 declared_types.insert(strct->name);
461 RefPtr<VariableDeclaration> Parser::parse_variable_declaration()
463 RefPtr<VariableDeclaration> var = new VariableDeclaration;
464 var->source = source_index;
465 var->line = tokenizer.get_location().line;
467 string token = tokenizer.peek_token();
468 while(is_qualifier(token))
470 tokenizer.parse_token();
471 if(is_interface_qualifier(token))
472 var->interface = token;
473 else if(is_sampling_qualifier(token))
474 var->sampling = token;
475 else if(is_interpolation_qualifier(token))
476 var->interpolation = token;
477 else if(is_precision_qualifier(token))
478 var->precision = token;
479 else if(token=="const")
480 var->constant = true;
481 token = tokenizer.peek_token();
484 var->type = expect_type();
485 var->name = expect_identifier();
492 var->array_size = parse_expression();
493 tokenizer.expect("]");
498 var->init_expression = parse_expression();
500 tokenizer.expect(";");
504 RefPtr<FunctionDeclaration> Parser::parse_function_declaration()
506 RefPtr<FunctionDeclaration> func = new FunctionDeclaration;
507 func->source = source_index;
508 func->line = tokenizer.get_location().line;
510 func->return_type = expect_type();
511 func->name = expect_identifier();
512 tokenizer.expect("(");
513 while(tokenizer.peek_token()!=")")
515 if(!func->parameters.empty())
516 tokenizer.expect(",");
518 RefPtr<VariableDeclaration> var = new VariableDeclaration;
519 string token = tokenizer.peek_token();
520 if(token=="in" || token=="out" || token=="inout")
521 var->interface = tokenizer.parse_token();
522 var->type = expect_type();
523 var->name = expect_identifier();
524 func->parameters.push_back(var);
526 tokenizer.expect(")");
528 string token = tokenizer.peek_token();
531 func->definition = func.get();
532 parse_block(func->body, true);
535 tokenizer.parse_token();
537 throw parse_error(tokenizer.get_location(), token, "'{' or ';'");
542 RefPtr<InterfaceBlock> Parser::parse_interface_block()
544 RefPtr<InterfaceBlock> iface = new InterfaceBlock;
545 iface->source = source_index;
546 iface->line = tokenizer.get_location().line;
548 iface->interface = tokenizer.parse_token();
549 if(!is_interface_qualifier(iface->interface))
550 throw parse_error(tokenizer.get_location(), iface->interface, "an interface qualifier");
552 iface->name = expect_identifier();
553 parse_block(iface->members, true);
556 iface->instance_name = expect_identifier();
560 tokenizer.expect("]");
562 tokenizer.expect(";");
568 RefPtr<Conditional> Parser::parse_conditional()
570 tokenizer.expect("if");
571 RefPtr<Conditional> cond = new Conditional;
572 cond->source = source_index;
573 cond->line = tokenizer.get_location().line;
574 tokenizer.expect("(");
575 cond->condition = parse_expression();
576 tokenizer.expect(")");
578 parse_block(cond->body, false);
580 string token = tokenizer.peek_token();
583 tokenizer.parse_token();
584 parse_block(cond->else_body, false);
590 RefPtr<Iteration> Parser::parse_for()
592 tokenizer.expect("for");
593 RefPtr<Iteration> loop = new Iteration;
594 loop->source = source_index;
595 loop->line = tokenizer.get_location().line;
596 tokenizer.expect("(");
597 string token = tokenizer.peek_token();
599 loop->init_statement = parse_statement();
604 RefPtr<ExpressionStatement> expr = new ExpressionStatement;
605 expr->expression = parse_expression();
606 loop->init_statement = expr;
608 tokenizer.expect(";");
610 if(tokenizer.peek_token()!=";")
611 loop->condition = parse_expression();
612 tokenizer.expect(";");
613 if(tokenizer.peek_token()!=")")
614 loop->loop_expression = parse_expression();
615 tokenizer.expect(")");
617 parse_block(loop->body, false);
622 RefPtr<Iteration> Parser::parse_while()
624 tokenizer.expect("while");
625 RefPtr<Iteration> loop = new Iteration;
626 loop->source = source_index;
627 loop->line = tokenizer.get_location().line;
628 tokenizer.expect("(");
629 loop->condition = parse_expression();
630 tokenizer.expect(")");
632 parse_block(loop->body, false);
637 RefPtr<Passthrough> Parser::parse_passthrough()
639 tokenizer.expect("passthrough");
640 RefPtr<Passthrough> pass = new Passthrough;
641 pass->source = source_index;
642 pass->line = tokenizer.get_location().line;
643 if(cur_stage->type==Stage::GEOMETRY)
645 tokenizer.expect("[");
646 pass->subscript = parse_expression();
647 tokenizer.expect("]");
649 tokenizer.expect(";");
653 RefPtr<Return> Parser::parse_return()
655 tokenizer.expect("return");
656 RefPtr<Return> ret = new Return;
657 ret->source = source_index;
658 ret->line = tokenizer.get_location().line;
659 if(tokenizer.peek_token()!=";")
660 ret->expression = parse_expression();
661 tokenizer.expect(";");