Skip to content
Snippets Groups Projects
Select Git revision
  • dd7a9961fe61c399067e16e84bca40df5ef64dfa
  • master default protected
  • cran_version
3 results

getScaleFlagCLP.Rd

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    whileinterpreter.py 8.72 KiB
    import lexer
    from loopinterpreter import LOOPInterpreter, ErrorHandler
    import re
    import signal
    
    
    class Timeout:
        def __init__(self, time):
            self.time = time
    
        def __enter__(self):
            if self.time > 0:
                signal.signal(signal.SIGALRM, self.interrupt)
                signal.alarm(self.time)
    
        def __exit__(self, exc_type, exc_value, exc_traceback):
            signal.alarm(0)
    
        def interrupt(self, sig_num, stack_frame):
            try:
                abort = input('''Die Funktion rechnet relativ lange.
    Vielleicht liegt eine Endlosschleife vor.
    Möchten sie abbrechen? [J,n]:''')
                if abort.upper() in ['J', 'JA', 'Y', 'YES', '']:
                    raise KeyboardInterrupt
                signal.alarm(self.time)
            except EOFError:
                pass
    
    
    class WHILEInterpreter(LOOPInterpreter):
        def __init__(self, timeout=60):
            super().__init__()
            self.regex_to_token = [(re.compile(r'\d+'), 'NUMBER'),
                                   (re.compile(r'x\d+'), 'IDENTIFIER'),
                                   (re.compile(r'\+'), 'PLUS'),
                                   (re.compile(r'[−-]'), 'MINUS'),
                                   (re.compile(r':=|≔'), 'ALLOCATION'),
                                   (re.compile(r'/=|≠|!='), 'NOTEQUALS'),
                                   (re.compile(r'LOOP'), 'LOOP'),
                                   (re.compile(r'WHILE'), 'WHILE'),
                                   (re.compile(r'DO'), 'DO'),
                                   (re.compile(r'END'), 'END'),
                                   (re.compile(r';'), 'SEMICOLON'),
                                   (re.compile(r'BREAK'), 'BREAK'),
                                   (re.compile(r'\s+', re.MULTILINE), 'WHITESPACE'),
                                   (re.compile(r'[^\n]*'), 'UNKNOWN')]
            self.timeout = timeout
    
        def process_program(self, forbidden_identifiers, current_token):
            if current_token is None or current_token.k not in ['IDENTIFIER', 'LOOP', 'WHILE']:
                self.error_handler.handle_error('Keine passende Anweisung gefunden\n' +
                                                'Erwartet: IDENTIFIER (x0, x1, ...), LOOP oder WHILE')
            elif current_token.k == 'IDENTIFIER':
                current_token = self.process_assignment(forbidden_identifiers, current_token)
            elif current_token.k == 'LOOP':
                current_token = self.process_loop(forbidden_identifiers, current_token)
            elif current_token.k == 'WHILE':
                current_token = self.process_while(forbidden_identifiers, current_token)
            return current_token
    
        def verify_program(self, forbidden_identifiers, current_token):
            if current_token is None or current_token.k not in ['IDENTIFIER', 'LOOP', 'WHILE']:
                self.error_handler.handle_error('Keine passende Anweisung gefunden\n' +
                                                'Erwartet: IDENTIFIER (x0, x1, ...), LOOP oder WHILE')
            elif current_token.k == 'IDENTIFIER':
                current_token = self.verify_assignment(forbidden_identifiers, current_token)
            elif current_token.k == 'LOOP':
                current_token = self.verify_loop(forbidden_identifiers, current_token)
            elif current_token.k == 'WHILE':
                current_token = self.verify_while(forbidden_identifiers, current_token)
            return current_token
    
        def process_while(self, forbidden_identifiers, current_token):
            identifier_token = self.next_nonempty_token('WHILE', 'IDENTIFIER (x0, x1, ...)')
            if not identifier_token.k == 'IDENTIFIER':
                self.error_handler.handle_error('IDENTIFIER in WHILE erwartet.')
            if identifier_token.v in forbidden_identifiers:
                self.error_handler.handle_error('Identifier ' + identifier_token.v +
                                                ' ist bereits in Loop vorhanden und darf nicht verwendet werden.')
            if not self.next_nonempty_token('WHILE', 'UNGLEICH').k == 'NOTEQUALS':
                self.error_handler.handle_error('UNGLEICH in WHILE erwartet.')
    
            zero_token = self.next_nonempty_token('WHILE', '0')
            if not zero_token.k == 'NUMBER':
                self.error_handler.handle_error('0 in WHILE erwartet.')
            if not int(zero_token.v) == 0:
                self.error_handler.handle_error('0 in WHILE erwartet.')
    
            if not self.next_nonempty_token('WHILE', 'DO').k == 'DO':
                self.error_handler.handle_error('DO in WHILE erwartet.')
    
            if identifier_token.v in self.values:
                while_value = int(self.values.get(identifier_token.v))
            else:
                while_value = 0
    
            saved_position = self.lex.current_position
            saved_line = self.error_handler.line_number
    
            if while_value == 0:
                end_found = False
                while not end_found:
                    token = self.verify_program(forbidden_identifiers, self.next_token())
                    if token is None or token.k not in ['SEMICOLON', 'END']:
                        self.error_handler.handle_error('SEMICOLON oder END in WHILE erwartet.')
                    elif token.k == 'SEMICOLON':
                        continue
                    elif token.k == 'END':
                        end_found = True
    
            while not while_value == 0:
                self.lex.current_position = saved_position
                self.error_handler.line_number = saved_line
                end_found = False
                while not end_found:
                    token = self.process_program(forbidden_identifiers, self.next_token())
                    if token is None or token.k not in ['SEMICOLON', 'END']:
                        self.error_handler.handle_error('SEMICOLON oder END in WHILE erwartet.')
                    elif token.k == 'SEMICOLON':
                        continue
                    elif token.k == 'END':
                        end_found = True
    
                while_value = int(self.values.get(identifier_token.v))
    
            return self.next_token()
    
        def verify_while(self, forbidden_identifiers, current_token):
            identifier_token = self.next_nonempty_token('WHILE', 'IDENTIFIER')
            if not identifier_token.k == 'IDENTIFIER':
                self.error_handler.handle_error('IDENTIFIER in WHILE erwartet.')
            if identifier_token.v in forbidden_identifiers:
                self.error_handler.handle_error('Identifier ' + identifier_token.v +
                                                ' ist bereits in Loop vorhanden und darf nicht verwendet werden.')
            if not self.next_nonempty_token('WHILE', 'UNGLEICH').k == 'NOTEQUALS':
                self.error_handler.handle_error('UNGLEICH in WHILE erwartet.')
    
            zero_token = self.next_nonempty_token('WHILE', '0')
            if not zero_token.k == 'NUMBER':
                self.error_handler.handle_error('0 in WHILE erwartet.')
            if not int(zero_token.v) == 0:
                self.error_handler.handle_error('0 in WHILE erwartet.')
    
            if not self.next_nonempty_token('WHILE', 'DO').k == 'DO':
                self.error_handler.handle_error('DO in WHILE erwartet.')
    
            end_found = False
            while not end_found:
                token = self.verify_program(forbidden_identifiers, self.next_token())
                if token is None or token.k not in ['SEMICOLON', 'END']:
                    self.error_handler.handle_error('SEMICOLON oder END in WHILE erwartet.')
                elif token.k == 'SEMICOLON':
                    continue
                elif token.k == 'END':
                    end_found = True
    
            return self.next_token()
    
        def interpret(self, program):
            try:
                with Timeout(self.timeout):
                    self.lex = lexer.Lexer(self.regex_to_token, program)
                    self.error_handler = ErrorHandler(program, self)
                    self.values = {}
                    forbidden_identifiers = []
                    current_token = self.next_token()
                    while current_token is not None:
                        current_token = self.process_program(forbidden_identifiers, current_token)
                        if current_token is not None:
                            if not current_token.k == 'SEMICOLON':
                                self.error_handler.handle_error('Semicolon erwartet')
                            current_token = self.next_token()
                            if current_token is None:
                                self.error_handler.handle_error('Semikolons werden nur zur Trennung und nicht zum ' +
                                                                'Abschluss von Programmen verwendet')
                    if 'x0' in self.values:
                        return self.values.get('x0')
                    return 0
            except KeyboardInterrupt:
                print('Die Ausführung des Programms wurde unterbrochen.\n' +
                      'Daher ist der Rückgabewert des Programms nicht definiert.')
                return -1
    
    
    def interpret(program, timeout=60):
        interpreter = WHILEInterpreter(timeout)
        return interpreter.interpret(program)