def parse_marker(strings: list): log(strings) assert len(strings) == 1 name = strings[0] token = Token(name, MARKER) node = Node(token) stack.append(node)
def parse_string(strings: list): log(strings) assert len(strings) == 1 name = strings[0] if name[0] not in ('"', "'"): name = "'" + name + "'" token = Token(name, STRING) node = Node(token) stack.append(node)
def parse_invocation(strings: list): log(strings) assert len(strings) > 1 num_arguments = min(len(strings) - 2, list(strings).count(",") + 1) assert len(stack) >= num_arguments name = strings[0] + strings[-1] token = Token(name, INVOCATION) node = Node(token, *stack[-num_arguments:]) del stack[-num_arguments:] stack.append(node)
def parse_operator(strings: list): log(strings) assert len(strings) >= 1 assert len(stack) > 1 name = " ".join(strings) token = Token(name, OPERATOR) right = stack.pop() left = stack.pop() node = Node(token, left, right) stack.append(node)
def parse_label(strings: list): log(strings) assert len(strings) == 1 assert len(stack) == 1 name = strings[0] if name == SHORT_WEAK: name = WEAK token = Token(name, LABEL) node = Node(token, stack.pop()) tree.root.children.append(node)
def parse_function(strings: list): log(strings) assert len(strings) == 1 assert len(stack) > 0 assert stack[-1].token.name == INVOCATION assert stack[-1].token.type == INVOCATION assert len(stack[-1].children) == 2 assert strings[0] == GET token = Token(GETATTR, OPERATOR) node = Node(token, *stack.pop().children) stack.append(node)
def typing(raw_tokens: Iterable[str]) -> Iterable[Token]: def get_type() -> str: if len(raw_token) > 1 and raw_token[0] in ( '"', "'") and raw_token[0] == raw_token[-1]: return Types.STRING matches = re.match(r"%s\[(0|[1-9][0-9]*)\]" % Tokens.PARAM, raw_token) if matches: return Types.MARKER try: index = { name == raw_token: type for type, names in Tokens.instances.items() for name in names } return index[True] except KeyError: raise ValueError("Token with name '%s' can't be identified" % raw_token) for raw_token in raw_tokens: yield Token(raw_token, get_type())
def parse(code: str) -> Tree: def log(strings: list): # print("\t{:<15} -> {:s}".format(" ".join(strings), ":".join(str(node) for node in stack))) pass def parse_label(strings: list): log(strings) assert len(strings) == 1 assert len(stack) == 1 name = strings[0] if name == SHORT_WEAK: name = WEAK token = Token(name, LABEL) node = Node(token, stack.pop()) tree.root.children.append(node) def parse_function(strings: list): log(strings) assert len(strings) == 1 assert len(stack) > 0 assert stack[-1].token.name == INVOCATION assert stack[-1].token.type == INVOCATION assert len(stack[-1].children) == 2 assert strings[0] == GET token = Token(GETATTR, OPERATOR) node = Node(token, *stack.pop().children) stack.append(node) def parse_operator(strings: list): log(strings) assert len(strings) >= 1 assert len(stack) > 1 name = " ".join(strings) token = Token(name, OPERATOR) right = stack.pop() left = stack.pop() node = Node(token, left, right) stack.append(node) def parse_marker(strings: list): log(strings) assert len(strings) == 1 name = strings[0] token = Token(name, MARKER) node = Node(token) stack.append(node) def parse_string(strings: list): log(strings) assert len(strings) == 1 name = strings[0] if name[0] not in ('"', "'"): name = "'" + name + "'" token = Token(name, STRING) node = Node(token) stack.append(node) def parse_invocation(strings: list): log(strings) assert len(strings) > 1 num_arguments = min(len(strings) - 2, list(strings).count(",") + 1) assert len(stack) >= num_arguments name = strings[0] + strings[-1] token = Token(name, INVOCATION) node = Node(token, *stack[-num_arguments:]) del stack[-num_arguments:] stack.append(node) try: stack: List[Node] = [] root_token = Token(ROOT, ROOT) root_node = Node(root_token) tree = Tree(root_node) parsers = { LABEL: parse_label, FUNCTION: parse_function, OPERATOR: parse_operator, MARKER: parse_marker, STRING: parse_string, INVOCATION: parse_invocation } parser = build(parsers) parser.parseString(code) assert len(stack) == 0 Validator().accept(tree) return tree except AssertionError: raise ParseException(code, 0, 0, 0) except pyparsing.ParseException as ex: raise ParseException.value_of(code, ex)