我正在构建一个名为C--(不是实际的C语言)的虚构编程语言的解析器.我已经到了需要将语言的语法翻译成Pyparsing可以接受的东西的阶段.不幸的是,当我来解析我的输入字符串(这是正确的,不应该导致Pyparsing错误)时,它没有正确解析.我担心这是由于我的语法错误,但是当我第一次开始Pyparsing时,我似乎无法看到我出错的地方.
我上传我是从翻译语法这里的人们有一个读通过.
编辑:更新了保罗的建议.
这是我目前得到的语法(我知道,语法定义的两个顶线对我来说非常糟糕):
# Lexical structure definition ifS = Keyword('if') elseS = Keyword('else') whileS = Keyword('while') returnS = Keyword('return') intVar = Keyword('int') voidKeyword = Keyword('void') sumdiff = Literal('+') | Literal('-') prodquot = Literal('*') | Literal('/') relation = Literal('<=') | Literal('<') | Literal('==') | \ Literal('!=') | Literal('>') | Literal('=>') lbrace = Literal('{') rbrace = Literal('}') lparn = Literal('(') rparn = Literal(')') semi = Literal(';') comma = Literal(',') number = Word(nums) identifier = Word(alphas, alphanums) # Syntax definition term = '' statement = '' variable = intVar + identifier + semi locals = ZeroOrMore(variable) expr = term | OneOrMore(Group(sumdiff + term)) args = ZeroOrMore(OneOrMore(Group(expr + comma)) | expr) funccall = Group(identifier + lparn + args + rparn) factor = Group(lparn + expr + rparn) | identifier | funccall | number term = factor | OneOrMore(prodquot + factor) cond = Group(lparn + expr + relation + expr + rparn) returnState = Group(returnS + semi) | Combine(returnS + expr + semi) assignment = Group(identifier + '=' + expr + semi) proccall = Group(identifier + lparn + args + rparn + semi) block = Group(lbrace + locals + statement + rbrace) iteration = Group(whileS + cond + block) selection = Group(ifS + cond + block) | Group(ifS + cond + block + elseS + block) statement = OneOrMore(proccall | assignment | selection | iteration | returnState) param = Group(intVar + identifier) paramlist = OneOrMore(Combine(param + comma)) | param params = paramlist | voidKeyword procedure = Group(voidKeyword + identifier + lparn + params + rparn + block) function = Group(intVar + identifier + lparn + params + rparn + block) declaration = variable | function | procedure program = OneOrMore(declaration)
我想知道我在翻译语法方面是否有任何错误以及我可以做些什么改进以使其简化,同时坚持我已经给出的语法.
编辑2:更新以包含新错误.
这是我正在解析的输入字符串:
int larger ( int first , int second ) { if ( first > second ) { return first ; } else { return second ; } } void main ( void ) { int count ; int sum ; int max ; int x ; x = input ( ) ; max = x ; sum = 0 ; count = 0 ; while ( x != 0 ) { count = count + 1 ; sum = sum + x ; max = larger ( max , x ) ; x = input ( ) ; } output ( count ) ; output ( sum ) ; output ( max ) ; }
这是我从终端运行程序时收到的错误消息:
/Users/Joe/Documents/Eclipse Projects/Parser/src/pyparsing.py:1156: SyntaxWarning: null string passed to Literal; use Empty() instead other = Literal( other ) /Users/Joe/Documents/Eclipse Projects/Parser/src/pyparsing.py:1258: SyntaxWarning: null string passed to Literal; use Empty() instead other = Literal( other ) Expected ")" (at char 30), (line:6, col:26) None
PaulMcG.. 33
1)更改Literal("if")
为Keyword("if")
(依此类推,直到Literal("void")
),以防止匹配名为变量的前导"if" "ifactor"
.
2) nums
,alphas
和alphanums
不表达,它们是字符串,可以与字类使用定义"单词"像"的数是由NUMS的一个字"时,以限定字符的一些典型的套,或"的标识符是一个以alpha开头的单词,后跟零个或多个alphanums." 所以代替:
number = nums identifier = alphas + OneOrMore(alphanums)
你要
number = Word(nums) identifier = Word(alphas, alphanums)
3)而不是Combine
,我想你想要Group
.使用Combine
当你想匹配的令牌是连续而没有中间的空白,并会连接这些令牌,并返回它们作为一个字符串. Combine
经常用于这样的情况:
realnum = Combine(Word(nums) + "." + Word(nums))
如果没有Combine
,解析"3.14"
将返回字符串列表['3', '.', '14']
,因此我们添加Combine
以便解析realnum的结果'3.14'
(然后您可以将其传递给解析操作以转换为实际浮动值3.14
). Combine
执行没有插入空格也使我们不会意外地解析'The answer is 3. 10 is too much.'
并认为"3. 10"
代表一个实数.
4)这不应该导致您的错误,但您的输入字符串有很多额外的空格.如果你得到你的语法的工作,你应该能够解析"int x;"
一样好"int x ;"
.
希望其中一些提示让你前进.您是否阅读过任何在线pyparsing文章或教程?请查看在线示例.你需要得到的是如何把握好Word
,Literal
,Combine
等执行各项解析任务.
5)您错误地实现了术语和语句的递归定义.''
写下:而不是分配给它们:
term = Forward() statement = Forward()
然后,当您使用递归定义实际定义它们时,请使用<<
运算符(并确保将RHS包含在()
s中).
term << (... term definition ...) statement << (... statement definition ...)
你可以找到一个递归解析器的例子在这里,并在基本pyparsing用法介绍这里 -请参见标题为"分析列表"上的递归如何处理的一步一步的.
1)更改Literal("if")
为Keyword("if")
(依此类推,直到Literal("void")
),以防止匹配名为变量的前导"if" "ifactor"
.
2) nums
,alphas
和alphanums
不表达,它们是字符串,可以与字类使用定义"单词"像"的数是由NUMS的一个字"时,以限定字符的一些典型的套,或"的标识符是一个以alpha开头的单词,后跟零个或多个alphanums." 所以代替:
number = nums identifier = alphas + OneOrMore(alphanums)
你要
number = Word(nums) identifier = Word(alphas, alphanums)
3)而不是Combine
,我想你想要Group
.使用Combine
当你想匹配的令牌是连续而没有中间的空白,并会连接这些令牌,并返回它们作为一个字符串. Combine
经常用于这样的情况:
realnum = Combine(Word(nums) + "." + Word(nums))
如果没有Combine
,解析"3.14"
将返回字符串列表['3', '.', '14']
,因此我们添加Combine
以便解析realnum的结果'3.14'
(然后您可以将其传递给解析操作以转换为实际浮动值3.14
). Combine
执行没有插入空格也使我们不会意外地解析'The answer is 3. 10 is too much.'
并认为"3. 10"
代表一个实数.
4)这不应该导致您的错误,但您的输入字符串有很多额外的空格.如果你得到你的语法的工作,你应该能够解析"int x;"
一样好"int x ;"
.
希望其中一些提示让你前进.您是否阅读过任何在线pyparsing文章或教程?请查看在线示例.你需要得到的是如何把握好Word
,Literal
,Combine
等执行各项解析任务.
5)您错误地实现了术语和语句的递归定义.''
写下:而不是分配给它们:
term = Forward() statement = Forward()
然后,当您使用递归定义实际定义它们时,请使用<<
运算符(并确保将RHS包含在()
s中).
term << (... term definition ...) statement << (... statement definition ...)
你可以找到一个递归解析器的例子在这里,并在基本pyparsing用法介绍这里 -请参见标题为"分析列表"上的递归如何处理的一步一步的.