def _parse()

in static/downloads/ezt.py [0:0]


  def _parse(self, reader, for_names=None, file_args=(), base_printer=None):
    """text -> string object containing the template.

    This is a private helper function doing the real work for method parse.
    It returns the parsed template as a 'program'.  This program is a sequence
    made out of strings or (function, argument) 2-tuples.

    Note: comment directives [# ...] are automatically dropped by _re_parse.
    """

    filename = reader.filename()
    # parse the template program into: (TEXT NEWLINE DIRECTIVE BRACKET)* TEXT
    parts = _re_parse.split(reader.text)

    program = [ ]
    stack = [ ]
    if not for_names:
      for_names = [ ]

    if base_printer is None:
      base_printer = ()
    printers = [ base_printer ]

    one_newline_copied = False
    line_number = 1
    for i in range(len(parts)):
      piece = parts[i]
      which = i % 4  # discriminate between: TEXT NEWLINE DIRECTIVE BRACKET
      if which == 0:
        # TEXT. append if non-empty.
        if piece:
          if self.compress_whitespace:
            piece = _re_whitespace.sub(' ', piece)
          program.append(piece)
          one_newline_copied = False
      elif which == 1:
        # NEWLINE. append unless compress_whitespace requested
        if piece:
          line_number += 1
          if self.compress_whitespace:
            if not one_newline_copied:
              program.append('\n')
              one_newline_copied = True
          else:
            program.append(piece)
      elif which == 3:
        # BRACKET directive. append '[' if present.
        if piece:
          program.append('[')
          one_newline_copied = False
      elif piece:
        # DIRECTIVE is present.
        one_newline_copied = False
        args = _re_args.findall(piece)
        cmd = args[0]
        if cmd == 'else':
          if len(args) > 1:
            raise ArgCountSyntaxError(str(args[1:]), filename, line_number)
          ### check: don't allow for 'for' cmd
          idx = stack[-1][1]
          true_section = program[idx:]
          del program[idx:]
          stack[-1][3] = true_section
        elif cmd == 'end':
          if len(args) > 1:
            raise ArgCountSyntaxError(str(args[1:]), filename, line_number)
          # note: true-section may be None
          try:
            cmd, idx, args, true_section, start_line_number = stack.pop()
          except IndexError:
            raise UnmatchedEndError(None, filename, line_number)
          else_section = program[idx:]
          if cmd == 'format':
            printers.pop()
          else:
            func = getattr(self, '_cmd_' + re.sub('-', '_', cmd))
            program[idx:] = [ (func, (args, true_section, else_section),
                               filename, line_number) ]
            if cmd == 'for':
              for_names.pop()
        elif cmd in _block_cmds:
          if len(args) > _block_cmd_specs[cmd] + 1:
            raise ArgCountSyntaxError(str(args[1:]), filename, line_number)
          ### this assumes arg1 is always a ref unless cmd is 'define'
          if cmd != 'define':
            args[1] = _prepare_ref(args[1], for_names, file_args)

          # handle arg2 for the 'is' command
          if cmd == 'is':
            args[2] = _prepare_ref(args[2], for_names, file_args)
          elif cmd == 'for':
            for_names.append(args[1][0])  # append the refname
          elif cmd == 'format':
            if args[1][0]:
              raise BadFormatConstantError(str(args[1:]), filename, line_number)
            printers.append(_parse_format(args[1][1]))

          # remember the cmd, current pos, args, and a section placeholder
          stack.append([cmd, len(program), args[1:], None, line_number])
        elif cmd == 'include' or cmd == 'insertfile':
          is_insertfile = (cmd == 'insertfile')
          # extra arguments are meaningless when using insertfile
          if is_insertfile and len(args) != 2:
            raise ArgCountSyntaxError(str(args), filename, line_number)
          if args[1][0] == '"':
            include_filename = args[1][1:-1]
            if is_insertfile:
              program.append(reader.read_other(include_filename).text)
            else:
              f_args = [ ]
              for arg in args[2:]:
                f_args.append(_prepare_ref(arg, for_names, file_args))
              program.extend(self._parse(reader.read_other(include_filename),
                                         for_names, f_args, printers[-1]))
          else:
            if len(args) != 2:
              raise ArgCountSyntaxError(str(args), filename, line_number)
            if is_insertfile:
              cmd = self._cmd_insertfile
            else:
              cmd = self._cmd_include
            program.append((cmd,
                            (_prepare_ref(args[1], for_names, file_args),
                             reader, printers[-1]), filename, line_number))
        elif cmd == 'if-any':
          f_args = [ ]
          for arg in args[1:]:
            f_args.append(_prepare_ref(arg, for_names, file_args))
          stack.append(['if-any', len(program), f_args, None, line_number])
        else:
          # implied PRINT command
          if len(args) > 1:
            f_args = [ ]
            for arg in args:
              f_args.append(_prepare_ref(arg, for_names, file_args))
            program.append((self._cmd_subst,
                            (printers[-1], f_args[0], f_args[1:]),
                            filename, line_number))
          else:
            valref = _prepare_ref(args[0], for_names, file_args)
            program.append((self._cmd_print, (printers[-1], valref),
                            filename, line_number))

    if stack:
      raise UnclosedBlocksError('Block opened at line %s' % stack[-1][4],
                                filename=filename)
    return program