我玩了这个,如果你在你的问题中放一个完整的最小可重现示例(mre),这对我来说会容易得多,快 15 分钟 - 请下次这样做,因为我不打算在未来花 15 分钟重新创建应该在您的问题中的东西。特别是让它成为一个完整的代码块,包含所有需要的导入,如果你想用文本块分割它,请抵制并使用 Python 注释代替该文本
所以这是一个免费的mre。
有一件事是,对于单个打印语句“HI”,我没有得到相同的结果——我得到了一个带有 STRING 值“HI”的令牌。
首先我添加了-> statements
然后我删除了,string = str
因为那是不对的:它将值(始终是列表)转换为列表的文字作为字符串。
然后我添加了一个string()
变压器和statements()
变压器。让他们打印他们的输入和返回值可以更容易地看到发生了什么。在我使用 Lark 的项目中,我保留了这些标识转换器功能和输入/输出的打印件,直到我得到它所有的稳定+工作 - 所以我可以检查一个标识符是否正确地被转换为一个 URI,或者两个正在添加添加的值并返回单个值。
转换器函数 takevalue
它始终是一个列表,对于像 print 或 string 这样的一元运算符返回其中的第一个(唯一)项目。接受两个输入的运算符将把这两个东西作为两个条目添加到 中value
,将它们相加并返回结果;这就是转变。
Token 是带有元数据的 str,运行此代码时可以看到结果。
from lark import Lark
from lark.indenter import Indenter
from lark import Transformer, v_args
grammar = """
?start: expr
| statement* -> statements // ADDED
?expr: STRING -> string
?statement: "print" "(" expr ")" ";" -> print_statement
%import common.ESCAPED_STRING -> STRING
%declare _INDENT _DEDENT
%import common.WS_INLINE
%ignore WS_INLINE
%import common.NEWLINE -> _NL
%ignore _NL
"""
class MainIndenter(Indenter):
NL_type = '_NL'
OPEN_PAREN_types = ['LPAR', 'LBRACE']
CLOSE_PAREN_types = ['RPAR', 'RBRACE']
INDENT_TYPE = '_INDENT'
DEDENT_type = '_DEDENT'
tab_len = 8
class MainTransformer(Transformer):
# string = str # REMOVED
def string(self,value): # ADDED
print( f"string {value=}" )
res = value[0] # this seems like quite a common thing to do for a unary thing like string - return value[0]
print( f"string returning {res}" )
return res
def print_statement(self, value):
print( f"print_statement {value=}" )
# value = str(value).strip('"')
res = value[0] # this seems like quite a common thing to do for a unary thing like print - return value[0]
print( f"print_statement returning {res}" )
return res
def statements(self,value): # ADDED
print( f"statements {value=}" )
for i,v in enumerate(value):
print( f" {i=} {v=}" )
return value
parser = Lark(grammar, parser="lalr", transformer=MainTransformer(), postlex=MainIndenter())
main_parser = parser.parse
hiho_input_str = '''
print("HI");
print("HO");
print("HI");
print("HO");
'''
hihoresult = main_parser(hiho_input_str)
print( "hiho result=")
for i,hiho in enumerate(hihoresult):
print(f" {i} {hiho}")
print()
hi_input_str = '''
print("HI");
'''
print("Hi result=",main_parser(hi_input_str))
结果:
string value=[Token('STRING', '"HI"')]
string returning "HI"
print_statement value=[Token('STRING', '"HI"')]
print_statement returning "HI"
string value=[Token('STRING', '"HO"')]
string returning "HO"
print_statement value=[Token('STRING', '"HO"')]
print_statement returning "HO"
string value=[Token('STRING', '"HI"')]
string returning "HI"
print_statement value=[Token('STRING', '"HI"')]
print_statement returning "HI"
string value=[Token('STRING', '"HO"')]
string returning "HO"
print_statement value=[Token('STRING', '"HO"')]
print_statement returning "HO"
statements value=[Token('STRING', '"HI"'), Token('STRING', '"HO"'), Token('STRING', '"HI"'), Token('STRING', '"HO"')]
i=0 v=Token('STRING', '"HI"')
i=1 v=Token('STRING', '"HO"')
i=2 v=Token('STRING', '"HI"')
i=3 v=Token('STRING', '"HO"')
hiho result=
0 "HI"
1 "HO"
2 "HI"
3 "HO"
string value=[Token('STRING', '"HI"')]
string returning "HI"
print_statement value=[Token('STRING', '"HI"')]
print_statement returning "HI"
statements value=[Token('STRING', '"HI"')]
i=0 v=Token('STRING', '"HI"')
Hi result= [Token('STRING', '"HI"')]
如果您可能想要更改字符串返回的内容,请先执行此操作,因为该更改会通过转换器中的项目向上传播。