1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
# -*- coding: utf-8 -*-
# Copyright (c) Vispy Development Team. All Rights Reserved.
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
from __future__ import division
import re
# regular expressions for parsing GLSL
re_version_pragma = r'#version\s+(\d+)(.*)?(//.*)?'
re_type = r'(?:void|int|float|vec2|vec3|vec4|mat2|mat3|mat4|\
sampler1D|sampler2D|sampler3D)'
re_identifier = r'(?:[a-zA-Z_][\w_]*)'
# variable qualifiers
re_qualifier = r'(const|uniform|attribute|varying|in|out|inout)'
# template variables like
# $func_name
re_template_var = (r"(?:(?:\$" + re_identifier + r")|(?:\$\{" +
re_identifier + r"\}))")
# function names may be either identifier or template var
re_func_name = r"(" + re_identifier + "|" + re_template_var + ")"
# type and identifier like "vec4 var_name"
re_declaration = "(?:(" + re_type + r")\s+(" + re_identifier + "))"
# qualifier, type, and identifier like "uniform vec4 var_name"
# qualifier is optional.
# may include multiple names like "attribute float x, y, z"
re_prog_var_declaration = ("(?:" + re_qualifier + r"?\s*(" + re_type +
r")\s+(" + re_identifier + r"(\s*,\s*(" +
re_identifier + "))*))")
# list of variable declarations like "vec4 var_name, float other_var_name"
re_arg_list = "(" + re_declaration + r"(?:,\s*" + re_declaration + ")*)?"
# function declaration like "vec4 function_name(float x, float y)"
re_func_decl = ("(" + re_type + r")\s+" + re_func_name + r"\s*\((void|" +
re_arg_list + r")\)")
# anonymous variable declarations may or may not include a name:
# "vec4" or "vec4 var_name"
re_anon_decl = "(?:(" + re_type + r")(?:\s+" + re_identifier + ")?)"
# list of anonymous declarations
re_anon_arg_list = "(" + re_anon_decl + r"(?:,\s*" + re_anon_decl + ")*)?"
# function prototype declaration like
# "vec4 function_name(float, float);"
re_func_prot = ("(" + re_type + r")\s+" + re_func_name + r"\((void|" +
re_anon_arg_list + r")\)\s*;")
def parse_function_signature(code):
"""
Return the name, arguments, and return type of the first function
definition found in *code*. Arguments are returned as [(type, name), ...].
"""
m = re.search(r"^\s*" + re_func_decl + r"\s*{", code, re.M)
if m is None:
print(code)
raise Exception("Failed to parse function signature. "
"Full code is printed above.")
rtype, name, args = m.groups()[:3]
if args == 'void' or args.strip() == '':
args = []
else:
args = [tuple(arg.strip().split(' ')) for arg in args.split(',')]
return name, args, rtype
def find_functions(code):
"""
Return a list of (name, arguments, return type) for all function
definition2 found in *code*. Arguments are returned as [(type, name), ...].
"""
regex = r"^\s*" + re_func_decl + r"\s*{"
funcs = []
while True:
m = re.search(regex, code, re.M)
if m is None:
return funcs
rtype, name, args = m.groups()[:3]
if args == 'void' or args.strip() == '':
args = []
else:
args = [tuple(arg.strip().split(' ')) for arg in args.split(',')]
funcs.append((name, args, rtype))
code = code[m.end():]
def find_prototypes(code):
"""
Return a list of signatures for each function prototype declared in *code*.
Format is [(name, [args], rtype), ...].
"""
prots = []
lines = code.split('\n')
for line in lines:
m = re.match(r"\s*" + re_func_prot, line)
if m is not None:
rtype, name, args = m.groups()[:3]
if args == 'void' or args.strip() == '':
args = []
else:
args = [tuple(arg.strip().split(' '))
for arg in args.split(',')]
prots.append((name, args, rtype))
return prots
def find_program_variables(code):
"""
Return a dict describing program variables::
{'var_name': ('uniform|attribute|varying', type), ...}
"""
vars = {}
lines = code.split('\n')
for line in lines:
m = re.match(r"\s*" + re_prog_var_declaration + r"\s*(=|;)", line)
if m is not None:
vtype, dtype, names = m.groups()[:3]
for name in names.split(','):
vars[name.strip()] = (vtype, dtype)
return vars
def find_template_variables(code):
"""
Return a list of template variables found in *code*.
"""
return re.findall(re_template_var, code)
|