def _stat(self):
        pos = self._pos
        
        varlist = self._varlist()
        if varlist is not None:
            # (Missing '=' is not a fatal error because varlist might also match
            # the beginning of a functioncall.)
            assign_op = (self._accept(lexer.TokSymbol('=')) or
                         self._accept(lexer.TokSymbol('+=')) or
                         self._accept(lexer.TokSymbol('-=')) or
                         self._accept(lexer.TokSymbol('*=')) or
                         self._accept(lexer.TokSymbol('/=')) or
                         self._accept(lexer.TokSymbol('%=')))
            if assign_op is not None:
                explist = self._assert(self._explist(),
                                       'Expected expression in assignment')
                return StatAssignment(varlist, assign_op, explist,
                                      start=pos, end=self._pos)
        self._pos = pos
        
        functioncall = self._functioncall()
        if functioncall is not None:
            return StatFunctionCall(functioncall, start=pos, end=self._pos)
        self._pos = pos

        if self._accept(lexer.TokKeyword('do')) is not None:
            block = self._assert(self._chunk(), 'block in do')
            self._expect(lexer.TokKeyword('end'))
            return StatDo(block, start=pos, end=self._pos)

        if self._accept(lexer.TokKeyword('while')) is not None:
            exp = self._assert(self._exp(), 'exp in while')
            self._expect(lexer.TokKeyword('do'))
            block = self._assert(self._chunk(), 'block in while')
            self._expect(lexer.TokKeyword('end'))
            return StatWhile(exp, block, start=pos, end=self._pos)

        if self._accept(lexer.TokKeyword('repeat')) is not None:
            block = self._assert(self._chunk(),
                                 'block in repeat')
            self._expect(lexer.TokKeyword('until'))
            exp = self._assert(self._exp(),
                               'expression in repeat')
            return StatRepeat(block, exp, start=pos, end=self._pos)

        if self._accept(lexer.TokKeyword('if')) is not None:
            exp_block_pairs = []
            exp = self._exp()

            then_pos = self._pos
            if (self._accept(lexer.TokKeyword('then')) is None and
                (self._tokens[exp._end_token_pos - 1] == lexer.TokSymbol(')'))):
                # Check for Pico-8 short form.

                then_end_pos = exp._end_token_pos
                while (then_end_pos < len(self._tokens) and
                       not self._tokens[then_end_pos].matches(lexer.TokNewline)):
                    then_end_pos += 1
                    
                try:
                    self._max_pos = then_end_pos
                    block = self._assert(self._chunk(),
                                         'valid chunk in short-if')
                    else_block = None
                    if self._accept(lexer.TokKeyword('else')) is not None:
                        # Pico-8 accepts an else with nothing after it.
                        else_block = self._chunk()
                finally:
                    self._max_pos = None
                    
                # (Use exp.value here to unwrap the condition from the
                # bracketed expression.)
                exp_block_pairs = [(exp.value, block)]
                if else_block is not None and len(else_block.stats) > 0:
                    exp_block_pairs.append((None, else_block))
                return StatIf(exp_block_pairs, start=pos, end=self._pos,
                              short_if=True)
            
            self._pos = then_pos

            # TODO: hack: accept "do" for "then" to support seven carts that
            # exploit a loophole in short-if.
            self._expect(lexer.TokKeyword('then'))
            block = self._chunk()
            self._assert(block, 'Expected block in if')
            exp_block_pairs.append((exp, block))
            while self._accept(lexer.TokKeyword('elseif')) is not None:
                exp = self._exp()
                self._expect(lexer.TokKeyword('then'))
                block = self._chunk()
                self._assert(block, 'Expected block in elseif')
                exp_block_pairs.append((exp, block))
            if self._accept(lexer.TokKeyword('else')) is not None:
                block = self._chunk()
                self._assert(block, 'Expected block in else')
                exp_block_pairs.append((None, block))
            self._expect(lexer.TokKeyword('end'))
            return StatIf(exp_block_pairs, start=pos, end=self._pos)

        if self._accept(lexer.TokKeyword('for')) is not None:
            for_pos = self._pos

            name = self._accept(lexer.TokName)
            eq_sym = self._accept(lexer.TokSymbol('='))
            if eq_sym is not None:
                exp_init = self._assert(self._exp(), 'exp-init in for')
                self._expect(lexer.TokSymbol(','))
                exp_end = self._assert(self._exp(), 'exp-end in for')
                exp_step = None
                if self._accept(lexer.TokSymbol(',')):
                    exp_step = self._assert(self._exp(), 'exp-step in for')
                self._expect(lexer.TokKeyword('do'))
                block = self._assert(self._chunk(), 'block in for')
                self._expect(lexer.TokKeyword('end'))
                return StatForStep(name, exp_init, exp_end, exp_step, block,
                                   start=pos, end=self._pos)
            self._pos = for_pos
                
            namelist = self._assert(self._namelist(), 'namelist in for-in')
            self._expect(lexer.TokKeyword('in'))
            explist = self._assert(self._explist(), 'explist in for-in')
            self._expect(lexer.TokKeyword('do'))
            block = self._assert(self._chunk(), 'block in for-in')
            self._expect(lexer.TokKeyword('end'))
            return StatForIn(namelist, explist, block, start=pos, end=self._pos)

        if self._accept(lexer.TokKeyword('function')) is not None:
            funcname = self._assert(self._funcname(), 'funcname in function')
            funcbody = self._assert(self._funcbody(), 'funcbody in function')
            return StatFunction(funcname, funcbody, start=pos, end=self._pos)

        if self._accept(lexer.TokKeyword('local')) is not None:
            if self._accept(lexer.TokKeyword('function')) is not None:
                funcname = self._expect(lexer.TokName)
                funcbody = self._assert(self._funcbody(),
                                        'funcbody in local function')
                return StatLocalFunction(funcname, funcbody,
                                         start=pos, end=self._pos)
            namelist = self._assert(self._namelist(),
                                    'namelist in local assignment')
            explist = None
            if self._accept(lexer.TokSymbol('=')) is not None:
                explist = self._assert(self._explist(),
                                       'explist in local assignment')
            return StatLocalAssignment(namelist, explist,
                                       start=pos, end=self._pos)

        if self._accept(lexer.TokKeyword('goto')) is not None:
            label = self._expect(lexer.TokName)
            return StatGoto(label.value, start=pos, end=self._pos)
        
        label = self._accept(lexer.TokLabel)
        if label is not None:
            # Remove colons from label.
            label_name = label.value[2:-2]
            return StatLabel(label_name, start=pos, end=self._pos)
        
        self._pos = pos
        return None
Parse a stat.
dataset/ETHPy150Open dansanderson/picotool/pico8/lua/parser.py/Parser._stat