Example #1
0
    def parseSubroutine(self, s, bytecode_program, filename, line_number, column_number):
        if BytecodeReader.looksLikeLiteral(s):
            raise Exception('The name %s is not valid as a subroutine name (it looks like a number).' % s)
        if s in Opcode.__members__:
            raise Exception('The name %s is not valid as a subroutine name (it is a built-in command).' % s)
        if s in Keyword.__members__:
            raise Exception('The name %s is not valid as a subroutine name (it is a keyword).' % s)

        bytecode_program.addInstruction(BytecodeInstruction.newSubroutine(s, filename, line_number, column_number))
        self.mode = Mode.NORMAL
Example #2
0
    def parseString(self, s, bytecode_program, filename, line_number, column_number, isMiniMaestro):
        try:
            if BytecodeReader.looksLikeLiteral(s):
                if s.startswith('0X'):
                    try:
                        num = int(s, 16)
                    except ValueError:
                        raise Exception('Value %s must be an integer.' % s)
                    if num > 65535 or num < 0:
                        raise Exception('Value %s is not in the allowed range of 0 to 65525.' % s)
                else:
                    try:
                        num = int(s)
                    except ValueError:
                        raise Exception('Value %s must be an integer.' % s)
                    if num > 65535 or num < 0:
                        raise Exception('Value %s is not in the allowed range of 0 to 65525.' % s)

                literal = (num % 65535)
                bytecode_program.addLiteral(literal, filename, line_number, column_number, isMiniMaestro)
                return
        except Exception as ex:
            raise Exception('Error parsing %s: %s' % (s, ex))

        if s == 'GOTO':
            self.mode = Mode.GOTO
        elif s == 'SUB':
            self.mode = Mode.SUBROUTINE
        else:
            match = re.match(r"(.*):$", s)
            if match:
                bytecode_program.addInstruction(BytecodeInstruction.newLabel(
                    'USER_%s' % match.group(1), filename, line_number, column_number))
            elif s == 'BEGIN':
                bytecode_program.openBlock(BlockType.BEGIN, filename, line_number, column_number)
            elif s == 'WHILE':
                if bytecode_program.getCurrentBlockType() != BlockType.BEGIN:
                    raise Exception('WHILE must be inside a BEGIN...REPEAT block')
                bytecode_program.addInstruction(BytecodeInstruction.newConditionalJumpToLabel(
                    bytecode_program.getCurrentBlockEndLabel(), filename, line_number, column_number))
            elif s == 'REPEAT':
                try:
                    if bytecode_program.getCurrentBlockType() != BlockType.BEGIN:
                        raise Exception('REPEAT must end a BEGIN...REPEAT block')
                    bytecode_program.addInstruction(BytecodeInstruction.newJumpToLabel(
                        bytecode_program.getCurrentBlockStartLabel(), filename, line_number, column_number))
                    bytecode_program.closeBlock(filename, line_number, column_number)
                except:
                    raise Exception('%s:%s:%s: Found REPEAT without a corresponding BEGIN.'
                                    % (filename, line_number, column_number))
            elif s == 'IF':
                bytecode_program.openBlock(BlockType.IF, filename, line_number, column_number)
                bytecode_program.addInstruction(BytecodeInstruction.newConditionalJumpToLabel(
                    bytecode_program.getCurrentBlockEndLabel(), filename, line_number, column_number))
            elif s == 'ENDIF':
                try:
                    if bytecode_program.getCurrentBlockType() != BlockType.IF and \
                                    bytecode_program.getCurrentBlockType() != BlockType.ELSE:
                        raise Exception('ENDIF must end an IF...ENDIF or an IF...ELSE...ENDIF block.')
                    bytecode_program.closeBlock(filename, line_number, column_number)
                except:
                    raise Exception('%s:%s:%s: Found ENDIF without a corresponding IF.'
                                    % (filename, line_number, column_number))
            elif s == 'ELSE':
                try:
                    if bytecode_program.getCurrentBlockType() != BlockType.IF:
                        raise Exception('ELSE must be part of an IF...ELSE...ENDIF block.')
                    bytecode_program.addInstruction(BytecodeInstruction.newJumpToLabel(
                        bytecode_program.getNextBlockEndLabel(), filename, line_number, column_number))
                    bytecode_program.closeBlock(filename, line_number, column_number)
                    bytecode_program.openBlock(BlockType.ELSE, filename, line_number, column_number)
                except:
                    raise Exception('%s:%s:%s: Found ELSE without a corresponding IF.'
                                    % (filename, line_number, column_number))
            else:
                try:
                    op = Opcode[s]
                    if op in [Opcode.LITERAL, Opcode.LITERAL8, Opcode.LITERAL_N, Opcode.LITERAL8_N]:
                        raise Exception('%s:%s:%s: Literal commands may not be used directly in a program. '
                                        'Integers should be entered directly.' % (filename, line_number, column_number))
                    elif op == Opcode.JUMP or op == Opcode.JUMP_Z:
                        raise Exception('%s:%s:%s: Jumps may not be used directly in a program.'
                                        % (filename, line_number, column_number))
                    else:
                        if not isMiniMaestro and op >= 50:
                            raise Exception('%s:%s:%s: is only available on the Mini Maestro 12, 18, and 24.'
                                            % (filename, line_number, column_number))
                        bytecode_program.addInstruction(BytecodeInstruction(op, filename, line_number, column_number))
                except KeyError:
                    bytecode_program.addInstruction(
                        BytecodeInstruction.newCall(s, filename, line_number, column_number))
Example #3
0
 def closeBlock(self, filename, line_number, column_number):
     self.addInstruction(BytecodeInstruction.newLabel('block_end_%s' % self.openBlocks.pop(), filename,
                                                      line_number, column_number))
     self.openBlockTypes.pop()
Example #4
0
 def parseGoto(self, s, bytecode_program, filename, line_number, column_number):
     bytecode_program.addInstruction(BytecodeInstruction.newJumpToLabel(
         'USER_' + s, filename, line_number, column_number))
     self.mode = Mode.NORMAL
Example #5
0
 def openBlock(self, blocktype, filename, line_number, column_number):
     self.addInstruction(BytecodeInstruction.newLabel('block_start_%s' % self.maxBlock,
                                                      filename, line_number, column_number))
     self.openBlocks.append(self.maxBlock)
     self.openBlockTypes.append(blocktype)
     self.maxBlock += 1