예제 #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_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,
                                        ("?|binding|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(map(str, scope))))
    return (GlslBlockLayout(lst), remaining)
예제 #3
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)
예제 #4
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)
예제 #5
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(map(str, scope))))
    return (GlslBlockLayout(lst), remaining)
예제 #6
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)
예제 #7
0
def glsl_parse_array(source, explicit=True):
    """Parse array literal block."""
    # Must have name. Name must not be just 'return'.
    (typeid, bracket_scope, paren_scope,
     content) = extract_tokens(source, ("?t", "?[", "?("))
    if not typeid:
        return (None, source)
    # Bracket scope must be empty.
    if bracket_scope and (len(bracket_scope != 1) or
                          (not is_glsl_type(bracket_scope[0]))):
        raise RuntimeError(
            "illegal contents for array literal bracket scope: %s" %
            (str(map(lambda x: str(x), bracket_scope))))
    # Parse paren scope.
    statements = []
    while paren_scope:
        (statement, following) = glsl_parse_statement(paren_scope, False)
        if statement:
            statements += [statement]
            paren_scope = following
            continue
        raise RuntimeError(
            "remaining elements cannot be parsed into a statement: %s" %
            (str(map(lambda x: str(x), paren_scope))))
    # Look for a terminator.
    (terminator, remaining) = extract_tokens(content, "?,|;")
    if terminator:
        return (GlslBlockArray(typeid, statements, terminator), remaining)
    # Return without terminator.
    return (GlslBlockArray(typeid, statements, None), content)
예제 #8
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(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)
예제 #9
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)
예제 #10
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)
예제 #11
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)
예제 #12
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)
예제 #13
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)
예제 #14
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)
예제 #15
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)
예제 #16
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)
예제 #17
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)
예제 #18
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)
예제 #19
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)
예제 #20
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)
예제 #21
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)
예제 #22
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)
예제 #23
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, None), content)
    # Empty assignment.
    (terminator, intermediate) = extract_tokens(content, ("?,|;",))
    if terminator:
        (statement, remaining) = glsl_parse_statement([terminator] + intermediate)
        return (GlslBlockAssignment(name, None, None, statement, None), remaining)
    # Non-empty assignment. Gather index and swizzle.
    modifiers = []
    while True:
        (index_scope, remaining) = extract_tokens(content, ("?[",))
        if index_scope:
            modifiers += [GlslParen("[")] + index_scope + [GlslParen("]")]
            content = remaining
            continue
        (access, remaining) = extract_tokens(content, ("?a",))
        if access:
            modifiers += [access]
            content = remaining
            continue
        (operator, remaining) = extract_tokens(content, ("?=",))
        if operator:
            content = remaining
            break
        # Can't be an assignment.
        return (None, source)
    # Try scope assignment.
    (scope, intermediate) = extract_tokens(content, ("?{",))
    if scope:
        (statements, discard) = glsl_parse_statements(scope)
        if (not statements) or discard:
            raise RuntimeError("error parsing statements from assignment scope")
        (terminator, remaining) = extract_tokens(intermediate, ("?,|;",))
        if terminator:
            return (GlslBlockAssignment(name, modifiers, operator, statements, terminator), remaining)
    # Try statement assignment.
    (statement, remaining) = glsl_parse_statement(content, explicit)
    if statement:
        return (GlslBlockAssignment(name, modifiers, operator, statement, None), remaining)
    # Not a valid assignment.
    return (None, source)
예제 #24
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)
예제 #25
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)
예제 #26
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)
예제 #27
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)
예제 #28
0
def glsl_parse_member(source):
    """Parse member block."""
    (typeid, name, remaining) = extract_tokens(source, ("?t", "?n", ";"))
    if not typeid:
        return (None, source)
    return (GlslBlockMember(typeid, name), remaining)
예제 #29
0
def glsl_parse_precision(source):
    """Parse precision block."""
    (typeid, remaining) = extract_tokens(source, ("precision", "?t", ";"))
    if typeid:
        return (GlslBlockPrecision(typeid), remaining)
    return (None, source)
예제 #30
0
def glsl_parse_member(source):
    """Parse member block."""
    (typeid, name, remaining) = extract_tokens(source, ("?t", "?n", ";"))
    if not typeid:
        return (None, source)
    return (GlslBlockMember(typeid, name), remaining)