美文网首页
【小实验】用Python将简单的缩进树语法解析成AST对象

【小实验】用Python将简单的缩进树语法解析成AST对象

作者: SystemLight | 来源:发表于2020-10-10 11:16 被阅读0次

view.tree

generate
  adt
    edit
    edit2
generate-2
  adt-2
  adt-3
    edit3
    edit5

main.py

import string
import json

"""

    缩进树语法解析器,将缩进树结构解析成AST语法树对象

"""

token = []
tokens = []
chars = string.ascii_letters + string.digits + "[]-"


class EOF:
    pass


def emmit_token(_type):
    global token
    tokens.append({"type": _type, "value": "".join(token)})
    token = []


def start(char):
    if char in chars:
        token.append(char)
        return is_chars

    if char in "\r\n":
        token.append(char)
        return is_wrap_line

    if char == " ":
        token.append(char)
        return is_space

    raise SyntaxError("无效字符")


def is_chars(char):
    if isinstance(char, EOF):
        emmit_token("Name")
        return start

    if char in chars:
        token.append(char)
        return is_chars

    if char in "\r\n":
        emmit_token("Name")
        token.append(char)
        return is_wrap_line

    if char == " ":
        emmit_token("Name")
        token.append(char)
        return is_space

    raise SyntaxError("无效字符")


def is_wrap_line(char):
    if isinstance(char, EOF):
        emmit_token("WrapLine")
        return start

    if char in chars:
        emmit_token("WrapLine")
        token.append(char)
        return is_chars

    if char in "\r\n":
        token.append(char)
        return is_wrap_line

    if char == " ":
        emmit_token("WrapLine")
        token.append(char)
        return is_space

    raise SyntaxError("无效字符")


def is_space(char):
    if isinstance(char, EOF):
        emmit_token("WhiteSpace")
        return start

    if char in chars:
        emmit_token("WhiteSpace")
        token.append(char)
        return is_chars

    if char in "\r\n":
        emmit_token("WhiteSpace")
        token.append(char)
        return is_wrap_line

    if char == " ":
        token.append(char)
        return is_space

    raise SyntaxError("无效字符")


with open("./views.tree", "r") as fp:
    content = fp.read()
    state = start
    for c in content:
        state = state(c)
    state(EOF())
obj = []


def expression():
    current = 0
    size = len(tokens)
    distance = 0

    def walk(parent_distance=-1):
        nonlocal current, size, distance

        node_list = []
        while True:
            if current >= size:
                return node_list

            _token = tokens[current]

            if _token["type"] == "WrapLine":
                distance = 0

            if _token["type"] == "WhiteSpace":
                distance = len(_token["value"])
                if distance <= parent_distance:
                    return node_list

            if _token["type"] == "Name":
                if distance == 0 and parent_distance != -1:
                    current -= 1
                    return node_list

                node = {
                    "type": "ItemLiteral",
                    "name": _token["value"],
                    "item": []
                }
                current += 1
                node["item"] = walk(distance)
                node_list.append(node)

                if distance <= parent_distance:
                    return node_list

            current += 1

    return walk()


print(json.dumps(expression(), indent=4))

相关文章

网友评论

      本文标题:【小实验】用Python将简单的缩进树语法解析成AST对象

      本文链接:https://www.haomeiwen.com/subject/nbbdpktx.html