1 #include <msp/core/raii.h>
2 #include <msp/strings/format.h>
3 #include <msp/strings/regex.h>
4 #include "glsl_error.h"
15 Parser::Operator Parser::operators[] =
17 { "[", 2, BINARY, LEFT_TO_RIGHT },
18 { "(", 2, BINARY, LEFT_TO_RIGHT },
19 { ".", 2, BINARY, LEFT_TO_RIGHT },
20 { "++", 2, POSTFIX, LEFT_TO_RIGHT },
21 { "--", 2, POSTFIX, LEFT_TO_RIGHT },
22 { "++", 3, PREFIX, RIGHT_TO_LEFT },
23 { "--", 3, PREFIX, RIGHT_TO_LEFT },
24 { "+", 3, PREFIX, RIGHT_TO_LEFT },
25 { "-", 3, PREFIX, RIGHT_TO_LEFT },
26 { "~", 3, PREFIX, RIGHT_TO_LEFT },
27 { "!", 3, PREFIX, RIGHT_TO_LEFT },
28 { "*", 4, BINARY, LEFT_TO_RIGHT },
29 { "/", 4, BINARY, LEFT_TO_RIGHT },
30 { "%", 4, BINARY, LEFT_TO_RIGHT },
31 { "+", 5, BINARY, LEFT_TO_RIGHT },
32 { "-", 5, BINARY, LEFT_TO_RIGHT },
33 { "<<", 6, BINARY, LEFT_TO_RIGHT },
34 { ">>", 6, BINARY, LEFT_TO_RIGHT },
35 { "<", 7, BINARY, LEFT_TO_RIGHT },
36 { ">", 7, BINARY, LEFT_TO_RIGHT },
37 { "<=", 7, BINARY, LEFT_TO_RIGHT },
38 { ">=", 7, BINARY, LEFT_TO_RIGHT },
39 { "==", 8, BINARY, LEFT_TO_RIGHT },
40 { "!=", 8, BINARY, LEFT_TO_RIGHT },
41 { "&", 9, BINARY, LEFT_TO_RIGHT },
42 { "^", 10, BINARY, LEFT_TO_RIGHT },
43 { "|", 11, BINARY, LEFT_TO_RIGHT },
44 { "&&", 12, BINARY, LEFT_TO_RIGHT },
45 { "^^", 13, BINARY, LEFT_TO_RIGHT },
46 { "||", 14, BINARY, LEFT_TO_RIGHT },
47 { "?", 15, BINARY, RIGHT_TO_LEFT },
48 { ":", 15, BINARY, RIGHT_TO_LEFT },
49 { "=", 16, BINARY, RIGHT_TO_LEFT },
50 { "+=", 16, BINARY, RIGHT_TO_LEFT },
51 { "-=", 16, BINARY, RIGHT_TO_LEFT },
52 { "*=", 16, BINARY, RIGHT_TO_LEFT },
53 { "/=", 16, BINARY, RIGHT_TO_LEFT },
54 { "%=", 16, BINARY, RIGHT_TO_LEFT },
55 { "<<=", 16, BINARY, RIGHT_TO_LEFT },
56 { ">>=", 16, BINARY, RIGHT_TO_LEFT },
57 { "&=", 16, BINARY, RIGHT_TO_LEFT },
58 { "^=", 16, BINARY, RIGHT_TO_LEFT },
59 { "|=", 16, BINARY, RIGHT_TO_LEFT },
60 { ",", 17, BINARY, LEFT_TO_RIGHT },
61 { { 0 }, 18, NO_OPERATOR, LEFT_TO_RIGHT }
73 Module &Parser::parse(const string &s, const string &n, unsigned i)
82 Module &Parser::parse(IO::Base &io, const string &n, unsigned i)
90 unsigned len = io.read(buffer, sizeof(buffer));
91 source.append(buffer, len);
97 void Parser::parse_source()
101 string::size_type slashes = source.find("//////");
102 if(slashes==string::npos)
105 string::size_type newline = source.find('\n', slashes);
106 string pragma = format("#pragma MSP stage(%s)", source.substr(slashes+6, newline-slashes-6));
107 source.replace(slashes, newline-slashes, pragma);
112 cur_stage = &module->shared;
113 iter = source.begin();
114 source_end = source.end();
116 allow_preprocess = true;
117 while(RefPtr<Statement> statement = parse_global_declaration())
118 cur_stage->content.body.push_back(statement);
121 const string &Parser::peek_token(unsigned index)
123 while(next_tokens.size()<=index)
124 next_tokens.push_back(parse_token_());
125 return (last_token = next_tokens[index]);
128 const string &Parser::parse_token()
130 if(!next_tokens.empty())
132 last_token = next_tokens.front();
133 next_tokens.pop_front();
137 return (last_token = parse_token_());
140 string Parser::parse_token_()
144 skip_comment_and_whitespace();
147 else if(allow_preprocess && *iter=='#')
149 allow_preprocess = false;
150 SetForScope<deque<string> > clear_tokens(next_tokens, deque<string>());
153 else if(isalpha(*iter) || *iter=='_')
154 return parse_identifier();
155 else if(isdigit(*iter))
156 return parse_number();
158 return parse_other();
162 string Parser::parse_identifier()
165 while(iter!=source_end)
167 if(isalnum(*iter) || *iter=='_')
176 string Parser::parse_number()
178 bool accept_sign = false;
180 while(iter!=source_end)
182 if(isdigit(*iter) || *iter=='.')
184 else if(*iter=='e' || *iter=='E')
189 else if(accept_sign && (*iter=='+' || *iter=='-'))
198 string Parser::parse_other()
203 string token(1, *iter++);
204 for(unsigned i=1; (i<3 && iter!=source_end); ++i)
206 bool matched = false;
207 for(const Operator *j=operators; (!matched && j->type); ++j)
209 matched = (j->token[i]==*iter);
210 for(unsigned k=0; (matched && k<i && j->token[k]); ++k)
211 matched = (j->token[k]==token[k]);
223 void Parser::skip_comment_and_whitespace()
225 unsigned comment = 0;
226 while(iter!=source_end)
232 else if(!isspace(*iter))
253 else if(comment==3 && *iter=='*')
266 allow_preprocess = (comment<3);
273 void Parser::expect(const string &token)
275 string parsed = parse_token();
277 throw parse_error(location, parsed, format("'%s'", token));
280 string Parser::expect_type()
282 string token = parse_token();
284 throw parse_error(location, token, "a type");
288 string Parser::expect_identifier()
290 string token = parse_token();
291 if(!is_identifier(token))
292 throw parse_error(location, token, "an identifier");
296 bool Parser::check(const string &token)
298 bool result = (peek_token()==token);
304 bool Parser::is_interface_qualifier(const string &token)
306 return (token=="uniform" || token=="in" || token=="out");
309 bool Parser::is_sampling_qualifier(const string &token)
311 return (token=="centroid" || token=="sample");
314 bool Parser::is_interpolation_qualifier(const string &token)
316 return (token=="smooth" || token=="flat" || token=="noperspective");
319 bool Parser::is_precision_qualifier(const string &token)
321 return (token=="highp" || token=="mediump" || token=="lowp");
324 bool Parser::is_qualifier(const string &token)
326 return (token=="const" ||
327 is_interface_qualifier(token) ||
328 is_sampling_qualifier(token) ||
329 is_interpolation_qualifier(token) ||
330 is_precision_qualifier(token));
333 bool Parser::is_builtin_type(const string &token)
335 static Regex re("^(void|float|int|bool|[ib]?vec[234]|mat[234](x[234])?|sampler((1D|2D|Cube)(Array)?(Shadow)?|3D))$");
336 return re.match(token);
339 bool Parser::is_type(const string &token)
341 return is_builtin_type(token) || declared_types.count(token);
344 bool Parser::is_identifier(const string &token)
346 static Regex re("^[a-zA-Z_][a-zA-Z0-9_]*$");
347 return re.match(token);
350 void Parser::preprocess()
354 string::const_iterator line_end = iter;
355 for(; (line_end!=source_end && *line_end!='\n'); ++line_end) ;
356 SetForScope<string::const_iterator> stop_at_line_end(source_end, line_end);
358 string token = peek_token();
361 else if(token=="version")
362 preprocess_version();
363 else if(token=="define" || token=="undef" || token=="if" || token=="ifdef" || token=="ifndef" || token=="else" ||
364 token=="elif" || token=="endif" || token=="error" || token=="extension" || token=="line")
365 throw invalid_shader_source(location, "Unsupported preprocessor directive '%s'", token);
366 else if(!token.empty())
367 throw parse_error(location, token, "a preprocessor directive");
372 void Parser::preprocess_version()
375 string token = parse_token();
376 unsigned version = lexical_cast<unsigned>(token);
377 cur_stage->required_version = Version(version/100, version%100);
379 token = parse_token();
381 throw parse_error(location, token, "end of line");
384 void Parser::preprocess_pragma()
387 string token = parse_token();
389 preprocess_pragma_msp();
392 void Parser::preprocess_pragma_msp()
394 string token = peek_token();
398 throw invalid_shader_source(location, "Unrecognized MSP pragma '%s'", token);
400 token = parse_token();
402 throw parse_error(location, token, "end of line");
405 void Parser::preprocess_stage()
407 if(!allow_stage_change)
408 throw invalid_shader_source(location, "Changing stage not allowed here");
412 string token = expect_identifier();
413 StageType stage = SHARED;
416 else if(token=="geometry")
418 else if(token=="fragment")
421 throw parse_error(location, token, "stage identifier");
424 if(stage<=cur_stage->type)
425 throw invalid_shader_source(location, "Stage '%s' not allowed here", token);
427 module->stages.push_back(stage);
429 if(cur_stage->type!=SHARED)
430 module->stages.back().previous = cur_stage;
431 cur_stage = &module->stages.back();
434 RefPtr<Statement> Parser::parse_global_declaration()
436 allow_stage_change = true;
437 string token = peek_token();
438 allow_stage_change = false;
441 return parse_import();
442 else if(token=="precision")
443 return parse_precision();
444 else if(token=="layout")
446 RefPtr<Layout> layout = parse_layout();
447 token = peek_token();
448 if(is_interface_qualifier(token) && peek_token(1)==";")
450 RefPtr<InterfaceLayout> iface_lo = new InterfaceLayout;
451 iface_lo->source = source_index;
452 iface_lo->line = location.line;
453 iface_lo->layout.qualifiers = layout->qualifiers;
454 iface_lo->interface = parse_token();
460 RefPtr<VariableDeclaration> var = parse_variable_declaration();
461 var->layout = layout;
465 else if(token=="struct")
466 return parse_struct_declaration();
467 else if(is_interface_qualifier(token))
469 string next = peek_token(1);
470 if(is_type(next) || is_qualifier(next))
471 return parse_variable_declaration();
473 return parse_interface_block();
475 else if(is_qualifier(token))
476 return parse_variable_declaration();
477 else if(is_type(token))
479 if(peek_token(2)=="(")
480 return parse_function_declaration();
482 return parse_variable_declaration();
484 else if(token.empty())
487 throw parse_error(location, token, "a global declaration");
490 RefPtr<Statement> Parser::parse_statement()
492 string token = peek_token();
494 return parse_conditional();
495 else if(token=="for")
497 else if(token=="while")
498 return parse_while();
499 else if(token=="passthrough")
500 return parse_passthrough();
501 else if(token=="return")
502 return parse_return();
503 else if(token=="break" || token=="continue" || token=="discard")
505 RefPtr<Jump> jump = new Jump;
506 jump->source = source_index;
507 jump->line = location.line;
508 jump->keyword = parse_token();
513 else if(is_qualifier(token) || is_type(token))
514 return parse_variable_declaration();
515 else if(!token.empty())
517 RefPtr<ExpressionStatement> expr = new ExpressionStatement;
518 expr->source = source_index;
519 expr->line = location.line;
520 expr->expression = parse_expression();
526 throw parse_error(location, token, "a statement");
529 RefPtr<Import> Parser::parse_import()
531 if(cur_stage->type!=SHARED)
532 throw invalid_shader_source(location, "Imports are only allowed in the shared section");
535 RefPtr<Import> import = new Import;
536 import->source = source_index;
537 import->line = location.line;
538 import->module = expect_identifier();
543 RefPtr<Precision> Parser::parse_precision()
546 RefPtr<Precision> precision = new Precision;
547 precision->source = source_index;
548 precision->line = location.line;
550 precision->precision = parse_token();
551 if(!is_precision_qualifier(precision->precision))
552 throw parse_error(location, precision->precision, "a precision qualifier");
554 precision->type = parse_token();
555 // Not entirely accurate; only float, int and sampler types are allowed
556 if(!is_builtin_type(precision->type))
557 throw parse_error(location, precision->type, "a builtin type");
564 RefPtr<Layout> Parser::parse_layout()
568 RefPtr<Layout> layout = new Layout;
571 string token = parse_token();
573 throw parse_error(location, token, "a layout qualifier name");
575 layout->qualifiers.push_back(Layout::Qualifier());
576 Layout::Qualifier &qual = layout->qualifiers.back();
577 qual.identifier = token;
580 qual.value = parse_token();
582 if(peek_token()==")")
592 void Parser::parse_block(Block &block, bool require_braces)
594 bool have_braces = (require_braces || peek_token()=="{");
600 while(peek_token()!="}")
601 block.body.push_back(parse_statement());
604 block.body.push_back(parse_statement());
606 block.use_braces = (require_braces || block.body.size()!=1);
612 RefPtr<Expression> Parser::parse_expression(unsigned precedence)
614 RefPtr<Expression> left;
615 VariableReference *left_var = 0;
618 string token = peek_token();
620 const Operator *oper = 0;
621 for(Operator *i=operators; (!oper && i->type); ++i)
622 if(token==i->token && (!left || i->type!=PREFIX) && (left || i->type!=POSTFIX))
625 if(token==";" || token==")" || token=="]" || token=="," || (oper && precedence && oper->precedence>=precedence))
630 throw parse_error(location, token, "an expression");
637 throw invalid_shader_source(location, "Syntax error before '(': function name must be an identifier");
638 left = parse_function_call(*left_var);
642 RefPtr<MemberAccess> memacc = new MemberAccess;
645 memacc->member = expect_identifier();
648 else if(oper && oper->type==POSTFIX)
650 RefPtr<UnaryExpression> unary = new UnaryExpression;
651 unary->oper = parse_token();
652 unary->prefix = false;
653 unary->expression = left;
656 else if(oper && oper->type==BINARY)
657 left = parse_binary(left, oper);
659 throw parse_error(location, token, "an operator");
667 RefPtr<ParenthesizedExpression> parexpr = new ParenthesizedExpression;
668 parexpr->expression = parse_expression();
672 else if(isdigit(token[0]) || token=="true" || token=="false")
674 RefPtr<Literal> literal = new Literal;
675 literal->token = parse_token();
678 else if(is_identifier(token))
680 RefPtr<VariableReference> var = new VariableReference;
681 var->name = expect_identifier();
683 left_var = var.get();
685 else if(oper && oper->type==PREFIX)
687 RefPtr<UnaryExpression> unary = new UnaryExpression;
688 unary->oper = parse_token();
689 unary->prefix = true;
690 unary->expression = parse_expression(oper->precedence);
694 throw parse_error(location, token, "an expression");
699 RefPtr<BinaryExpression> Parser::parse_binary(const RefPtr<Expression> &left, const Operator *oper)
701 RefPtr<BinaryExpression> binary = (oper->precedence==16 ? new Assignment : new BinaryExpression);
703 binary->oper = parse_token();
704 if(binary->oper=="[")
706 binary->right = parse_expression();
711 binary->right = parse_expression(oper->precedence+(oper->assoc==RIGHT_TO_LEFT));
715 RefPtr<FunctionCall> Parser::parse_function_call(const VariableReference &var)
717 RefPtr<FunctionCall> call = new FunctionCall;
718 call->name = var.name;
719 call->constructor = is_type(call->name);
721 while(peek_token()!=")")
723 if(!call->arguments.empty())
725 call->arguments.push_back(parse_expression());
731 RefPtr<StructDeclaration> Parser::parse_struct_declaration()
734 RefPtr<StructDeclaration> strct = new StructDeclaration;
735 strct->source = source_index;
736 strct->line = location.line;
738 strct->name = expect_identifier();
739 parse_block(strct->members, true);
742 declared_types.insert(strct->name);
746 RefPtr<VariableDeclaration> Parser::parse_variable_declaration()
748 RefPtr<VariableDeclaration> var = new VariableDeclaration;
749 var->source = source_index;
750 var->line = location.line;
752 string token = peek_token();
753 while(is_qualifier(token))
756 if(is_interface_qualifier(token))
757 var->interface = token;
758 else if(is_sampling_qualifier(token))
759 var->sampling = token;
760 else if(is_interpolation_qualifier(token))
761 var->interpolation = token;
762 else if(is_precision_qualifier(token))
763 var->precision = token;
764 else if(token=="const")
765 var->constant = true;
766 token = peek_token();
769 var->type = expect_type();
770 var->name = expect_identifier();
777 var->array_size = parse_expression();
783 var->init_expression = parse_expression();
789 RefPtr<FunctionDeclaration> Parser::parse_function_declaration()
791 RefPtr<FunctionDeclaration> func = new FunctionDeclaration;
792 func->source = source_index;
793 func->line = location.line;
795 func->return_type = expect_type();
796 func->name = expect_identifier();
798 while(peek_token()!=")")
800 if(!func->parameters.empty())
803 RefPtr<VariableDeclaration> var = new VariableDeclaration;
804 string token = peek_token();
805 if(token=="in" || token=="out" || token=="inout")
806 var->interface = parse_token();
807 var->type = expect_type();
808 var->name = expect_identifier();
809 func->parameters.push_back(var);
813 string token = peek_token();
816 func->definition = func.get();
817 parse_block(func->body, true);
822 throw parse_error(location, token, "'{' or ';'");
827 RefPtr<InterfaceBlock> Parser::parse_interface_block()
829 RefPtr<InterfaceBlock> iface = new InterfaceBlock;
830 iface->source = source_index;
831 iface->line = location.line;
833 iface->interface = parse_token();
834 if(!is_interface_qualifier(iface->interface))
835 throw parse_error(location, iface->interface, "an interface qualifier");
837 iface->name = expect_identifier();
838 parse_block(iface->members, true);
841 iface->instance_name = expect_identifier();
853 RefPtr<Conditional> Parser::parse_conditional()
856 RefPtr<Conditional> cond = new Conditional;
857 cond->source = source_index;
858 cond->line = location.line;
860 cond->condition = parse_expression();
863 parse_block(cond->body, false);
865 string token = peek_token();
869 parse_block(cond->else_body, false);
875 RefPtr<Iteration> Parser::parse_for()
878 RefPtr<Iteration> loop = new Iteration;
879 loop->source = source_index;
880 loop->line = location.line;
882 string token = peek_token();
884 loop->init_statement = parse_statement();
889 RefPtr<ExpressionStatement> expr = new ExpressionStatement;
890 expr->expression = parse_expression();
891 loop->init_statement = expr;
895 if(peek_token()!=";")
896 loop->condition = parse_expression();
898 if(peek_token()!=")")
899 loop->loop_expression = parse_expression();
902 parse_block(loop->body, false);
907 RefPtr<Iteration> Parser::parse_while()
910 RefPtr<Iteration> loop = new Iteration;
911 loop->source = source_index;
912 loop->line = location.line;
914 loop->condition = parse_expression();
917 parse_block(loop->body, false);
922 RefPtr<Passthrough> Parser::parse_passthrough()
924 expect("passthrough");
925 RefPtr<Passthrough> pass = new Passthrough;
926 pass->source = source_index;
927 pass->line = location.line;
928 if(cur_stage->type==GEOMETRY)
931 pass->subscript = parse_expression();
938 RefPtr<Return> Parser::parse_return()
941 RefPtr<Return> ret = new Return;
942 ret->source = source_index;
943 ret->line = location.line;
944 if(peek_token()!=";")
945 ret->expression = parse_expression();