X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fparser.cpp;h=fd782648083bdb05a1aa700ca65d4ab8f15aa926;hb=041ba4b1acd55337239c5ce24cc310118c621206;hp=0f7122f50dae119283390b22f51bbae31ce245eb;hpb=a82fcc462550d63a101aca4313807b1320789a5a;p=libs%2Fgl.git diff --git a/source/glsl/parser.cpp b/source/glsl/parser.cpp index 0f7122f5..fd782648 100644 --- a/source/glsl/parser.cpp +++ b/source/glsl/parser.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "builtin.h" #include "glsl_error.h" #include "parser.h" @@ -53,11 +54,27 @@ void Parser::parse_source(const string &name, int index) { delete module; module = new Module; + cur_stage = &module->shared; base_index = index; source_index = index; if(index>=0) source_reference(1, name); + + // TODO Need to somehow get type names from imports + if(const Stage *builtin = get_builtins(Stage::SHARED)) + { + for(map::const_iterator i=builtin->types.begin(); i!=builtin->types.end(); ++i) + declared_types.insert(i->first); + } + else + { + declared_types.insert("void"); + declared_types.insert("bool"); + declared_types.insert("int"); + declared_types.insert("float"); + } + tokenizer.begin(source, name); allow_stage_change = true; while(!tokenizer.peek_token().empty()) @@ -171,15 +188,9 @@ bool Parser::is_qualifier(const string &token) is_precision_qualifier(token)); } -bool Parser::is_builtin_type(const string &token) -{ - static Regex re("^(void|float|int|bool|[ib]?vec[234]|mat[234](x[234])?|sampler((1D|2D|Cube)(Array)?(Shadow)?|3D))$"); - return re.match(token); -} - bool Parser::is_type(const string &token) { - return is_builtin_type(token) || declared_types.count(token); + return declared_types.count(token); } bool Parser::is_identifier(const string &token) @@ -269,6 +280,8 @@ RefPtr Parser::parse_global_declaration() return var; } } + else if(token=="typedef") + return parse_type_declaration(); else if(token=="struct") return parse_struct_declaration(); else if(is_interface_qualifier(token)) @@ -355,10 +368,8 @@ RefPtr Parser::parse_precision() if(!is_precision_qualifier(precision->precision)) throw parse_error(tokenizer.get_location(), precision->precision, "a precision qualifier"); - precision->type = tokenizer.parse_token(); - // Not entirely accurate; only float, int and sampler types are allowed - if(!is_builtin_type(precision->type)) - throw parse_error(tokenizer.get_location(), precision->type, "a builtin type"); + // TODO Add validation for this + precision->type = expect_type(); tokenizer.expect(";"); @@ -436,7 +447,8 @@ RefPtr Parser::parse_expression(unsigned precedence) if(token==i->token && (!left || i->type!=Operator::PREFIX) && (left || i->type!=Operator::POSTFIX)) oper = i; - if(token==";" || token==")" || token=="]" || token=="," || (oper && precedence && oper->precedence>=precedence)) + bool lower_precedence = (oper && oper->type!=Operator::PREFIX && precedence && oper->precedence>=precedence); + if(token==";" || token==")" || token=="]" || token=="," || lower_precedence) { if(left) return left; @@ -485,11 +497,7 @@ RefPtr Parser::parse_expression(unsigned precedence) left = parexpr; } else if(isdigit(token[0]) || token=="true" || token=="false") - { - RefPtr literal = new Literal; - literal->token = tokenizer.parse_token(); - left = literal; - } + left = parse_literal(); else if(is_identifier(token)) { RefPtr var = create_node(); @@ -511,6 +519,26 @@ RefPtr Parser::parse_expression(unsigned precedence) } } +RefPtr Parser::parse_literal() +{ + RefPtr literal = create_node(); + literal->token = tokenizer.parse_token(); + if(isdigit(literal->token[0])) + { + // TODO have the tokenizer return the type of the token + if(isnumrc(literal->token)) + literal->value = lexical_cast(literal->token); + else + literal->value = lexical_cast(literal->token); + } + else if(literal->token=="true" || literal->token=="false") + literal->value = (literal->token=="true"); + else + throw parse_error(tokenizer.get_location(), literal->token, "a literal"); + + return literal; +} + RefPtr Parser::parse_binary(const RefPtr &left, const Operator &oper) { RefPtr binary = (oper.precedence==16 ? @@ -545,6 +573,98 @@ RefPtr Parser::parse_function_call(const VariableReference &var) return call; } +RefPtr Parser::parse_type_declaration() +{ + tokenizer.expect("typedef"); + + RefPtr type; + if(tokenizer.peek_token()=="image") + type = parse_image_type_declaration(); + else + type = parse_basic_type_declaration(); + + tokenizer.expect(";"); + declared_types.insert(type->name); + return type; +} + +RefPtr Parser::parse_basic_type_declaration() +{ + RefPtr type = create_node(); + + if(tokenizer.peek_token()=="vector") + { + type->kind = BasicTypeDeclaration::VECTOR; + + tokenizer.parse_token(); + tokenizer.expect("("); + type->size = expect_integer(); + tokenizer.expect(")"); + } + + type->base = expect_type(); + type->name = expect_identifier(); + + if(type->kind==BasicTypeDeclaration::ALIAS && check("[")) + { + type->kind = BasicTypeDeclaration::ARRAY; + tokenizer.expect("]"); + } + + return type; +} + +RefPtr Parser::parse_image_type_declaration() +{ + tokenizer.expect("image"); + tokenizer.expect("("); + + RefPtr type = create_node(); + while(1) + { + string token = tokenizer.parse_token(); + if(token=="dimensions") + { + tokenizer.expect("="); + token = tokenizer.parse_token(); + if(token=="1") + type->dimensions = ImageTypeDeclaration::ONE; + else if(token=="2") + type->dimensions = ImageTypeDeclaration::TWO; + else if(token=="3") + type->dimensions = ImageTypeDeclaration::THREE; + else if(token=="cube") + type->dimensions = ImageTypeDeclaration::CUBE; + else + throw parse_error(tokenizer.get_location(), token, "dimensions"); + + if(check("[")) + { + type->array = true; + tokenizer.expect("]"); + } + } + else if(token=="sampled") + type->sampled = true; + else if(token=="shadow") + type->shadow = true; + else + throw parse_error(tokenizer.get_location(), token, "image type attribute"); + + token = tokenizer.peek_token(); + if(token==")") + break; + + tokenizer.expect(","); + } + tokenizer.expect(")"); + + type->base = expect_type(); + type->name = expect_identifier(); + + return type; +} + RefPtr Parser::parse_struct_declaration() { tokenizer.expect("struct"); @@ -656,7 +776,8 @@ RefPtr Parser::parse_interface_block() throw parse_error(tokenizer.get_location(), iface->interface, "an interface qualifier"); iface->name = expect_identifier(); - parse_block(iface->members, true, &Parser::parse_variable_declaration_with_layout); + iface->members = new Block; + parse_block(*iface->members, true, &Parser::parse_variable_declaration_with_layout); if(!check(";")) { iface->instance_name = expect_identifier();