python - 解析此脚本语言的最有效方法

标签 python lexer shlex

我正在为一种过时的文本编辑器的脚本语言实现一个解释器,但我在让词法分析器正常工作时遇到了一些麻烦。

这是语言中有问题的部分的示例:

T
L /LOCATE ME/
C /LOCATE ME/CHANGED ME/ * *
C ;CHANGED ME;CHANGED ME AGAIN; 1 *

/ 字符似乎引用字符串,也充当 sed 中 C (CHANGE) 命令的定界符 类型的语法,尽管它允许任何字符作为分隔符。

到现在为止,我可能已经实现了大约一半的最常用命令,仅使用 parse_tokens(line.split())。这既快又脏,但效果出奇地好。

为了避免编写自己的词法分析器,我尝试了 shlex

它工作得很好,除了 CHANGE 情况:

import shlex

def shlex_test(cmd_str):
    lex = shlex.shlex(cmd_str)
    lex.quotes = '/'
    return list(lex)

print(shlex_test('L /spaced string/'))
# OK! gives: ['L', '/spaced string/']

print(shlex_test('C /spaced string/another string/ * *'))
# gives   : ['C', '/spaced string/', 'another', 'string/', '*', '*']
# desired : any format that doesn't split on a space between /'s

print(shlex_test('C ;a b;b a;'))
# gives   : ['C', ';', 'b', 'a', ';', 'a', 'b', ';']
# desired : same format as CHANGE command above

有谁知道完成此操作的简单方法(使用 shlex 或其他方式)?

编辑:

如果有帮助,这里是帮助文件中给出的 CHANGE 命令语法:

'''
C [/stg1/stg2/ [n|n m]]

    The CHANGE command replaces the m-th occurrence of "stg1" with "stg2"
for the next n lines.  The default value for m and n is 1.'''

同样难以标记化 XY 命令:

'''
X [/command/[command/[...]]n]
Y [/command/[command/[...]]n]

    The X and Y commands allow the execution of several commands contained
in one command.  To define an X or Y "command string", enter X (or Y)
followed by a space, then individual commands, each separated by a
delimiter (e.g. a period ".").  An unlimited number of commands may be
placed in the X or Y command string.  Once the command string has been
defined, entering X (or Y) followed optionally by a count n will execute
the defined command string n times.  If n is not specified, it will
default to 1.'''

最佳答案

问题可能是 / 不代表引号,而仅代表定界。我猜第三个字符总是用于定义分隔符。此外,您不需要 /; 在输出中,对吗?

我只是对 L 和 C 命令用例进行了拆分:

>>> def parse(cmd):
...     delim = cmd[2]
...     return cmd.split(delim)
...
>>> c_cmd = "C /LOCATE ME/CHANGED ME/ * *"
>>> parse(c_cmd)
['C ', 'LOCATE ME', 'CHANGED ME', ' * *']

>>> c_cmd2 = "C ;a b;b a;"
>>> parse(c_cmd2)
['C ', 'a b', 'b a', '']

>>> l_cmd = "L /spaced string/"
>>> parse(l_cmd)
['L ', 'spaced string', '']

对于可选的 "* *" 部分,您可以在最后一个列表元素上使用 split("")

>>> parse(c_cmd)[-1].split(" ")
['', '*', '*']

关于python - 解析此脚本语言的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11565618/

相关文章:

c - 在 Flex Lexer 中,为什么在加载新输入之前将最后一个字符移动到缓冲区的开头?

python - 使用python设置组权限

Python 按空格拆分字符串,除非在引号中,但保留引号

python - 如何卸载并重新安装 anaconda navigator

python - Keras - on_batch_end 方法很慢,但我只有回调是检查点

ANTLR4 ATN 代表什么?

java - ANTLR:Unicode 字符扫描

python - distutils.util.split_quoted 和 shlex.split 之间有什么区别

python - 在 wxpython 中单击按钮后如何禁用按钮?

python - entry_points 不会在 Python 中使用 pip 或 easy_install 创建自定义脚本?