class_docstr: Shader program object
  
  A Program is an object to which shaders can be attached and linked to
  create the final program.
  
  Uniforms and attributes can be set using indexing: e.g.
  ``program['a_pos'] = pos_data`` and ``program['u_color'] = (1, 0, 0)``.
  
  Parameters
  ----------
  vert : str
      The vertex shader to be used by this program
  frag : str
      The fragment shader to be used by this program
  count : int (optional)
      The program will prepare a structured vertex buffer of count
      vertices. All attributes set using ``prog['attr'] = X`` will
      be combined into a structured vbo with interleaved elements, which
      is more efficient than having one vbo per attribute.
  
  Notes
  -----
  If several shaders are specified, only one can contain the main
  function. OpenGL ES 2.0 does not support a list of shaders.
class_docstr_tok: ["Shader","program","object","A","Program","is","an","object","to","which","shaders","can","be","attached","and","linked","to","create","the","final","program",".","Uniforms","and","attributes","can","be","set","using","indexing",":","e.g",".","``","program","[","'a_pos","'","]","=","pos_data","``","and","``","program","[","'u_color","'","]","=","(","1",",","0",",","0",")","``",".","Parameters","--","--","--","--","--","vert",":","str","The","vertex","shader","to","be","used","by","this","program","frag",":","str","The","fragment","shader","to","be","used","by","this","program","count",":","int","(","optional",")","The","program","will","prepare","a","structured","vertex","buffer","of","count","vertices",".","All","attributes","set","using","``","prog","[","'attr","'","]","=","X","``","will","be","combined","into","a","structured","vbo","with","interleaved","elements",",","which","is","more","efficient","than","having","one","vbo","per","attribute",".","Notes","--","--","-","If","several","shaders","are","specified",",","only","one","can","contain","the","main","function",".","OpenGL","ES","2.0","does","not","support","a","list","of","shaders","."]
docstr: Parse uniforms, attributes and varyings from the source code.
docstr_tok: ["Parse","uniforms",",","attributes","and","varyings","from","the","source","code","."]
code: def _parse_variables_from_code(self, update_variables=True):
      """Parse uniforms, attributes and varyings from the source code."""
      # Get one string of code with comments removed
      code = "\n\n".join([sh.code for sh in self._shaders])
      code = re.sub(r"(.*)(//.*)", r"\1", code, re.M)
  
      # Parse uniforms, attributes and varyings
      self._code_variables = {}
      for kind in (
          "uniform",
          "attribute",
          "varying",
          "const",
          "in",
          "out",
      ):
          # pick regex for the correct kind of var
          reg = REGEX_VAR[kind]
  
          # treat *in* like attribute, *out* like varying
          if kind == "in":
              kind = "attribute"
          elif kind == "out":
              kind = "varying"
  
          for m in re.finditer(reg, code):
              gtype = m.group("type")
              size = int(m.group("size")) if m.group("size") else -1
              this_kind = kind
              if size >= 1:
                  # uniform arrays get added both as individuals and full
                  for i in range(size):
                      name = "%s[%d]" % (m.group("name"), i)
                      self._code_variables[name] = kind, gtype, name, -1
                  this_kind = "uniform_array"
              name = m.group("name")
              self._code_variables[name] = this_kind, gtype, name, size
  
      # Now that our code variables are up-to date, we can process
      # the variables that were set but yet unknown.
      if update_variables:
          self._process_pending_variables()
  
imports: import re
  import numpy
  from .globject import GLObject
  from .buffer import VertexBuffer, IndexBuffer, DataBuffer
  from .texture import BaseTexture, Texture2D, Texture3D, Texture1D, TextureCube
  from ..util import logger
  from .util import check_enum
  from .context import get_current_canvas
  from .preprocessor import preprocess
label_desc: Use image node_id 5 for calling the Program obj's underlying member method code with example usage: obj._parse_variables_from_code(update_variables) without return types