jw-python/tools/python/jwutils/CppState.py

102 lines
3.3 KiB
Python
Raw Normal View History

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()