iter = source.begin();
while(1)
{
- while(Node *statement = parse_global_declaration())
+ while(RefPtr<Node> statement = parse_global_declaration())
cur_stage->content.body.push_back(statement);
parse_token();
return re.match(token);
}
-Node *ProgramParser::parse_global_declaration()
+RefPtr<Node> ProgramParser::parse_global_declaration()
{
string token = peek_token();
- if(token=="layout")
- return parse_layout();
+ if(token=="import")
+ return parse_import();
+ else if(token=="layout")
+ {
+ RefPtr<Layout> layout = parse_layout();
+ token = peek_token();
+ if(is_interface_qualifier(token) && peek_token(1)==";")
+ {
+ RefPtr<InterfaceLayout> iface_lo = new InterfaceLayout;
+ iface_lo->layout.qualifiers = layout->qualifiers;
+ iface_lo->interface = parse_token();
+ expect(";");
+ return iface_lo;
+ }
+ else
+ {
+ RefPtr<VariableDeclaration> var = parse_variable_declaration();
+ var->layout = layout;
+ return var;
+ }
+ }
else if(token=="struct")
return parse_struct_declaration();
else if(is_sampling_qualifier(token) || token=="const")
throw runtime_error(format("Syntax error at '%s': expected a global declaration", token));
}
-Node *ProgramParser::parse_statement()
+RefPtr<Node> ProgramParser::parse_statement()
{
string token = peek_token();
if(token=="if")
return parse_passthrough();
else if(token=="return")
return parse_return();
+ else if(token=="break" || token=="continue" || token=="discard")
+ {
+ RefPtr<Jump> jump = new Jump;
+ jump->keyword = parse_token();
+ expect(";");
+
+ return jump;
+ }
else if(is_qualifier(token) || is_type(token))
return parse_variable_declaration();
else if(!token.empty())
expr->expression = parse_expression();
expect(";");
- return expr.release();
+ return expr;
}
else
throw runtime_error(format("Syntax error at '%s': expected a statement", token));
}
-Layout *ProgramParser::parse_layout()
+RefPtr<Import> ProgramParser::parse_import()
+{
+ if(cur_stage->type!=SHARED)
+ throw runtime_error("Imports are only allowed in the shared section");
+
+ expect("import");
+ RefPtr<Import> import = new Import;
+ import->module = parse_token();
+ expect(";");
+ return import;
+}
+
+RefPtr<Layout> ProgramParser::parse_layout()
{
expect("layout");
expect("(");
expect(",");
}
expect(")");
- layout->interface = parse_token();
- expect(";");
- return layout.release();
+ return layout;
}
void ProgramParser::parse_block(Block &block, bool require_braces)
expect("}");
}
-Expression *ProgramParser::parse_expression(unsigned precedence)
+RefPtr<Expression> ProgramParser::parse_expression(unsigned precedence)
{
RefPtr<Expression> left;
VariableReference *left_var = 0;
if(token==";" || token==")" || token=="]" || token=="," || (oper && precedence && oper->precedence>=precedence))
{
if(left)
- return left.release();
+ return left;
else
throw runtime_error(format("Parse error at '%s': expected an expression", token));
}
{
if(!left_var)
throw runtime_error(format("Parse error at '%s': function name must be an identifier", token));
- left = parse_function_call(left_var);
+ left = parse_function_call(*left_var);
}
else if(token==".")
{
RefPtr<MemberAccess> memacc = new MemberAccess;
- memacc->left = left.release();
+ memacc->left = left;
parse_token();
memacc->member = expect_identifier();
left = memacc;
RefPtr<UnaryExpression> unary = new UnaryExpression;
unary->oper = parse_token();
unary->prefix = false;
- unary->expression = left.release();
+ unary->expression = left;
left = unary;
}
else if(oper && oper->type==BINARY)
- left = parse_binary(left.release(), oper);
+ left = parse_binary(left, oper);
else
throw runtime_error(format("Parse error at '%s': expected an operator", token));
left_var = 0;
expect(")");
left = parexpr;
}
+ else if(isdigit(token[0]) || token=="true" || token=="false")
+ {
+ RefPtr<Literal> literal = new Literal;
+ literal->token = parse_token();
+ left = literal;
+ }
else if(is_identifier(token))
{
RefPtr<VariableReference> var = new VariableReference;
unary->expression = parse_expression(oper->precedence);
left = unary;
}
- else if(isdigit(token[0]))
- {
- RefPtr<Literal> literal = new Literal;
- literal->token = parse_token();
- left = literal;
- }
else
throw runtime_error(format("Parse error at '%s': expected an expression", token));
}
}
}
-BinaryExpression *ProgramParser::parse_binary(Expression *left, const Operator *oper)
+RefPtr<BinaryExpression> ProgramParser::parse_binary(const RefPtr<Expression> &left, const Operator *oper)
{
RefPtr<BinaryExpression> binary = (oper->precedence==16 ? new Assignment : new BinaryExpression);
binary->left = left;
}
else
binary->right = parse_expression(oper->precedence+(oper->assoc==RIGHT_TO_LEFT));
- return binary.release();
+ return binary;
}
-FunctionCall *ProgramParser::parse_function_call(VariableReference *var)
+RefPtr<FunctionCall> ProgramParser::parse_function_call(const VariableReference &var)
{
RefPtr<FunctionCall> call = new FunctionCall;
- call->name = var->name;
+ call->name = var.name;
call->constructor = is_type(call->name);
expect("(");
while(peek_token()!=")")
call->arguments.push_back(parse_expression());
}
expect(")");
- return call.release();
+ return call;
}
-StructDeclaration *ProgramParser::parse_struct_declaration()
+RefPtr<StructDeclaration> ProgramParser::parse_struct_declaration()
{
expect("struct");
RefPtr<StructDeclaration> strct = new StructDeclaration;
expect(";");
declared_types.insert(strct->name);
- return strct.release();
+ return strct;
}
-VariableDeclaration *ProgramParser::parse_variable_declaration()
+RefPtr<VariableDeclaration> ProgramParser::parse_variable_declaration()
{
RefPtr<VariableDeclaration> var = new VariableDeclaration;
var->init_expression = parse_expression();
expect(";");
- return var.release();
+ return var;
}
-FunctionDeclaration *ProgramParser::parse_function_declaration()
+RefPtr<FunctionDeclaration> ProgramParser::parse_function_declaration()
{
RefPtr<FunctionDeclaration> func = new FunctionDeclaration;
RefPtr<VariableDeclaration> var = new VariableDeclaration;
var->type = expect_type();
var->name = expect_identifier();
- func->parameters.push_back(var.release());
+ func->parameters.push_back(var);
}
expect(")");
string token = peek_token();
if(token=="{")
{
- func->definition = true;
+ func->definition = func.get();
parse_block(func->body, true);
}
else if(token==";")
else
throw runtime_error(format("Parse error at '%s': expected '{' or ';'", token));
- return func.release();
+ return func;
}
-InterfaceBlock *ProgramParser::parse_interface_block()
+RefPtr<InterfaceBlock> ProgramParser::parse_interface_block()
{
RefPtr<InterfaceBlock> iface = new InterfaceBlock;
expect(";");
}
- return iface.release();
+ return iface;
}
-Conditional *ProgramParser::parse_conditional()
+RefPtr<Conditional> ProgramParser::parse_conditional()
{
expect("if");
expect("(");
parse_block(cond->else_body, false);
}
- return cond.release();
+ return cond;
}
-Iteration *ProgramParser::parse_iteration()
+RefPtr<Iteration> ProgramParser::parse_iteration()
{
expect("for");
expect("(");
RefPtr<ExpressionStatement> expr = new ExpressionStatement;
expr->expression = parse_expression();
expect(";");
- loop->init_statement = expr.release();
+ loop->init_statement = expr;
}
loop->condition = parse_expression();
expect(";");
parse_block(loop->body, false);
- return loop.release();
+ return loop;
}
-Passthrough *ProgramParser::parse_passthrough()
+RefPtr<Passthrough> ProgramParser::parse_passthrough()
{
expect("passthrough");
RefPtr<Passthrough> pass = new Passthrough;
expect("]");
}
expect(";");
- return pass.release();
+ return pass;
}
-Return *ProgramParser::parse_return()
+RefPtr<Return> ProgramParser::parse_return()
{
expect("return");
RefPtr<Return> ret = new Return;
if(peek_token()!=";")
ret->expression = parse_expression();
expect(";");
- return ret.release();
+ return ret;
}
} // namespace GL