首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调试语法分析

调试语法分析
EN

Stack Overflow用户
提问于 2009-12-01 01:08:14
回答 1查看 5.1K关注 0票数 19

我正在为一种名为C-(而不是真正的C-语言)的虚拟编程语言构建一个解析器。我已经到了需要将语言的语法翻译成gotten可以接受的东西的阶段。不幸的是,当我解析我的输入字符串时(这是正确的,不应该导致语法分析出错),它没有正确地解析。我担心这是由于语法错误造成的,但是当我第一次开始语法分析时,我似乎看不出哪里出了问题。

我已经上传了我从这里翻译的语法,让人们读一读。

编辑:更新了保罗的建议。

这就是我目前掌握的语法(语法定义的两行对我来说是非常糟糕的):

代码语言:javascript
复制
# 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:更新以包含新错误。

下面是我正在解析的输入字符串:

代码语言:javascript
复制
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 ) ; 
} 

这是我在终端运行程序时收到的错误信息:

代码语言:javascript
复制
/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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2009-12-01 01:55:18

1)将Literal("if")更改为Keyword("if") (以此类推,向下改为Literal("void")),以防止匹配名为"ifactor"的变量的前导"if“。

2) numsalphasalphanums不是表达式,它们是字符串,在定义“单词”时,可以与单词类一起使用,比如“数字是由名词组成的单词”,或者“标识符是以alpha开头的单词,后面跟着零或更多的字母”。因此,与其:

代码语言:javascript
复制
number = nums
identifier = alphas + OneOrMore(alphanums)

你想要的

代码语言:javascript
复制
number = Word(nums)
identifier = Word(alphas, alphanums)

我认为你想要的不是Combine,而是Group。如果您希望匹配的令牌是连续的,没有中间空格,并将连接这些标记并将它们作为一个字符串返回,请使用Combine。在这种情况下,经常使用Combine

代码语言:javascript
复制
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 ;"

希望这些暗示能让你走。你读过任何在线的语法分析文章或教程吗?请看一下网上的例子。您需要很好地了解WordLiteralCombine等如何执行各自的解析任务。

5)错误地实现了术语和语句的递归定义。与其将''分配给它们,不如编写:

代码语言:javascript
复制
term = Forward()
statement = Forward()

然后,当您实际使用它们的递归定义定义它们时,使用<<运算符(并确保将RHS包含在()中)。

代码语言:javascript
复制
term << (... term definition ...)
statement << (... statement definition ...)

您可以找到一个递归解析器这里的示例,以及一个关于基本语法解析用法这里的演示文稿--请参阅题为“解析列表”的一节,以获得关于如何处理递归的详细信息。

票数 33
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1823427

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档