You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于PLY解析PlantUML定义语言:冒号后转义字符串解析问题

我之前处理过PlantUML语法解析的类似场景,针对你提到的「冒号后所有内容需视为带转义的字符串,直到换行符结束,忽略内部标点」的需求,这里给你一套实用的解决思路和代码参考:

核心方案:基于行的状态机解析

PlantUML是面向行的语言,所以我们可以按行遍历,通过状态标记来区分「普通语法模式」和「冒号后字符串模式」,核心逻辑如下:

  • 初始处于普通语法模式,逐个字符收集token,直到遇到冒号:;
  • 碰到冒号后,立即切换到字符串模式,从冒号的下一个字符开始,所有内容(包括内部的标点、特殊符号)都作为字符串内容捕获,直到遇到换行符\n;
  • 字符串模式中优先处理转义字符:如果碰到\,则将下一个字符直接加入字符串,忽略其特殊语法意义(比如\:会被解析成普通冒号,\\解析成单个反斜杠)。
代码示例(Python)

下面是一个简单的单行解析实现,你可以基于此扩展到完整的解析器:

def parse_plantuml_single_line(line):
    parsed_result = []
    current_segment = []
    in_string_mode = False
    need_escape = False

    for char in line:
        # 优先处理转义逻辑
        if need_escape:
            current_segment.append(char)
            need_escape = False
            continue

        if not in_string_mode:
            # 未进入字符串模式,遇到冒号则切换状态
            if char == ':':
                # 先把之前收集的普通token存入结果
                if current_segment:
                    parsed_result.append(("normal_token", ''.join(current_segment)))
                    current_segment = []
                in_string_mode = True
                # 冒号本身不加入字符串,跳过
                continue
            # 普通字符继续收集
            current_segment.append(char)
        else:
            # 处于字符串模式,直到换行符结束
            if char == '\n':
                parsed_result.append(("quoted_string", ''.join(current_segment)))
                current_segment = []
                in_string_mode = False
                break
            # 遇到反斜杠标记下一个字符需要转义
            elif char == '\\':
                need_escape = True
                continue
            # 其他字符直接加入字符串
            current_segment.append(char)
    
    # 处理行尾剩余的未完成内容
    if current_segment:
        if in_string_mode:
            parsed_result.append(("quoted_string", ''.join(current_segment)))
        else:
            parsed_result.append(("normal_token", ''.join(current_segment)))
    
    return parsed_result

# 测试用例
test_input = "Bob : Hi\\, there! My name is Bob (and I have parentheses)"
print(parse_plantuml_single_line(test_input))
# 预期输出:[('normal_token', 'Bob '), ('quoted_string', 'Hi, there! My name is Bob (and I have parentheses)')]
关键注意事项
  • 严格以换行符为边界:PlantUML中冒号后的字符串默认不会跨多行(除非使用续行符\,如果你的测试输入包含这种情况,可以在状态机中额外判断续行逻辑);
  • 转义逻辑优先:一定要先处理\的转义,再判断是否触发其他语法规则,否则会把转义后的字符误判为语法符号;
  • 避免用正则拆分:因为字符串内部可能包含任意标点,用正则拆分冒号很容易误切割,状态机是更可靠的方案。

内容的提问来源于stack exchange,提问作者ZioByte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:28:31