def _parse()

in modules/pymol/parser.py [0:0]


        def _parse(self, s, secure):
            layer = self.layer[self.nest]
            self.result = None
# report any uncaught errors...
# WLD: this is problematic if parse is called inside an exception...removed.
#            if sys.exc_info()!=(None,None,None):
#                traceback.print_exc()
#                sys.exc_clear()
            def parse_embed():
                if s.strip() == layer.embed_sentinel:
                    etn = layer.embed_type
                    if etn == 0: # embedded data
                        colorprinting.parrot(" Embed: read %d lines."%(len(layer.embed_list)))
                        layer.embed_sentinel=None
                    elif etn == 1: # python block
                        colorprinting.parrot("PyMOL>"+s.rstrip())
                        py_block = ''.join(layer.embed_list)
                        del layer.embed_list
                        layer.embed_sentinel=None
                        self.exec_python(py_block)
                    elif etn == 2: # skip block
                        colorprinting.parrot(" Skip: skipped %d lines."%(layer.embed_line))
                        layer.embed_sentinel=None
                else:
                    etn = layer.embed_type
                    if etn == 0: # normal embedded data
                        layer.embed_list.append(s.rstrip()+"\n")
                    elif etn == 1: # python block
                        el = layer.embed_line + 1
                        colorprinting.parrot("%5d:%s"%(el,s.rstrip()))
                        layer.embed_line = el
                        layer.embed_list.append(s.rstrip()+"\n")
                    elif etn == 2:
                        layer.embed_line = layer.embed_line + 1

            p_result = 1
            layer.com0 = s
            try:
                if layer.embed_sentinel is not None:
                    parse_embed()
                    return 1

                layer.com1 = layer.com0.rstrip() # strips trailing whitespace
                if len(layer.com1) > 0:
                    if str(layer.com1[-1]) == "\\":
                        # prepend leftovers
                        if layer.cont != '':
                            layer.cont = layer.cont + "\n" + layer.com1[:-1]
                        else:
                            layer.cont = layer.com1[:-1]
                    else:
                        # prepend leftovers
                        if layer.cont != '':
                            layer.com1 = layer.cont + "\n" + layer.com1
                            layer.cont = ''
        # this routine splits up the line first based on semicolon 
                        
                        layer.next = parsing.split(layer.com1,';',1) + layer.next[1:]
                        
        # layer.com2 now a full non-compound command            
                        layer.com2 = layer.next[0]
                        layer.input = layer.com2.split(' ',1)
                        lin = len(layer.input)
                        if lin:
                            layer.input[0] = layer.input[0].strip()
                            com = layer.input[0]
                            if (com[0:1]=='/'):
                                # explicit literal python 
                                layer.com2 = layer.com2[1:].strip()
                                if len(layer.com2)>0:
                                    self.exec_python(layer.com2, secure)
                            elif lin>1 and layer.input[-1:][0].split(' ',1)[0] in py_delims:
                                self.exec_python(layer.com2, secure)
                            else:
                                # try to find a keyword which matches
                                if com in self.cmd.kwhash:
                                    amb = self.cmd.kwhash.interpret(com)
                                    if amb == None:
                                        com = self.cmd.kwhash[com]
                                    elif not isinstance(amb, str):
                                        colorprinting.warning('Error: ambiguous command: ')
                                        amb.sort()
                                        amb = parsing.list_to_str_list(amb)
                                        for a in amb:
                                            colorprinting.warning(a)
                                        raise QuietException
                                    com = amb
                                if com in self.cmd.keyword:
                                    # here is the command and argument handling section
                                    layer.kw = self.cmd.keyword[com]
                                    if layer.kw[4]>=parsing.NO_CHECK:
                                        # stricter, Python-based argument parsing
                                        # remove line breaks (only important for Python expressions)
                                        layer.com2=layer.com2.replace('\n','')

                                        if layer.kw[4]>=parsing.LITERAL: # treat literally
                                            layer.next = []
                                            if not secure:
                                                layer.com2=layer.com1
                                            else:
                                                raise SecurityException('Python expressions disallowed in this file')
                                        if secure and (layer.kw[4]==parsing.SECURE):
                                            layer.next = []
                                            raise SecurityException('Command disallowed in this file')
                                        else:
                                           (layer.args, layer.kw_args) = \
                                            parsing.prepare_call(
                                             layer.kw[0],
                                             parsing.parse_arg(layer.com2,mode=layer.kw[4],_self=self.cmd),
                                             layer.kw[4], _self=self.cmd) # will raise exception on failure
                                        self.result=layer.kw[0](*layer.args, **layer.kw_args)
                                    elif layer.kw[4]==parsing.PYTHON:
                                            # handle python keyword
                                            layer.com2 = layer.com2.strip()
                                            if len(layer.com2)>0:
                                                self.exec_python(layer.com2, secure)
                                    else:
                                        # remove line breaks (only important for Python expressions)
                                        layer.com2=layer.com2.replace('\n','')
                                        # old parsing style, being phased out
                                        if layer.kw[4]==parsing.ABORT:
                                            return None # SCRIPT ABORT EXIT POINT
                                        if layer.kw[4]==parsing.MOVIE: # copy literal single line, no breaks
                                            layer.next = []
                                            if not secure:
                                                layer.input = layer.com1.split(' ',1)
                                            else:
                                                raise SecurityException('Movie commands disallowed in this file')
                                        if len(layer.input)>1:
                                            layer.args = parsing.split(layer.input[1],layer.kw[3])
                                            while 1:
                                                nArg = len(layer.args) - 1
                                                c = 0
                                                while c < nArg:
                                                    if ( layer.args[c].count('(')!=
                                                         layer.args[c].count(')')):
                                                        tmp=layer.args[c+1]
                                                        layer.args.remove(tmp)
                                                        layer.args[c]=layer.args[c].strip()+\
                                                                          ','+tmp.strip()
                                                        nArg = nArg-1
                                                        break;
                                                    c = c + 1
                                                if c == nArg:
                                                    break;
                                            if len(layer.args)==1 and len(layer.args[0])==0:
                                                layer.args = []
                                        else:
                                            layer.args = []
                                        if layer.kw[1]<= len(layer.args) <= layer.kw[2]:
                                            layer.args = [a.strip() for a in layer.args]
                                            if layer.kw[4]<parsing.RUN:
                                                #                           
                                                # this is where old-style commands are invoked
                                                #
                                                self.result=layer.kw[0](*layer.args)
                                                #                           
                                            elif (layer.kw[4]==parsing.EMBED):
                                                layer.next = []
                                                if secure or self.nest==0: # only legal on top level and p1m files
                                                    l = len(layer.args)
                                                    if l>0:
                                                        key = layer.args[0]
                                                    else:
                                                        key = self.get_default_key()
                                                    if l>1:
                                                        format = layer.args[1]
                                                    else:
                                                        format = 'pdb'
                                                    if l>2:
                                                        layer.embed_sentinel = layer.args[2]
                                                    else:
                                                        layer.embed_sentinel = "embed end"
                                                    list = []
                                                    layer.embed_dict[key] = ( format, list )
                                                    layer.embed_list = list
                                                    layer.embed_type = 0 # not a python block
                                                else:
                                                    print('Error: embed only legal in special files (e.g. p1m)')
                                                    raise None
                                            elif (layer.kw[4]==parsing.SKIP):
                                                layer.next = []
                                                arg = parsing.apply_arg(
                                                    parsing.parse_arg(layer.com2,_self=self.cmd),
                                                    ('sentinel',),
                                                    {'sentinel':'skip end'})
                                                print(arg) # ???
                                                if len(layer.args):
                                                    if layer.args[0]=='end': # probable 'skip end' to ignore
                                                        arg = []
                                                if len(arg):
                                                    layer.embed_sentinel = arg[0]
                                                    layer.embed_type = 2 # skip block
                                                    layer.embed_line = 0
                                            elif (layer.kw[4]==parsing.PYTHON_BLOCK):
                                                layer.next = []
                                                if not secure:
                                                    arg = parsing.apply_arg(
                                                        parsing.parse_arg(layer.com2,_self=self.cmd),
                                                        ('sentinel','skip'),
                                                        {'sentinel':'python end','skip':0})
                                                    layer.embed_sentinel = arg[0]
                                                    list = []
                                                    layer.embed_list = list
                                                    if arg[1]:
                                                        layer.embed_type = 2 # skip block
                                                    else:
                                                        layer.embed_type = 1 # python block
                                                    layer.embed_line = 0
                                                else:
                                                    print('Error: Python blocks disallowed in this file.')
                                                    raise None
                                            else:
                                                print('Error: unknown keyword mode: '+str(layer.kw[4]))
                                                raise QuietException
                                        else:
                                            print('Error: invalid arguments for %s command.' % com)
        #
        # non-keyword command handling
        #
                                elif len(layer.input[0]):
                                    if layer.input[0][0]=='@':
                                        path = exp_path(layer.com2[1:].strip())
                                        if path[-3:].lower()=='p1m':
                                            nest_securely = 1
                                        else:
                                            nest_securely = secure
                                        if re.search("\.py$|\.pym$",path) != None:
                                            if self.cmd._feedback(fb_module.parser,fb_mask.warnings):
                                                print("Warning: use 'run' instead of '@' with Python files?")
                                        layer.script = open(path,'rU')
                                        self.cmd._pymol.__script__ = path
                                        self.nest=self.nest+1
                                        self.layer[self.nest] = NestLayer()
                                        layer = self.layer[self.nest]
                                        layer.cont=''
                                        layer.sc_path=path
                                        layer.embed_sentinel=None
                                        while 1:
                                            layer.com0  = self.layer[self.nest-1].script.readline()
                                            self.layer[self.nest].lineno += 1
                                            if not layer.com0: break
                                            inp_cmd = layer.com0
                                            tmp_cmd = inp_cmd.strip()
                                            if len(tmp_cmd):
                                                if tmp_cmd[0] not in ['#','_','/']: # suppress comments, internals, python
                                                    if layer.embed_sentinel==None:
                                                        colorprinting.parrot("PyMOL>"+tmp_cmd)
                                                elif tmp_cmd[0]=='_' and \
                                                      tmp_cmd[1:2] in [' ','']: # "_ " remove echo suppression signal
                                                    inp_cmd=inp_cmd[2:]
                                            pp_result = self.parse(inp_cmd,nest_securely)
                                            if pp_result==None: # RECURSION
                                                break # abort command gets us out
                                            elif pp_result==0: # QuietException
                                                if self.cmd.get_setting_boolean("stop_on_exceptions"):
                                                    p_result = 0 # signal an error occurred
                                                    colorprinting.error("PyMOL: stopped on exception.")
                                                    break;
                                        self.nest=self.nest-1
                                        layer=self.layer[self.nest]
                                        
                                        layer.script.close()
                                        self.cmd._pymol.__script__ = layer.sc_path
                                    else: # nothing found, try literal python
                                        layer.com2 = layer.com2.strip()
                                        if len(layer.com2)>0:
                                            if not secure:
                                                self.exec_python(layer.com2, fallback=True)
                                            elif layer.input[0][0:1]!='#':
                                                colorprinting.error('Error: unrecognized keyword: '+layer.input[0])
                        if (len(layer.next)>1) and p_result:
                            # continue parsing if no error or break has occurred
                            self.nest=self.nest+1
                            self.layer[self.nest] = NestLayer()
                            layer=self.layer[self.nest]
                            layer.com0 = self.layer[self.nest-1].next[1]
                            self.layer[self.nest-1].next=[]
                            layer.cont=''
                            layer.embed_sentinel=None
                            p_result = self.parse(layer.com0,secure) # RECURSION
                            self.nest=self.nest-1
                            layer=self.layer[self.nest]
            except (QuietException, CmdException) as e:
                if e.args:
                    colorprinting.error(e)
                if self.cmd._feedback(fb_module.parser,fb_mask.blather):         
                    print("Parser: caught " + type(e).__name__)
                p_result = 0
            except SecurityException as e:
                colorprinting.error('Error: %s' % (e,))
                p_result = None
            except:
                exc_type, exc_value, tb = colorprinting.print_exc(
                        [__file__, SCRIPT_TOPLEVEL])

                p_result = 0 # notify caller that an error was encountered
            if not p_result and self.cmd._pymol.invocation.options.exit_on_error:
                self.cmd.quit(1)
            return p_result  # 0 = Exception, None = abort, 1 = ok