class CppState: # export def __init__(self): self.__pair_square = ['[', ']'] self.__pair_curly = ['{', '}'] self.__pair_ext = ['<', '>'] self.__pair_paren = ['(', ')'] self.__pair_c_comment = ['/*', '*/'] self.__pair_special = ['?', '?'] self.reset() def reset(self): self.curly = 0 self.square = 0 self.ext = 0 self.paren = 0 self.in_c_comment = False self.in_cpp_comment = False self.in_special = False self.rule = [] self.rules = [] self.things = [] def optional(self): return self.square != 0 or self.curly != 0 def update(self, tok, line): if not self.in_comment(): if tok == '[': self.square += 1 self.things.append(self.__pair_square) elif tok == ']': self.square -= 1 assert(self.things.pop() == self.__pair_square) elif tok == '{': self.curly += 1 self.things.append(self.__pair_curly) elif tok == '}': self.curly -= 1 assert(self.things.pop() == self.__pair_curly) elif tok == '(': self.paren += 1 self.things.append(self.__pair_paren) elif tok == ')': self.paren -= 1 assert(self.things.pop() == self.__pair_paren) elif tok == '<': self.ext += 1 self.things.append(self.__pair_ext) elif tok == '>': self.ext -= 1 assert(self.things.pop() == self.__pair_ext) elif tok == '?': if not self.in_special: self.in_special = True self.things.append(self.__pair_special) else: self.in_special = False assert(self.things.pop() == self.__pair_special) elif tok == '/*': self.in_c_comment = True self.things.append(self.__pair_c_comment) elif tok == '*/': raise Exception("Unmatched closing C-style comment mark", tok, "in line", line) else: if self.in_cpp_comment: if tok == '\n': self.in_cpp_comment = False return if tok == '/*': raise Exception("Nested C-style comment", tok, "in line", line) elif tok == '*/': assert(self.things.pop() == self.__pair_c_comment) self.in_c_comment = False if self.curly < 0 or self.square < 0 or self.ext < 0 or self.paren < 0: raise Exception("Unbalanced BNF bracket", tok, "in line", line) return self.optional() def in_list(self): return self.curly > 0 def in_option(self): return self.square > 0 def in_paren(self): return self.paren > 0 def in_ext(self): return self.ext > 0 def in_comment(self): return self.in_c_comment or self.in_cpp_comment def in_something(self): if len(self.things) == 0: return None return self.things[-1] def is_optional(self): return self.in_list() or self.in_option()