예제 #1
0
def glsl_parse_control(source):
    """Parse control block."""
    (control, content) = extract_tokens(source, "?c")
    if not control:
        return (None, source)
    # 'else' is simpler.
    if control.format(False) == "else":
        return (GlslBlockControl(control, None, None), content)
    # Other control structures require scope.
    (scope, remaining) = extract_tokens(content, "?(")
    if not scope:
        return (None, source)
    # 'for' may require declaration at the beginning.
    declaration = None
    if control.format(False) == "for":
        (declaration, intermediate) = glsl_parse_declaration(scope)
        if declaration:
            scope = intermediate
    # Parse the rest of the statements, regardless if declaration was found.
    (statements, scope_remaining) = glsl_parse_statements(scope)
    if not statements:
        return (None, source)
    if scope_remaining:
        raise RuntimeError(
            "control scope cannot have remaining elements: '%s'" %
            str(scope_remaining))
    return (GlslBlockControl(control, declaration, statements), remaining)
예제 #2
0
def glsl_parse_inout(source):
    """Parse inout block."""
    (layout, content) = glsl_parse_layout(source)
    if not layout:
        content = source
    # It is possible to have an inout block without anything.
    (inout, remaining) = extract_tokens(content, ("?o", ";"))
    if inout:
        return (GlslBlockInOut(layout, inout), remaining)
    # Scoped version first.
    (inout, type_name, scope, name, intermediate) = extract_tokens(content, ("?o", "?n", "?{", "?n"))
    if inout and type_name and scope and name:
        members = glsl_parse_member_list(scope)
        if not members[0]:
            raise RuntimeError("wat?")
        if not members:
            raise RuntimeError("empty member list for inout struct")
        # May have an array.
        (size, remaining) = extract_tokens(intermediate, ("[", "?u", "]", ";"))
        if size:
            return (GlslBlockInOutStruct(layout, inout, type_name, members, name, size), remaining)
        # Did not have an array.
        (terminator, remaining) = extract_tokens(intermediate, "?|;")
        if terminator:
            return (GlslBlockInOutStruct(layout, inout, type_name, members, name), remaining)
    # Regular inout.
    (inout, typeid, name, remaining) = extract_tokens(content, ("?o", "?t", "?n", ";"))
    if not inout or not typeid or not name:
        return (None, source)
    return (GlslBlockInOutTyped(layout, inout, typeid, name), remaining)
예제 #3
0
def glsl_parse_layout(source):
    """Parse layout block."""
    (scope, remaining) = extract_tokens(source, ("layout", "?("))
    if not scope:
        return (None, source)
    lst = []
    while scope:
        (location, assignment, index, intermediate) = extract_tokens(scope, ("?|location", "?=", "?u"))
        if location and assignment and index:
            lst += [[location, assignment, index]]
            scope = intermediate
            continue
        primitive_selector = "?" + "|".join(get_list_primitives())
        (primitive, intermediate) = extract_tokens(scope, (primitive_selector,))
        if primitive:
            lst += [[primitive]]
            scope = intermediate
            continue
        (max_vertices, assignment, amount, intermediate) = extract_tokens(scope, ("?|max_vertices", "?=", "?u"))
        if max_vertices and assignment and amount:
            lst += [[max_vertices, assignment, amount]]
            scope = intermediate
            continue
        (comma, intermediate) = extract_tokens(scope, "?|,")
        if comma:
            scope = intermediate
            continue
        raise RuntimeError("unknown layout directive %s" % (str(list(map(str, scope)))))
    return (GlslBlockLayout(lst), remaining)
예제 #4
0
def glsl_parse_parameter(source):
    """Parse parameter block."""
    (inout, typeid, content) = extract_tokens(source, ("?o", "?t"))
    if not inout:
        (typeid, content) = extract_tokens(source, ("?t"))
        if not typeid:
            return (None, source)
    (assignment, remaining) = glsl_parse_assignment(content, False)
    if not assignment:
        raise RuntimeError("could not parse assignment from '%s'" %
                           (str(list(map(str, content)))))
    if inout and (not inout.format(False) in ("in", "inout", "out")):
        raise RuntimeError("invalid inout directive for parameter: '%s'" %
                           (inout.format(False)))
    return (GlslBlockParameter(inout, typeid, assignment), remaining)
예제 #5
0
def glsl_parse_pervertex(source):
    """Parse inout block."""
    (inout, scope,
     remaining) = extract_tokens(source, ("?o", "gl_PerVertex", "?{", ";"))
    if (not inout) or (not scope):
        return (None, source)
    # Split scope into elements.
    lst = []
    while scope:
        (typeid, name, content) = extract_tokens(scope, ("?t", "?n", ";"))
        if not typeid or not name:
            return (None, source)
        lst += [(typeid, name)]
        scope = content
    return (GlslBlockPerVertex(inout, lst), remaining)
예제 #6
0
def glsl_parse_return(source):
    """Parse return block."""
    (ret, content) = extract_tokens(source, "?|return")
    if not ret:
        return (None, source)
    (statements, remaining) = glsl_parse_statements(content, ";")
    if not statements:
        return (None, source)
    return (GlslBlockReturn(statements), remaining)
예제 #7
0
def glsl_parse_unary(source):
    """Parse unary block."""
    # Try prefix unary.
    (operator, name, terminator, remaining) = extract_tokens(source, ("?p", "?n", "?;"))
    if operator in g_allowed_operators:
        (statement, discarded) = glsl_parse_statement([operator, name, terminator])
        if discarded:
            raise RuntimeError("discarded elements in prefix unary")
        return (GlslBlockUnary(statement), remaining)
    # Try postfix unary.
    (name, operator, terminator, remaining) = extract_tokens(source, ("?n", "?p", "?;"))
    if operator in g_allowed_operators:
        (statement, discarded) = glsl_parse_statement([name, operator, terminator])
        if discarded:
            raise RuntimeError("discarded elements in postfix unary")
        return (GlslBlockUnary(statement), remaining)
    # No match.
    return (None, source)
예제 #8
0
def glsl_parse_flow(source):
    """Parse flow block."""
    (name, terminator, remaining) = extract_tokens(source, ("?n", "?;"))
    if name in ("break", "continue"):
        (statement, discarded) = glsl_parse_statement([name, terminator])
        if discarded:
            raise RuntimeError(
                "discarded elements after flow control statement")
        return (GlslBlockFlow(statement), remaining)
    return (None, source)
예제 #9
0
def glsl_parse_function(source):
    """Parse function block."""
    (typeid, name, param_scope, content) = extract_tokens(source, ("?t", "?n", "?("))
    if (not typeid) or (not name) or (param_scope is None):
        return (None, source)
    parameters = glsl_parse_parameter_list(param_scope)
    if parameters is None:
        return (None, source)
    (scope, remaining) = glsl_parse_scope(content)
    if not scope:
        return (None, source)
    return (GlslBlockFunction(typeid, name, parameters, scope), remaining)
예제 #10
0
def glsl_parse_uniform(source):
    """Parse preprocessor block."""
    (layout, content) = glsl_parse_layout(source)
    if not layout:
        content = source
    # Extract actual uniform definition.
    (typeid, content) = extract_tokens(content, ("uniform", "?t"))
    if not typeid:
        return (None, source)
    # Try array types.
    (name, size, content) = extract_tokens(content, ("?n", "[", "?u", "]", ";"))
    if name and size:
        return (GlslBlockUniform(layout, typeid, size, name), content)
    (size, name, content) = extract_tokens(content, ("[", "?u", "]", "?n", ";"))
    if size and name:
        return (GlslBlockUniform(layout, typeid, size, name), content)
    # No array types, default to just name.
    (name, content) = extract_tokens(content, ("?n", ";"))
    if not name:
        return (None, source)
    return (GlslBlockUniform(layout, typeid, size, name), content)
예제 #11
0
def glsl_parse_assignment(source, explicit=True):
    """Parse assignment block."""
    # Must have name. Name must not be just 'return'.
    (name, content) = extract_tokens(source, ("?n", ))
    if (not name) or (name == "return"):
        return (None, source)
    # Completely empty assignment. Acceptable if not in explicit mode.
    if (not content) and (not explicit):
        return (GlslBlockAssignment(name, None, None, None), content)
    # Empty assignment.
    (terminator, intermediate) = extract_tokens(content, ("?,|;", ))
    if terminator:
        (statement,
         remaining) = glsl_parse_statement([terminator] + intermediate)
        return (GlslBlockAssignment(name, None, None, statement), remaining)
    # Non-empty assignment. Gather index and swizzle.
    lst = []
    while True:
        (index_scope, remaining) = extract_tokens(content, ("?[", ))
        if index_scope:
            lst += [GlslParen("[")] + index_scope + [GlslParen("]")]
            content = remaining
            continue
        (access, remaining) = extract_tokens(content, ("?a", ))
        if access:
            lst += [access]
            content = remaining
            continue
        (operator, remaining) = extract_tokens(content, ("?=", ))
        if operator:
            content = remaining
            break
        # Can't be an assignment.
        return (None, source)
    # Gather statement.
    (statement, remaining) = glsl_parse_statement(content, explicit)
    if not statement:
        return (None, source)
    return (GlslBlockAssignment(name, lst, operator, statement), remaining)
예제 #12
0
def glsl_parse_struct(source):
    """Parse struct block."""
    (type_name, scope, content) = extract_tokens(source,
                                                 ("struct", "?n", "?{"))
    if not type_name:
        return (None, source)
    # Get potential name and size.
    (name, size, remaining) = extract_tokens(content,
                                             ("?n", "[", "?i", "]", ";"))
    if not name:
        size = None
        (name, remaining) = extract_tokens(content, ("?n", ";"))
        if not name:
            name = None
            (terminator, remaining) = extract_tokens(content, ("?;", ))
            if not terminator:
                return (None, source)
    # Parse members
    members = glsl_parse_member_list(scope)
    if not members:
        raise RuntimeError("empty member list for struct")
    return (GlslBlockStruct(type_name, members, name, size), remaining)
예제 #13
0
def glsl_parse_call(source):
    """Parse call block."""
    (name, scope, terminator,
     remaining) = extract_tokens(source, ("?n", "?(", "?;"))
    if not name:
        return (None, source)
    if scope:
        (statements, scope_remaining) = glsl_parse_statements(scope)
        if not statements:
            return (None, source)
        if scope_remaining:
            raise RuntimeError(
                "call scope cannot have remaining elements: '%s'" %
                str(scope_remaining))
        return (GlslBlockCall(name, statements, terminator), remaining)
    return (GlslBlockCall(name, [], terminator), remaining)
예제 #14
0
def glsl_parse_declaration(source):
    """Parse declaration block."""
    (typeid, content) = extract_tokens(source, ("?t",))
    if not typeid:
        return (None, source)
    # Loop until nothing found.
    lst = []
    while True:
        (assignment, remaining) = glsl_parse_assignment(content)
        if assignment:
            lst += [assignment]
            # Might have been last assignement.
            if assignment.getTerminator() == ";":
                return (GlslBlockDeclaration(typeid, lst), remaining)
            # Otherwise keep going.
            content = remaining
            continue
        # Unknown element, not a valid declaration.
        return (None, source)
예제 #15
0
def glsl_parse_scope(source, explicit=True):
    """Parse scope block."""
    (content, remaining) = extract_tokens(source, ("?{", ))
    if not (content is None):
        return (GlslBlockScope(glsl_parse_content(content),
                               explicit), remaining)
    # If explicit scope is not expected, try legal one-statement scopes.
    elif not explicit:
        (block, remaining) = glsl_parse_flow(source)
        if block:
            return (GlslBlockScope([block], explicit), remaining)
        (block, remaining) = glsl_parse_unary(source)
        if block:
            return (GlslBlockScope([block], explicit), remaining)
        (block, remaining) = glsl_parse_assignment(source)
        if block:
            return (GlslBlockScope([block], explicit), remaining)
    # No scope found.
    return (None, source)