语法分析和语义分析

问题描述 投票:3回答:2

我想知道语法分析和语义分析是如何工作的。

我已经完成了我的翻译的词法分析器和语法结构。

现在我要为这个语法实现一个递归下降(自上而下)解析器

例如,我有以下语法:

<declaration>  ::=   <data_type> <identifier> ASSIGN <value>

所以我这样编码(在java中):

public void declaration(){
    data_type();
    identifier();
    if(token.equals("ASSIGN")){
        lexer();   //calls next token
        value();
    } else {
        error();
    }
}

假设我有三种数据类型:Int,String和Boolean。由于每种数据类型的值都不同(例如,仅在布尔值中为true或false)如何确定它是否正确匹配数据类型?我的代码的哪一部分会决定这一点?

我想知道我将把代码放在哪里:

1.) call the semantic analysis part of my program. 
2.) store my variables into the symbol table.

语法分析和语义分析是否同时发生?或者我是否需要先完成语法分析,然后进行语义分析?

我真的很困惑。请帮忙。

谢谢。

parsing syntax compiler-construction semantics recursive-descent
2个回答
3
投票

您可以同时进行语法分析(解析)和语义分析(例如,检查<data_type><value>之间的协议)。例如,当declaration()调用data_type()时,后者可以返回一些东西(称之为DT),指示声明的类型是Int,String还是Boolean。类似地,value()可以返回指示解析类型的东西(VT)。然后,declaration()将简单地比较DT和VT,如果它们不匹配则引发错误。 (或者,value()可以采用指示声明类型的参数,并且可以进行检查。)

但是,您可能会发现将两个阶段完全分开会更容易。为此,您通常会在解析阶段构建一个解析树(或抽象语法树)。所以你的顶层会调用(例如)program()来解析一个整个程序,它会返回一个表示程序语法的树,你可以将那个树传递给一个semantic_analysis()例程,该例程将遍历树,提取相关信息并实施语义约束。


2
投票

简短的回答是:它取决于您的编程语言的定义。而且,由于您只指定了一个派生规则和三个本机类型,因此无法知道。例如,如果您的编程语言允许前面的声明,如下面的c ++代码,那么处理函数声明(foo)的派生规则是在不知道变量序列的类型的情况下完成的。

class Tree {
public:
    int foo(void)
    {
        return serial;
    }
    int serial;
};

实际上,现代编译器将语法分析阶段与语义分析阶段分开。首先执行语法分析阶段,确保输入程序与语言的上下文无关语法一致。此外,还生成一个抽象语法树(AST)。请注意AST和解析树之间的区别,如in this SO post所述。然后,语义分析阶段遍历AST并检查其他事物之间的类型不匹配。

话虽如此,玩具编程语言有时可以将语义和语法分析结合在一起。当使用递归下降解析器时,您应该让相关的递归调用返回一个类型。

© www.soinside.com 2019 - 2024. All rights reserved.