コード例 #1
0
    def __intr_check_flow(self, inst_count):
        # pruchod pro labely
        for i in range(0, inst_count):
            item = self.prg[i]
            opcode = item.get('opcode')

            if (opcode == 'label'):
                key = item.get('argv')[0].get('value')
                value = item.get('order')
                # najdi label
                if (key in self.labels):
                    Error(52, 'Duplictni label')
                # jinak proste prirad label
                self.labels[key] = value

        # pruchod pro funkci volani a jump
        for i in range(0, inst_count):
            item = self.prg[i]
            opcode = item.get('opcode')
            # pokud se jedna o jakoukoliv skokovou instrukci
            if (opcode == 'call' or opcode == 'jump' or opcode == 'jumpifeq'
                    or opcode == 'jumpifneq'):
                # najdeme jmeno labelu
                key = item.get('argv')[0].get('value')

                if (not key in self.labels):
                    Error(52, 'Referencujeme neexistujici label')
コード例 #2
0
    def __parser_scrape_xml(self):
        # citac pro cislo instrukci, zajistime duplicitni a nesourode
        # poradi instrukci, ktere muze pozdeji rozbit program
        # viceme integritni omezeni
        order_counter = 0
        # projed skrz cele XML
        for instruction in self.root:
            # konverze z XML.tree objektu na standarni list
            # argumenty instrukce
            argv = list(instruction)
            # pomocne promenne
            opcode = instruction.attrib.get('opcode')
            # poradi instrukce i s normalizaci pro Python
            order = int(instruction.attrib.get('order')) - 1
            # pokud nam nesedi poradi instrukci
            if (order != order_counter):
                Error(
                    31,
                    'Nesedi order parametru u instrukce, neni v tom border?')

            # prace s ukazatelem poradi instrukce
            try:
                order = int(instruction.attrib.get('order'))
            except ValueError:
                Error(31, 'Atribut poradi evidetne neni validni int')
            # kontrola spravnosti argumentu poradi
            if (order < 1):
                Error(31, 'Atribut poradi musi byt > 0')

            # zkontroluj, jestli je operacni kod spravny
            blueprint_index = self.__parser_inst_check(
                instruction.attrib['opcode'])
            blueprint = Parser._blueprint[blueprint_index]
            #inst_blueprint = Parser._blueprint[inst_blueprint]
            # zkontroluj, zdali sedi pocet argumentu, vzhledem k operacnimu kodu
            self.__parser_arg_count(argv, blueprint_index)

            # pole pro j*z osetrene (escapove) a jinak upravene/zkontrolovane argumenty
            checked_argv = []

            for i in range(len(argv)):
                # slovnik pro obsah datovych atributu argumentu
                checked_arg = {}
                # kontrola validity parametru
                checked_arg = self.__parser_arg_check(
                    blueprint[i], argv[i].attrib.get('type'), argv[i].text)
                # pridej ho do pole argumentu instrukce
                checked_argv.append(checked_arg)

            # pridej do pole instrukci
            out = {}
            out['opcode'] = opcode.lower()
            # normalizace pro indexovani pole
            out['order'] = order - 1
            out['argv'] = checked_argv

            # inkrementuj citac instrukci
            order_counter += 1
            # pridej novou polozku
            Parser.output.append(out)
コード例 #3
0
 def __argp_check_argv(self):
     argv = self.accepted
     # zkontrolujeme jednotlive mody
     if (argv.get('help')):
         self.mode = 1
     # cokoliv jineho nez help
     elif (argv.get('source')):
         # pokud mame parametry a spravny beh programu
         if ((argv.get('insts') or argv.get('vars'))
                 and not argv.get('stats')):
             Error(10, 'Statisticke parametry vyzaduji vystupni soubor')
         # mame oba parametry?
         if (argv.get('insts') and argv.get('vars')):
             if (argv.get('insts') == 1):
                 self.mode = 5
             elif (argv.get('insts') == 2):
                 print('prvni promenne')
                 self.mode = 6
         # pokud mame jenom jeden z parametru
         elif (argv.get('insts')):
             self.mode = 3
         elif (argv.get('vars')):
             self.mode = 4
         # evidetne mame jenom jeden soubor
         else:
             self.mode = 2
     else:
         Error(10, 'Potrebuju nejakej vstupni soubor .xml')
コード例 #4
0
 def __init__(self, filename):
     if (not os.path.isfile(filename)):
         Error(11, 'Vstupni soubor neexistuje')
     elif (os.path.getsize(filename) == 0):
         Error(11, 'Vstupni soubor existuje, ale prazdny')
     else:
         # muzeme bezpecne priradit
         self.filename = filename
コード例 #5
0
    def __parser_map_type(self, expected_type, type):

        # korekce pro symbol
        if (expected_type == 'symb'):
            valid_subtypes = ['int', 'float', 'bool', 'string', 'var']
            valid = False
            for subtype in valid_subtypes:
                if (type == subtype):
                    valid = True
            if (not valid):
                Error(32, 'Typ operandu nesedi k ocekavanemu typu')

        else:
            if (expected_type != type):
                Error(32, 'Typ operandu nesedi k ocekavanemu typu')
コード例 #6
0
    def _return(self):
        # vybereme ze zasobniku volani a skocime
        ret_place = self.call_stack.top()
        if (ret_place == None):
            Error(56, 'Davas return, ale nemas kam skocit, zavolal jsi call?')

        return ret_place
コード例 #7
0
    def _read(self, dest, type):
        # zkusime, jestli je vubec co cist
        try:
            # nacteme hodnotu
            value = input()
            type = type.get('value')

            # typovani symbolu
            if (type == 'int'):
                try:
                    value = int(value)
                except ValueError:
                    value = 0

            elif (type == 'float'):
                try:
                    # TODO: poresit ty silene zapisy floatu
                    value = float(value)
                except ValueError:
                    value = 0

            elif (type == 'bool'):
                # zde se pouze podivani, co mame za hodnotu
                if (value == 'true'):
                    value = bool(1)
                else:
                    value = bool(0)
            # prirad do symbolu
            dest.symb_set(type, value)
        except EOFError:
            Error(56, "V .in souboru neni hodnota")
コード例 #8
0
 def _idiv(self, dest, s1, s2, stack=False):
     ret = Retype('r=', s1, s2)
     ret = ret.rt_exec()
     # kontrola deleni nulou
     if (ret.b == 0 or ret.a == 0):
         Error(57, 'Delime nulou, coz tak nejak nejde')
     else:
         self.__fn_assign(dest, s1.get('type'), ret.a // ret.b, stack)
コード例 #9
0
 def __parser_inst_check(self, inst):
     regexes = Parser._inst_regex
     ret = None
     # projed vsechny mozne regexy
     for i in range(len(regexes)):
         if (re.match(regexes[i], inst)):
             ret = i
             break
     # vyres navratove typy
     return ret if (ret != None) else Error(32, 'Neznamy typ instrukce')
コード例 #10
0
 def _getchar(self, dest, s1, s2):
     # nacteme string
     string = s1.get('value')
     # normalizace pro index
     string_len = len(string) - 1
     # neindexujeme nekam do pekel?
     index = s2.get('value')
     if (index < 0 or index > string_len):
         Error(58, "Indexace mimo retezec (str2int)")
     # uloz symbol
     dest.symb_set('string', string[index])
コード例 #11
0
 def _pushframe(self):
     tf = self.frames.get('tf')
     # mame vubec co pushovat?
     if (tf != None):
         # zmena typu ramce
         self.frames.get('tf').frame_tf2lf()
         # ulozeni na zasobnik
         self.frames.get('stack').push(tf)
         self.frames['tf'] = None
     else:
         # ramec TF neexistuje
         Error(55, 'Soudruhu, TF neexistuje a ty ho zadas!')
コード例 #12
0
 def _write(self, to_write):
     to_write_type = to_write.get('type')
     # ma vubec neco cenu vypisovat?
     if (to_write_type != None):
         if (to_write_type == 'bool'):
             v = to_write.get('value')
             if (v == 0):
                 print('false')
             else:
                 print('true')
         else:
             print(to_write.get('value'))
     else:
         Error(56, 'Neni co vytisknout')
コード例 #13
0
    def parser_run(self):
        # je to vubec validni xml
        try:
            # nacteme do promennes
            self.tree = ET.parse(self.filename)
        except ET.ParseError:
            Error(31, 'Spatne formatovane vstupni XML')

        self.root = self.tree.getroot()
        # mame tam spravnou hlavicku
        self.__parser_check_shebang()
        # projed XML a nasyp to do 'output'
        self.__parser_scrape_xml()
        # vrat objekt s daty
        return Parser.output
コード例 #14
0
 def __intr_config_load(self):
     # otevreni souboru
     try:
         config = open("ippcode18_blueprint.json", "r")
     except FileNotFoundError:
         Error(
             99,
             'Nepodarilo se otevrit soubor pro popis instrukci (FILE CORRUPTED)'
         )
     # precteme config
     config = config.read()
     # prevedeme do pouzitelne podoby
     config = json.loads(config)
     # vratime
     return config
コード例 #15
0
    def _setchar(self, dest, s1, s2):
        # nacteme string
        index = s1.get('value')
        chars = s2.get('value')
        # nacteme retezec na upravu
        string = dest.symb_get().get('value')
        string_len = len(string)

        if (index < 0 or index > string_len):
            Error(58, "Indexace mimo retezec (str2int)")

        new_val = chars[0]
        # prirad hodnotu
        string = string[:index] + new_val + string[index + 1:]
        # uloz symbol
        dest.symb_set('string', string)
コード例 #16
0
    def __parser_arg_check(self, expected_type, type, value):
        # sedi nam typy argumentu?
        self.__parser_map_type(expected_type, type)
        # samotne kolecko kontrolovani spravnosti hodnot
        if (type == 'var'):
            if (not re.match(Parser._param_regex[0], value)):
                Error(32, 'Spatne jmeno promenne')

        elif (type == 'label'):
            if (not re.match(Parser._param_regex[2], value)):
                Error(32, 'Spatny nazev labelu')

        elif (type == 'type'):
            if (not re.match(Parser._param_regex[3], value)):
                Error(32, 'Spatny nazev datoveho typu u typu')

        elif (expected_type == 'symb'):
            # typovani symbolu
            if (type == 'int'):
                try:
                    value = int(value)
                except ValueError:
                    Error(52, 'Toto jaksi neni INT')
                except TypeError:
                    value = None

            elif (type == 'float'):
                try:
                    value = float(value)
                except ValueError:
                    Error(52, 'Toto jaksi neni FLOAT')
                except TypeError:
                    value = None

            elif (type == 'bool'):
                # zde se pouze podivani, co mame za hodnotu
                if (value == 'true'):
                    value = bool(1)
                elif (value == 'false'):
                    value = bool(0)
                else:
                    Error(52, 'Toto jaksi neni BOOL')

            elif (type == 'string'):
                # escapovani stringu
                if (value):
                    value = self.__parser_escape_arg(value)

        # slovnik pro kopii do listu rozparsovanych instrukci
        return {'type': type, 'value': value}
コード例 #17
0
    def __intr_instruction(self, config, opcode):
        # umisteni predpisu instrukci v JSON configu
        with_params = config.get('operd')
        on_stack = config.get('stack')
        # vysekneme posledni znak
        suffix = opcode[-1]

        try:
            # mame zasobnikovou instrukci
            if (suffix == 's' and opcode != 'pushs' and opcode != 'pops'):
                # instrukce s argumenty
                #print("Na stacku: {}".format(opcode))
                # normalizace pro rozpoznavani argumentu
                # sice nejsou treba, ale metodou musime projit, proto ji obalime
                rules = [['stack', on_stack.get(opcode)]]
            else:
                #print("S argumenty: {}".format(opcode))
                rules = with_params.get(opcode)

        except KeyError:
            Error(99, 'Pro dany instrukci neexistuje predpis')

        return rules
コード例 #18
0
 def __parser_arg_count(self, temp_argv, index):
     if (len(temp_argv) != len(Parser._blueprint[index])):
         Error(32, 'Nesedi pocet parametru k instrukci')
コード例 #19
0
 def __parser_check_shebang(self):
     # kontrola spravne hlavicky vstupu
     if (not self.root.attrib['language'] == 'IPPcode18'):
         Error(32, 'Spatna/neexistujici hlavicka')
コード例 #20
0
 def _int2char(self, dest, s1, stack=False):
     try:
         convert = chr(s1.get('value'))
         self.__fn_assign(dest, 'string', convert, stack)
     except ValueError:
         Error(58, "Konverze int2char vyzaduje cislo znaku v Unicode")
コード例 #21
0
    def argp_parse_argv(self):
        # ulozime argumenty a odsekneme 1. param.
        argv = self.argv
        argc = len(argv)

        # kdyby tam nekdo nahodou dal velky pocet parametru
        if (argc < 1 or argc > 5):
            Error(10, 'Nespravny pocet argumentu')
        else:
            for arg in argv:
                # osekneme -- ze zacatku
                arg = arg[2:]
                optarg = ""

                # podivame se, jestli nahodou nemame optarg
                try:
                    index = arg.index('=')
                    optarg = arg[index + 1:]
                    arg = arg[:index]
                except ValueError:
                    pass

                # zkusime porovnat
                if (arg in self.accepted):

                    # duplicitni argumenty
                    if (self.accepted[arg]):
                        Error(10, 'Duplicitni argumenty')

                    # pokud chceme optarg
                    if (arg == 'source' or arg == 'stats'):
                        pass
                        # zde je povinny, takze kdyz error
                        if (optarg == ""):
                            Error(10, 'Source a Stats musi mit soubor')
                        else:
                            self.accepted[arg] = True
                            self.accepted[arg + "_file"] = optarg
                    # pokud mame pocitat pocet proveden instrukci
                    elif (arg == 'insts'):
                        if (self.accepted['vars'] == 1):
                            self.accepted[arg] = 2
                        else:
                            self.accepted[arg] = 1
                    # pokud mame pocitat pocet inicializovanych promennych
                    elif (arg == 'vars'):
                        if (self.accepted['insts'] == 1):
                            self.accepted[arg] = 2
                        else:
                            self.accepted[arg] = 1
                    else:
                        self.accepted[arg] = True
                else:
                    Error(10, 'Nevalidni parametr')

        # podivame se jestli je to validni a nastavime mod programu
        self.__argp_check_argv()
        # vratime zjisteny mod
        return {
            'mode': self.mode,
            'src_url': self.accepted.get('source_file'),
            'stats_url': self.accepted.get('stats_file')
        }
コード例 #22
0
    def _fn_prepare_args(self, index):
        # indexace v predpisech
        rules = self.config
        # pole s pripravenymi argumenty
        prepared_args = []
        # pro loopovani
        argv_index = 0
        # insturukce bez parametru
        if (rules != []):
            #zkontroluj, jestli vsechny pravidla sedi
            for rule in rules:
                # reset nalezeneho typu
                match_type = None
                # nastaveni typu a modu (cteni, zapis, oboje)
                arg_type = rule[0]
                # pokud je to promenna
                if (arg_type == 'var'):
                    # vytvorim z ni symbol
                    var_temp = Symbol(self.argv[argv_index], self.frames)
                    # nactu si mod
                    var_mode = rule[1]
                    # jinak proste vytvorime objekt pro symbol
                    # a posilame dale (v samotnych funkcich uz
                    # resime tvoreni ci zapis)
                    prepared_args.append(var_temp)

                # prace se symbolem (tedy literal nebo promenna)
                elif (arg_type == 'symb'):
                    #
                    allowed_types = rule[1]
                    symbol_defined = rule[2]
                    # vytvor docasny symbol pro polozky symb
                    temp = Symbol(self.argv[argv_index], self.frames)
                    # zde nas zajima jakou metodu mame pouzit, jelikoz pri 'move' je dovoleno int@
                    # treba u scitani nemuzeme scitat prazdny datovy typ, jehoz hodnota je nedefinovana
                    # TODO: problem u setchar a prazdneho stringu, zkus to
                    temp = temp.symb_get_defined(
                    ) if symbol_defined else temp.symb_get()
                    # existuje mnozina povolenych datovych typu? Jestli ano, musime
                    # kontrolovat, jinak proste pridame nactenou polozku
                    if (allowed_types == []):
                        prepared_args.append(temp)
                    elif (allowed_types == ["="]):
                        prepared_args.append(temp)
                    else:
                        # projed vsechny akceptovane typy
                        has_type = None
                        # pokud nemame zadny datovy typ
                        if (match_type == None):
                            for t in allowed_types:
                                if (t == temp['type']):
                                    has_type = t
                        # pokud ho j*z mame, nemusime nic resit
                        else:
                            has_type = match_type if match_type == temp[
                                'type'] else None

                        # osetreni chyby, pripadna dalsi obrata v cyklu
                        if (has_type == None):
                            Error(
                                53,
                                'Zadany datovy typ nepodporuje operaci zadanou instrukci'
                            )
                        else:
                            # nastavime realny datovy typ
                            match_type = has_type
                            prepared_args.append(temp)

                elif (arg_type == 'label'):
                    prepared_args.append(self.argv[argv_index].get('value'))
                else:
                    Error(99, 'Neznamy typ parametru')
                # posunuti se v poli parametru
                argv_index += 1

            # prevod na tuple z duvodu vyhodnosti volani funkcnich parametru
            return tuple(prepared_args)
コード例 #23
0
 def _popframe(self):
     if (self.frames.get('stack').not_empty()):
         self.frames['tf'] = self.frames['stack'].pop()
         self.frames.get('tf').frame_lf2tf()
     else:
         Error(55, 'Soudruhu, chces si do TF ulozit LF, ale zadne tam neni')