#include <msp/strings/format.h>
#include <msp/strings/regex.h>
+#include <msp/strings/utils.h>
#include "glsl_error.h"
#include "parser.h"
return token;
}
+int Parser::expect_integer()
+{
+ string token = tokenizer.parse_token();
+ if(!isnumrc(token))
+ throw parse_error(tokenizer.get_location(), token, "an integer literal");
+ return lexical_cast<int>(token);
+}
+
bool Parser::check(const string &token)
{
bool result = (tokenizer.peek_token()==token);
layout->qualifiers.push_back(Layout::Qualifier());
Layout::Qualifier &qual = layout->qualifiers.back();
- qual.identifier = token;
+ qual.name = token;
- if(check("="))
- qual.value = tokenizer.parse_token();
+ if((qual.has_value = check("=")))
+ {
+ if(qual.name=="constant_id" && tokenizer.peek_token()=="auto")
+ {
+ qual.value = -1;
+ tokenizer.parse_token();
+ }
+ else
+ qual.value = expect_integer();
+ }
if(tokenizer.peek_token()==")")
break;
return layout;
}
-void Parser::parse_block(Block &block, bool require_braces)
+template<typename T>
+void Parser::parse_block(Block &block, bool require_braces, RefPtr<T> (Parser::*parse_content)())
{
bool have_braces = (require_braces || tokenizer.peek_token()=="{");
if(have_braces)
if(have_braces)
{
while(tokenizer.peek_token()!="}")
- block.body.push_back(parse_statement());
+ block.body.push_back((this->*parse_content)());
}
else
- block.body.push_back(parse_statement());
+ block.body.push_back((this->*parse_content)());
block.use_braces = (require_braces || block.body.size()!=1);
strct->line = tokenizer.get_location().line;
strct->name = expect_identifier();
- parse_block(strct->members, true);
+ parse_block(strct->members, true, &Parser::parse_variable_declaration);
tokenizer.expect(";");
declared_types.insert(strct->name);
return var;
}
+RefPtr<VariableDeclaration> Parser::parse_variable_declaration_with_layout()
+{
+ RefPtr<Layout> layout;
+ if(tokenizer.peek_token()=="layout")
+ layout = parse_layout();
+
+ RefPtr<VariableDeclaration> var = parse_variable_declaration();
+ var->layout = layout;
+
+ return var;
+}
+
RefPtr<FunctionDeclaration> Parser::parse_function_declaration()
{
RefPtr<FunctionDeclaration> func = new FunctionDeclaration;
if(token=="{")
{
func->definition = func.get();
- parse_block(func->body, true);
+ parse_block(func->body, true, &Parser::parse_statement);
}
else if(token==";")
tokenizer.parse_token();
throw parse_error(tokenizer.get_location(), iface->interface, "an interface qualifier");
iface->name = expect_identifier();
- parse_block(iface->members, true);
+ parse_block(iface->members, true, &Parser::parse_variable_declaration_with_layout);
if(!check(";"))
{
iface->instance_name = expect_identifier();
cond->condition = parse_expression();
tokenizer.expect(")");
- parse_block(cond->body, false);
+ parse_block(cond->body, false, &Parser::parse_statement);
string token = tokenizer.peek_token();
if(token=="else")
{
tokenizer.parse_token();
- parse_block(cond->else_body, false);
+ parse_block(cond->else_body, false, &Parser::parse_statement);
}
return cond;
loop->loop_expression = parse_expression();
tokenizer.expect(")");
- parse_block(loop->body, false);
+ parse_block(loop->body, false, &Parser::parse_statement);
return loop;
}
loop->condition = parse_expression();
tokenizer.expect(")");
- parse_block(loop->body, false);
+ parse_block(loop->body, false, &Parser::parse_statement);
return loop;
}