def add_arg(self, name): if name in self.args.keys(): #redefinice argumentu; exit_err("Semantic error (argument redefinition - '" + name + "')", 56); self.args[name] = ''; self.args_ord_name.append(name); self.args_cnt += 1;
def set_next_arg(self, value): if self.args_order == self.args_cnt: #prilis mnoho parametru sys.stderr.write("Syntax error\n"); sys.exit(56); if self.is_def and self.args_order == 0 and value[0] != '@': exit_err("Macro name expected ('" + value + "' given)", 57); self.args[self.args_ord_name[self.args_order]] = value; self.args_order += 1;
def _read_at(self): self.at_result = "" char = self.act_char() if re.match("(@|{|}|\$)", char): self.at_result += char self.next_char() return False elif re.match("[a-zA-Z_]", char): self.name_result = "@" + char self.next_char() self.read_name() return True else: exit_err("Syntax error (read_at)", 55)
def _read_def_block(self): state = 0 self.block_result = "" while (self.index < self.length): char = self.act_char() if state == 0: if char == "$": state = 1 elif char == "}": self.next_char() return elif not re.match("\s", char): exit_err("Wrong def argument list identifier", 55) elif state == 1: if not re.match("[a-zA-Z_]", char): exit_err("Wrong def argument list identifier", 55) state = 2 elif state == 2: if char == "$": state = 1 elif re.match("\s", char): state = 0 elif char == "}": self.next_char() return elif not re.match("[0-9a-zA-Z_]", char): exit_err("Wrong def argument list identifier", 57) self.block_result += char self.next_char() exit_err("Syntax error ('{' without '}')", 55)
def _expand_let(self): self.body = ""; first = self.args[self.args_ord_name[0]]; second = self.args[self.args_ord_name[1]]; if first[0] != '@' or second[0] != '@': exit_err("let macro requires macro names as both arguments", 57); if first == "@null": return self.body; if first == "@__def__" or first == "@__let__" or first == "@__set__": exit_err("Redef __macro__ error", 57); if second == "@null": if first in macro_list: del macro_list[first]; return self.body; macro_list[first] = macro_list[second]; return self.body;
def _expand_def(self): name = self.args[self.args_ord_name[0]]; arg_list = self.args[self.args_ord_name[1]]; def_body = self.args[self.args_ord_name[2]]; new_macro = Macro(name); if name == "@__def__" or name == "@__let__" or name == "@__set__": exit_err("Redef __macro__ error", 57); if name == "@null": return ""; if self.redef and name in macro_list: exit_err("Redef -r macro error", 57); m = re.findall("\$[a-zA-Z_][a-zA-Z_0-9]*", arg_list); for rex in m: new_macro.add_arg(rex); new_macro.set_body(def_body); macro_list[name] = new_macro; return "";
def _read_mode(self): while (self.index < self.length): char = self.act_char() if char == '@': self.next_char() if self.read_at(): # got macro name - read arguments and expand it if self.name_result not in Macro.macro_list.keys(): exit_err( "Semantic error (macro '" + self.name_result + "' not found)", 56) name = self.name_result self.read_args(name) to_join = Macro.macro_list[name].expand() self.text = to_join + self.text[self.index:] self.index = 0 self.length = len(self.text) else: self.result += self.at_result elif char == '{': self.next_char() self.read_block() self.result += self.block_result elif char == '}': exit_err("Syntax error ('}' without '{')", 55) elif char == '$': exit_err("Syntax error ('$')", 55) else: if not (Config.ignore_white and re.match("\s", char)): self.result += char self.next_char()
def _read_block(self): self.block_result = "" self.in_block += 1 while (self.index < self.length): char = self.act_char() if char == '{': self.in_block += 1 self.block_result += '{' elif char == '}': self.in_block -= 1 if self.in_block == 0: self.next_char() return self.block_result += '}' elif char == '@': if re.match("(@|{|})", self.text[self.index + 1]): self.block_result += self.text[self.index + 1] self.next_char() else: self.block_result += char else: self.block_result += char self.next_char() exit_err("Syntax error ('{' without '}')", 55)
def _read_args(self, name): cnt = Macro.macro_list[name].get_num_of_args() for i in range(0, cnt): if self.index >= self.length: exit_err( "Semantic error (too few arguments for macro '" + name + "', " + str(i) + "/" + str(cnt) + ")", 56) if Config.ignore_white: while re.match("\s", self.act_char()): self.next_char() if self.index >= self.length: exit_err( "Semantic error (too few arguments for macro '" + name + "', " + str(i) + "/" + str(cnt) + ")", 56) char = self.act_char() if Macro.macro_list[name].is_def and (i == 1 or i == 2) and char != '{': exit_err("def macro requires blocks as second and third arguments", 57) if Macro.macro_list[name].is_set and char != '{': exit_err("set macro requires block as argument", 57) if char == "@": self.next_char() if self.read_at(): arg = self.name_result else: arg = self.at_result elif char == "{": self.next_char() if Macro.macro_list[name].is_def and i == 1: self.read_def_block() else: self.read_block() arg = self.block_result else: arg = char self.next_char() Macro.macro_list[name].set_next_arg(arg)