Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为花括号构造解析C文件_Python_Yacc_Lex_Ply - Fatal编程技术网

Python 为花括号构造解析C文件

Python 为花括号构造解析C文件,python,yacc,lex,ply,Python,Yacc,Lex,Ply,我想用PLY解析一些C代码。 我想摘录以下内容: {ARGUMENT1, ARGUMENT2, ARGUMENT3, ARGUMENT4} ARGUMENT1, ARGUMENT2, ARGUMENT3, ARGUMENT4 Argument1, Argument2, Argument3, Argument4 这个结构可以隐藏在一些更大的花括号中 {SOME, RANDOM, STUFF {ARGUMENT1, ARGUMENT2, ARGUMENT3, ARGUMENT4}, SOME,

我想用PLY解析一些C代码。 我想摘录以下内容:

{ARGUMENT1, ARGUMENT2, ARGUMENT3, ARGUMENT4}
ARGUMENT1, ARGUMENT2, ARGUMENT3, ARGUMENT4
Argument1, Argument2, Argument3, Argument4
这个结构可以隐藏在一些更大的花括号中

{SOME, RANDOM, STUFF {ARGUMENT1, ARGUMENT2, ARGUMENT3, ARGUMENT4}, SOME, MORE, RANDOM, STUFF }
目前,我可以为我想要提取的结构lex
ARGUMENT1、ARGUMENT2、ARGUMENT3、ARGUMENT4
,但前提是它是唯一匹配的

    {SOME, RANDOM, STUFF {ARGUMENT1, ARGUMENT2, ARGUMENT3, ARGUMENT4}, SOME, MORE, RANDOM, STUFF }{Argument1, Argument2, Argument3, Argument4}
这就是我当前方法失败的地方,因为上面示例中的词法分析输出是:

ARGUMENT1, ARGUMENT2, ARGUMENT3, ARGUMENT4}, SOME, MORE, RANDOM, STUFF }{Argument1, Argument2, Argument3, Argument4
我如何才能收到以下信息:

{ARGUMENT1, ARGUMENT2, ARGUMENT3, ARGUMENT4}
ARGUMENT1, ARGUMENT2, ARGUMENT3, ARGUMENT4
Argument1, Argument2, Argument3, Argument4
简要说明: 我有一个条件lexer,它搜索左大括号来保存它的位置。 对于每个新的左大括号,我增加一个计数器。 对于每一个右括号,我减小计数器。 如果计数器为零,我开始将
t.value
设置为从最新的左大括号到下一个右大括号的所有元素。 我想这应该适用于一个示例字符串中的多个命中。 在我看来,我无法从
ccode
状态切换回
initial
状态

现在来看我的实际代码(在本例中,我省略了大括号中的逗号,以使编程更简单):

数据只是一个简单示例的测试字符串。 但是在我的C源文件中,有一些构造我想提取
Argument1、Argument2、Argument3、Argument4
。 显然,这些C文件不会编译,但没有必要编译,因为它们包含在其他一些文件中


谢谢你的所有意见

你的描述不太清楚。您的示例似乎表明您希望找到一个不包含任何子列表的大括号列表。这就是我要解决的问题

注意,通常不建议尝试在lexer中完成所有这些工作。lexer通常应该返回简单的原子标记,让解析器的语法来完成将标记组合成有用结构的工作。但是,如果我对您的用例有正确的理解,那么就有可能用lexer实现这一点

代码决定是否返回CCODE标记,这取决于深度计数器在命中右大括号时是否为0。但这显然不是你想要的:你不在乎大括号嵌套得有多深;相反,当遇到右大括号时,您需要知道它是否是最里面的大括号。您不需要堆栈,因为您只需要读取最后一次打开的大括号的位置,并且只需要在它未关闭时读取。因此,每次看到打开的支撑时,都要设置最后一个打开的支撑位置,当看到关闭的支撑时,要检查是否设置了最后一个打开的支撑位置。如果是,则可以返回该位置之后的字符串,并将最后打开的大括号位置设置为
None
。如果未设置,则继续扫描

下面是一个基于您的代码的简化示例:

将ply.lex导入为lex
#申报国家
国家=(
(“ccode”、“exclusive”),
)
代币=[
“文本”,
“CCODE”
]
#从t_更改为ANY_TEXT,因为否则会将所有文本都包含在内
#还有牙套。也许这正是您想要的,但它会减少输出
#清楚。
def t_文本(t):
r'\w+'
t、 值=str(t.value)
返回t
#匹配第一个{。输入ccode状态。
def t_代码(t):
r'\{'
t、 lexer.current_open=t.lexer.lexpos#记录起始位置
t、 lexer.level=1#初始支撑标高
t、 lexer.begin('ccode')#输入'ccode'状态
#t_lbrace和t_rbrace被删除,因为它们从不匹配
#ccode状态的规则
def t_ccode_lbrace(t):
r'\{'
t、 lexer.current_open=t.lexer.lexpos
t、 lexer.level+=1
定义代码(t):
r'\}
t、 lexer.level-=1
如果t.lexer.level==0:
t、 lexer.begin('首字母')
如果t.lexer.current_open不是None:
t、 value=t.lexer.lexdata[t.lexer.current\u open:t.lexer.lexpos-1]
t、 type=“CCODE”
t、 lexer.current\u open=无
返回t
C或C++注释(忽略)
定义代码注释(t):
r'(/\*(.\n)*?\*/)|(/.*)”
#C字符串
def t_代码_字符串(t):
r'\'([^\\\n]|(\\)*?\“'
#C字符文字
def t_ccode_char(t):
r'\'([^\\\n]|(\\)*?\''
#任何非空白字符序列(不是大括号、字符串)
def t_ccode_nonspace(t):
r''[^\s{}']+'''#无需在字符类内转义
#忽略的字符(空白)
t\u ccode\u ignore=“\t\n”
#对于坏角色,我们跳过它
def t_代码错误(t):
t、 lexer.skip(1)
def t_错误(t):
t、 lexer.skip(1)
lexer=lex.lex()
data=''{我不想收到这个
{这就是我想看到的}
而且我不想收到这个}
花括号外
{我想再看一遍}
'''
lexer.input(数据)
对于lexer中的tok:
打印(tok)
样本运行:

$python3嵌套_brace.py
LexToken(CCODE,“这是我想看到的”,1,58)
LexToken(文本,“外部”,1102)
LexToken(文本,'OF',1110)
LexToken(文本,'CURLY',1113)
LexToken(文本,“大括号”,1119)
LexToken(代码“我想再看一次”,1152)

我对C代码部分感到困惑。
数据
C代码对吗?也许你能说得更清楚些吗?我补充了一些解释。数据只是一个测试字符串,便于编程。我的C源文件中的示例与此测试字符串类似。当然,这些C文件不会编译,但不需要编译因为它们包含在其他文件中。当您删除一个问题时,您会有效地阻止任何答案(或评论)。多输入问题的问题可能是您在检测到错误后没有调用
lexer.begin('INITIAL')
。即使您提供了新的输入,Ply lexer也不会自动重置(这有点奇怪,而且afaik没有文档记录)。我不能确定这是你的问题,因为我没有一个示例输入来测试,但这是一个合理的理论。非常感谢你!我只是没有想到只搜索第一个大括号…我想我会的