Exemple #1
0
def checkBalancedParens(str, refs):
    m = RE_BRACES.search(str)
    stack = []
    try:
        while m:
            if m.group(0) == '{': stack.append(m)
            else: stack.pop()
            m = RE_BRACES.search(str, m.end())
    except IndexError:
        row, _ = calcRowCol(str, m.start())
        try:
            info = refs[row]
        except KeyError:
            info = None
        raise spyceException.spyceSyntaxError("unbalanced open brace '{'",
                                              info)
    if stack:
        m = stack[-1]
        row, _ = calcRowCol(str, m.start())
        try:
            info = refs[row]
        except KeyError:
            info = None
        raise spyceException.spyceSyntaxError("unbalanced close brace '}'",
                                              info)
Exemple #2
0
class spyceTagChecker:
    def __init__(self, server):
        self._server = server
        self._taglibs = {}
        self._stack = []

    def loadLib(self, libname, libfrom, libas, rel_file, info=None):
        if not libas: libas = libname
        try:
            self._taglibs[(libname, libfrom)] = \
              self._server.loadModule(libname, libfrom, rel_file)(libas)
        except (SyntaxError, TypeError):
            raise
        except:
            raise spyceException.spyceSyntaxError(
                'unable to load module: %s' % libname, info)

    def startTag(self, (libname, libfrom), name, attrs, pair, info):
        lib = self._taglibs[(libname, libfrom)]
        try:
            tag = lib.getTag(name, attrs, pair, None)
        except:
            raise spyceException.spyceSyntaxError(
                'unknown tag "%s:%s"' % (libname, name), info)
        try:
            error = tag.syntax()
        except spyceTagSyntaxException, e:
            raise spyceException.spyceSyntaxError(str(e), info)
Exemple #3
0
def emitPython(out, bracedPythonCode, spyceRefs):
    out = LineWriter(out)
    spyceRefs2 = {}
    braceConv = BraceConverter(out)

    def eatToken(type,
                 string,
                 begin,
                 end,
                 _,
                 out=out,
                 braceConv=braceConv,
                 spyceRefs=spyceRefs,
                 spyceRefs2=spyceRefs2):
        try:
            beginrow, _ = begin
            line1 = out.lineno
            braceConv.emitToken(type, string)
            line2 = out.lineno
            if spyceRefs.has_key(beginrow):
                for l in range(line1, line2):
                    spyceRefs2[l] = spyceRefs[beginrow]
        except:
            raise spyceException.spyceSyntaxError(sys.exc_info()[0])

    try:
        tokenize.tokenize(StringIO(bracedPythonCode).readline, eatToken)
    except tokenize.TokenError, e:
        msg, (row, col) = e
        raise spyceException.spyceSyntaxError(msg)
 def processLambda(self):
   # collect lambda
   self.popToken()
   begin = self._tokenBegin
   lamb = ''
   depth = 1
   while self._tokenType!=T_EOF:
     if self._tokenType in [T_END,]:
       depth = depth - 1
       if not depth: break
       lamb = lamb + self._tokenText
     elif self._tokenType in [T_EVAL, T_STMT, T_CHUNK, T_CHUNKG, T_DIRECT, T_LAMBDA]:
       depth = depth + 1
       lamb = lamb + self._tokenText
     elif self._tokenType==T_CMNT:
       self.processComment()
     else:
       lamb = lamb + self._tokenText
     end = self._tokenEnd
     self.popToken()
   # process lambda
   lamb = string.split(lamb, ':')
   try:
     params = lamb[0]
     memoize = 0
     if params and params[0]=='!':
       params = params[1:]
       memoize = 1
     lamb = string.join(lamb[1:],':')
   except:
     raise spyceException.spyceSyntaxError('invalid spyce lambda', (begin, end, lamb, self._curfile))
   self._load_spylambda = 1
   lamb = 'spylambda.define(%s,%s,%d)' % (`string.strip(params)`, `lamb`, memoize)
   return lamb
Exemple #5
0
 def loadLib(self, libname, libfrom, libas, rel_file, info=None):
     if not libas:
         libas = libname
     try:
         self._taglibs[(libname, libfrom)] = self._server.loadModule(libname, libfrom, rel_file)(libas)
     except (SyntaxError, TypeError):
         raise
     except:
         raise spyceException.spyceSyntaxError("unable to load module: %s" % libname, info)
Exemple #6
0
 def loadLib(self, libname, libfrom, libas, rel_file, info=None):
     if not libas: libas = libname
     try:
         self._taglibs[(libname, libfrom)] = \
           self._server.loadModule(libname, libfrom, rel_file)(libas)
     except (SyntaxError, TypeError):
         raise
     except:
         raise spyceException.spyceSyntaxError(
             'unable to load module: %s' % libname, info)
def checkBalancedParens(str, refs):
  m = RE_BRACES.search(str)
  stack = []
  try:
    while m:
      if m.group(0)=='{': stack.append(m)
      else: stack.pop()
      m = RE_BRACES.search(str, m.end())
  except IndexError: 
    row, _ = calcRowCol(str, m.start())
    try: info = refs[row]
    except KeyError: info =None
    raise spyceException.spyceSyntaxError("unbalanced open brace '{'", info)
  if stack:
    m = stack[-1]
    row, _ = calcRowCol(str, m.start())
    try: info = refs[row]
    except KeyError: info =None
    raise spyceException.spyceSyntaxError("unbalanced close brace '}'", info)
 def eatToken(type, string, begin, end, _, out=out, braceConv=braceConv, spyceRefs=spyceRefs, spyceRefs2=spyceRefs2):
   try:
     beginrow, _ = begin
     line1 = out.lineno
     braceConv.emitToken(type, string)
     line2 = out.lineno
     if spyceRefs.has_key(beginrow):
       for l in range(line1, line2):
         spyceRefs2[l] = spyceRefs[beginrow]
   except:
     raise spyceException.spyceSyntaxError(sys.exc_info()[0])
Exemple #9
0
 def processChunk(self, globalChunk=0):
     # collect chunk
     self.popToken()
     begin = self._tokenBegin
     chunk = ''
     while self._tokenType not in [T_END, T_EOF]:
         if self._tokenType == T_TEXT:
             chunk = chunk + self._tokenText
         elif self._tokenType == T_LAMBDA:
             chunk = chunk + self.processLambda()
         else:
             self.processUnexpected()
         end = self._tokenEnd
         self.popToken()
     chunk = string.split(chunk, '\n')
     # eliminate initial blank lines
     brow, bcol = begin
     while chunk and not string.strip(chunk[0]):
         chunk = chunk[1:]
         brow = brow + 1
         bcol = 0
     begin = brow, bcol
     if not chunk: self.processUnexpected()
     # outdent chunk based on first line
     # note: modifies multi-line strings having more spaces than first line outdent
     #    by removing outdent number of spaces at the beginning of each line.
     #    -- difficult to deal with efficiently (without parsing python) so just
     #    don't do this!
     outdent = len(chunk[0]) - len(string.lstrip(chunk[0]))
     for i in range(len(chunk)):
         if string.strip(chunk[i][:outdent]):
             chunk[i] = ' ' * outdent + chunk[i]
     chunk = map(lambda l, outdent=outdent: l[outdent:], chunk)
     chunk = string.join(chunk, '\n')
     # add chunk block at ast
     if chunk:
         try:
             self._ast.addCodeIndented(chunk,
                                       (begin, end, chunk, self._curfile),
                                       globalChunk)
         except tokenize.TokenError, e:
             msg, _ = e
             raise spyceException.spyceSyntaxError(
                 msg, (begin, end, chunk, self._curfile))
Exemple #10
0
 def eatToken(type,
              string,
              begin,
              end,
              _,
              out=out,
              braceConv=braceConv,
              spyceRefs=spyceRefs,
              spyceRefs2=spyceRefs2):
     try:
         beginrow, _ = begin
         line1 = out.lineno
         braceConv.emitToken(type, string)
         line2 = out.lineno
         if spyceRefs.has_key(beginrow):
             for l in range(line1, line2):
                 spyceRefs2[l] = spyceRefs[beginrow]
     except:
         raise spyceException.spyceSyntaxError(sys.exc_info()[0])
def emitPython(out, bracedPythonCode, spyceRefs):
  out = LineWriter(out)
  spyceRefs2 = {}
  braceConv = BraceConverter(out)
  def eatToken(type, string, begin, end, _, out=out, braceConv=braceConv, spyceRefs=spyceRefs, spyceRefs2=spyceRefs2):
    try:
      beginrow, _ = begin
      line1 = out.lineno
      braceConv.emitToken(type, string)
      line2 = out.lineno
      if spyceRefs.has_key(beginrow):
        for l in range(line1, line2):
          spyceRefs2[l] = spyceRefs[beginrow]
    except:
      raise spyceException.spyceSyntaxError(sys.exc_info()[0])
  try:
    tokenize.tokenize(StringIO(bracedPythonCode).readline, eatToken)
  except tokenize.TokenError, e:
    msg, (row, col) = e
    raise spyceException.spyceSyntaxError(msg)
Exemple #12
0
 def processLambda(self):
     # collect lambda
     self.popToken()
     begin = self._tokenBegin
     lamb = ''
     depth = 1
     while self._tokenType != T_EOF:
         if self._tokenType in [
                 T_END,
         ]:
             depth = depth - 1
             if not depth: break
             lamb = lamb + self._tokenText
         elif self._tokenType in [
                 T_EVAL, T_STMT, T_CHUNK, T_CHUNKG, T_DIRECT, T_LAMBDA
         ]:
             depth = depth + 1
             lamb = lamb + self._tokenText
         elif self._tokenType == T_CMNT:
             self.processComment()
         else:
             lamb = lamb + self._tokenText
         end = self._tokenEnd
         self.popToken()
     # process lambda
     lamb = string.split(lamb, ':')
     try:
         params = lamb[0]
         memoize = 0
         if params and params[0] == '!':
             params = params[1:]
             memoize = 1
         lamb = string.join(lamb[1:], ':')
     except:
         raise spyceException.spyceSyntaxError(
             'invalid spyce lambda', (begin, end, lamb, self._curfile))
     self._load_spylambda = 1
     lamb = 'spylambda.define(%s,%s,%d)' % ( ` string.strip(params) `, `
                                             lamb `, memoize)
     return lamb
 def processChunk(self, globalChunk=0):
   # collect chunk
   self.popToken()
   begin = self._tokenBegin
   chunk = ''
   while self._tokenType not in [T_END, T_EOF]:
     if self._tokenType==T_TEXT:
       chunk = chunk + self._tokenText
     elif self._tokenType==T_LAMBDA:
       chunk = chunk + self.processLambda()
     else: self.processUnexpected()
     end = self._tokenEnd
     self.popToken()
   chunk = string.split(chunk, '\n')
   # eliminate initial blank lines
   brow, bcol = begin
   while chunk and not string.strip(chunk[0]):
     chunk = chunk[1:]
     brow = brow + 1
     bcol = 0
   begin = brow, bcol
   if not chunk: self.processUnexpected()
   # outdent chunk based on first line
   # note: modifies multi-line strings having more spaces than first line outdent
   #    by removing outdent number of spaces at the beginning of each line.
   #    -- difficult to deal with efficiently (without parsing python) so just 
   #    don't do this!
   outdent = len(chunk[0]) - len(string.lstrip(chunk[0]))
   for i in range(len(chunk)):
     if string.strip(chunk[i][:outdent]):
       chunk[i] = ' '*outdent + chunk[i]
   chunk = map(lambda l, outdent=outdent: l[outdent:], chunk)
   chunk = string.join(chunk, '\n')
   # add chunk block at ast
   if chunk:
     try:
       self._ast.addCodeIndented(chunk, (begin, end, chunk, self._curfile), globalChunk)
     except tokenize.TokenError, e:
       msg, _ = e
       raise spyceException.spyceSyntaxError(msg, (begin, end, chunk, self._curfile) )
Exemple #14
0
 def finish(self):
   if self._stack:
     libname, libfrom, name, info = self._stack.pop()
     raise spyceException.spyceSyntaxError(
       'unmatched open tag', info)
Exemple #15
0
            raise spyceException.spyceSyntaxError(
                'unable to load module: %s' % libname, info)

    def startTag(self, (libname, libfrom), name, attrs, pair, info):
        lib = self._taglibs[(libname, libfrom)]
        try:
            tag = lib.getTag(name, attrs, pair, None)
        except:
            raise spyceException.spyceSyntaxError(
                'unknown tag "%s:%s"' % (libname, name), info)
        try:
            error = tag.syntax()
        except spyceTagSyntaxException, e:
            raise spyceException.spyceSyntaxError(str(e), info)
        if error:
            raise spyceException.spyceSyntaxError(error, info)
        if pair:
            self._stack.append((libname, libfrom, name, info))

    def endTag(self, (libname, libfrom), name, info):
        try:
            libname1, libfrom1, name1, info1 = self._stack.pop()
        except IndexError:
            raise spyceException.spyceSyntaxError('unmatched close tag', info)
        if (libname1, libfrom1, name1) != (libname, libfrom, name):
            raise spyceException.spyceSyntaxError(
                'unmatched close tag, expected <%s:%s>' % (libname1, name1),
                info)

    def finish(self):
        if self._stack:
Exemple #16
0
 def processUnexpected(self):
     raise spyceException.spyceSyntaxError(
         'unexpected token: "%s"' % self._tokenText,
         (self._tokenBegin, self._tokenEnd, self._tokenText, self._curfile))
Exemple #17
0
 def processDirective(self):
     # collect directive
     begin = self._tokenBegin
     self.popToken()
     directive = ''
     while self._tokenType not in [T_END, T_EOF]:
         if self._tokenType == T_TEXT:
             directive = directive + self._tokenText
         else:
             self.processUnexpected()
         end = self._tokenEnd
         self.popToken()
     directive = string.strip(directive)
     if not directive: self.processUnexpected()
     # process directives
     name, attrs = parseDirective(directive)
     if name == 'compact':
         compact_mode = COMPACT_FULL
         if attrs.has_key('mode'):
             mode = string.lower(attrs['mode'])
             if mode == 'off':
                 compact_mode = COMPACT_OFF
             elif mode == 'line':
                 compact_mode = COMPACT_LINE
             elif mode == 'space':
                 compact_mode = COMPACT_SPACE
             elif mode == 'full':
                 compact_mode = COMPACT_FULL
             else:
                 raise spyceException.spyceSyntaxError(
                     'invalid compacting mode "%s" specified' % mode,
                     (begin, end, directive, self._curfile))
         self._ast.addCompact(
             compact_mode,
             (begin, end, '<spyce compact directive>', self._curfile))
     elif name in ('module', 'import'):
         if not attrs.has_key('name') and not attrs.has_key('names'):
             raise spyceException.spyceSyntaxError(
                 'name or names attribute required',
                 (begin, end, directive, self._curfile))
         if attrs.has_key('names'):
             mod_names = filter(
                 None, map(string.strip, string.split(attrs['names'], ',')))
             for mod_name in mod_names:
                 self._ast.addModule(mod_name, None, None)
                 self._ast.addCode('%s.init()' % mod_name,
                                   (begin, end, directive, self._curfile))
         else:
             mod_name = attrs['name']
             mod_from = spyceUtil.extractValue(attrs, 'from')
             mod_as = spyceUtil.extractValue(attrs, 'as')
             mod_args = spyceUtil.extractValue(attrs, 'args', '')
             if mod_as: theName = mod_as
             else: theName = mod_name
             self._ast.addModule(mod_name, mod_from, mod_as)
             self._ast.addCode('%s.init(%s)' % (theName, mod_args),
                               (begin, end, directive, self._curfile))
     elif name in ('taglib', ):
         if not attrs.has_key('name') and not attrs.has_key('names'):
             raise spyceException.spyceSyntaxError(
                 'name or names attribute required',
                 (begin, end, directive, self._curfile))
         fullfile = os.path.join(self._curdir, self._curfile)
         if attrs.has_key('names'):
             taglib_names = filter(
                 None, map(string.strip, string.split(attrs['names'], ',')))
             for taglib_name in taglib_names:
                 self._tagChecker.loadLib(
                     taglib_name, None, None, fullfile,
                     (begin, end, directive, self._curfile))
                 self._ast.addTaglib(taglib_name)
                 self._load_taglib = 1
                 self._ast.addCode('taglib.load(%s)' % repr(taglib_name),
                                   (begin, end, directive, self._curfile))
         else:
             taglib_name = attrs['name']
             taglib_from = spyceUtil.extractValue(attrs, 'from')
             taglib_as = spyceUtil.extractValue(attrs, 'as')
             self._tagChecker.loadLib(
                 taglib_name, taglib_from, taglib_as, fullfile,
                 (begin, end, directive, self._curfile))
             self._ast.addTaglib(taglib_name, taglib_from, taglib_as)
             self._load_taglib = 1
             self._ast.addCode(
                 'taglib.load(%s, %s, %s)' %
                 (repr(taglib_name), repr(taglib_from), repr(taglib_as)),
                 (begin, end, directive, self._curfile))
     elif name == 'include':
         if not attrs.has_key('file'):
             raise spyceException.spyceSyntaxError(
                 'file attribute missing',
                 (begin, end, directive, self._curfile))
         filename = os.path.join(self._curdir, attrs['file'])
         f = None
         try:
             try:
                 f = open(filename)
                 buf = f.read()
             finally:
                 if f: f.close()
         except KeyboardInterrupt:
             raise
         except:
             raise spyceException.spyceSyntaxError(
                 'unable to open included file: %s' % filename,
                 (begin, end, directive, self._curfile))
         prev = (self._curdir, self._curfile, self._tokens, self._tokenType,
                 self._tokenText, self._tokenBegin, self._tokenEnd)
         self._curdir, self._curfile = os.path.dirname(filename), filename
         self._tokens = spyceTokenize4Parse(processMagic(buf))
         self.popToken()
         self.processSpyce()
         (self._curdir, self._curfile, self._tokens, self._tokenType,
          self._tokenText, self._tokenBegin, self._tokenEnd) = prev
     else:
         raise spyceException.spyceSyntaxError(
             'invalid spyce directive',
             (begin, end, directive, self._curfile))
 def processDirective(self):
   # collect directive
   begin = self._tokenBegin
   self.popToken()
   directive = ''
   while self._tokenType not in [T_END, T_EOF]:
     if self._tokenType==T_TEXT:
       directive = directive + self._tokenText
     else: self.processUnexpected()
     end = self._tokenEnd
     self.popToken()
   directive = string.strip(directive)
   if not directive: self.processUnexpected()
   # process directives
   name, attrs = parseDirective(directive)
   if name=='compact':
     compact_mode = COMPACT_FULL
     if attrs.has_key('mode'):
       mode = string.lower(attrs['mode'])
       if mode=='off':
         compact_mode = COMPACT_OFF
       elif mode=='line':
         compact_mode = COMPACT_LINE
       elif mode=='space':
         compact_mode = COMPACT_SPACE
       elif mode=='full':
         compact_mode = COMPACT_FULL
       else:
         raise spyceException.spyceSyntaxError('invalid compacting mode "%s" specified'%mode, (begin, end, directive, self._curfile))
     self._ast.addCompact(compact_mode, (begin, end, '<spyce compact directive>', self._curfile))
   elif name in ('module', 'import'):
     if not attrs.has_key('name') and not attrs.has_key('names'):
       raise spyceException.spyceSyntaxError('name or names attribute required', (begin, end, directive, self._curfile) )
     if attrs.has_key('names'):
       mod_names = filter(None, map(string.strip, string.split(attrs['names'],',')))
       for mod_name in mod_names:
         self._ast.addModule(mod_name, None, None)
         self._ast.addCode('%s.init()'%mod_name, (begin, end, directive, self._curfile))
     else:
       mod_name = attrs['name']
       mod_from = spyceUtil.extractValue(attrs, 'from')
       mod_as = spyceUtil.extractValue(attrs, 'as')
       mod_args = spyceUtil.extractValue(attrs, 'args', '')
       if mod_as: theName=mod_as
       else: theName=mod_name
       self._ast.addModule(mod_name, mod_from, mod_as)
       self._ast.addCode('%s.init(%s)'%(theName,mod_args), (begin, end, directive, self._curfile))
   elif name in ('taglib',):
     if not attrs.has_key('name') and not attrs.has_key('names'):
       raise spyceException.spyceSyntaxError('name or names attribute required', (begin, end, directive, self._curfile) )
     fullfile = os.path.join(self._curdir, self._curfile)
     if attrs.has_key('names'):
       taglib_names = filter(None, map(string.strip, string.split(attrs['names'],',')))
       for taglib_name in taglib_names:
         self._tagChecker.loadLib(taglib_name, None, None, fullfile, (begin, end, directive, self._curfile))
         self._ast.addTaglib(taglib_name)
         self._load_taglib = 1
         self._ast.addCode('taglib.load(%s)'%repr(taglib_name), (begin, end, directive, self._curfile))
     else:
       taglib_name = attrs['name']
       taglib_from = spyceUtil.extractValue(attrs, 'from')
       taglib_as = spyceUtil.extractValue(attrs, 'as')
       self._tagChecker.loadLib(taglib_name, taglib_from, taglib_as, fullfile, (begin, end, directive, self._curfile))
       self._ast.addTaglib(taglib_name, taglib_from, taglib_as)
       self._load_taglib = 1
       self._ast.addCode('taglib.load(%s, %s, %s)'%(repr(taglib_name), repr(taglib_from), repr(taglib_as)), (begin, end, directive, self._curfile))
   elif name=='include':
     if not attrs.has_key('file'):
       raise spyceException.spyceSyntaxError('file attribute missing', (begin, end, directive, self._curfile) )
     filename = os.path.join(self._curdir, attrs['file'])
     f = None
     try:
       try:
         f = open(filename)
         buf = f.read()
       finally:
         if f: f.close()
     except KeyboardInterrupt: raise
     except:
       raise spyceException.spyceSyntaxError('unable to open included file: %s'%filename, (begin, end, directive, self._curfile) )
     prev = (self._curdir, self._curfile, self._tokens,
       self._tokenType, self._tokenText, self._tokenBegin, self._tokenEnd)
     self._curdir, self._curfile = os.path.dirname(filename), filename
     self._tokens = spyceTokenize4Parse(processMagic(buf))
     self.popToken()
     self.processSpyce()
     (self._curdir, self._curfile, self._tokens,
       self._tokenType, self._tokenText, self._tokenBegin, self._tokenEnd) = prev
   else:
     raise spyceException.spyceSyntaxError('invalid spyce directive', (begin, end, directive, self._curfile) )
Exemple #19
0
   except:
     raise spyceException.spyceSyntaxError(
       'unable to load module: %s'%libname, info)
 def getTag(self, (libname,libfrom), name, attrs, pair, info):
   lib = self._taglibs[(libname, libfrom)]
   try:
     return lib.getTag(name, attrs, pair, None)
   except:
     raise spyceException.spyceSyntaxError(
       'unknown tag "%s:%s"'%(libname, name), info)
 def getTagClass(self, (libname, libfrom), name, info):
   lib = self._taglibs[(libname, libfrom)]
   try:
     return lib.getTagClass(name)
   except:
     raise spyceException.spyceSyntaxError(
       'unknown tag "%s:%s"'%(libname, name), info)
 def startTag(self, (libname,libfrom), name, attrs, pair, info):
   tag = self.getTag((libname, libfrom), name, attrs, pair, info)
   try:
     error = tag.syntax()
   except spyceTagSyntaxException, e:
     raise spyceException.spyceSyntaxError(str(e), info)
   if error:
     raise spyceException.spyceSyntaxError(error, info)
   if pair:
     self._stack.append( (libname, libfrom, name, info) )
 def endTag(self, (libname,libfrom), name, info):
   try:
     libname1, libfrom1, name1, info1 = self._stack.pop()
   except IndexError:
     raise spyceException.spyceSyntaxError(
 def processUnexpected(self):
   raise spyceException.spyceSyntaxError('unexpected token: "%s"'%self._tokenText, 
     (self._tokenBegin, self._tokenEnd, self._tokenText, self._curfile))
Exemple #21
0
 def finish(self):
     if self._stack:
         libname, libfrom, name, info = self._stack.pop()
         raise spyceException.spyceSyntaxError('unmatched open tag', info)
Exemple #22
0
            raise
        except:
            raise spyceException.spyceSyntaxError("unable to load module: %s" % libname, info)

    def startTag(self, (libname, libfrom), name, attrs, pair, info):
        lib = self._taglibs[(libname, libfrom)]
        try:
            tag = lib.getTag(name, attrs, pair, None)
        except:
            raise spyceException.spyceSyntaxError('unknown tag "%s:%s"' % (libname, name), info)
        try:
            error = tag.syntax()
        except spyceTagSyntaxException, e:
            raise spyceException.spyceSyntaxError(str(e), info)
        if error:
            raise spyceException.spyceSyntaxError(error, info)
        if pair:
            self._stack.append((libname, libfrom, name, info))

    def endTag(self, (libname, libfrom), name, info):
        try:
            libname1, libfrom1, name1, info1 = self._stack.pop()
        except IndexError:
            raise spyceException.spyceSyntaxError("unmatched close tag", info)
        if (libname1, libfrom1, name1) != (libname, libfrom, name):
            raise spyceException.spyceSyntaxError("unmatched close tag, expected <%s:%s>" % (libname1, name1), info)

    def finish(self):
        if self._stack:
            libname, libfrom, name, info = self._stack.pop()
            raise spyceException.spyceSyntaxError("unmatched open tag", info)