PL/0编译程序的语法分析
时间: 2023-12-07 07:06:07 浏览: 36
PL/0编译程序的语法分析可以采用自顶向下的递归下降分析方法实现。具体来说,可以先定义PL/0语言的文法规则,然后编写对应的语法分析函数来实现对输入程序的分析。
PL/0语言的文法规则如下:
```
<程序> ::= <分程序>.
<分程序> ::= [<常量说明部分>][<变量说明部分>][<过程说明部分>]<语句>
<常量说明部分> ::= const<常量定义>{,<常量定义>};
<常量定义> ::= <标识符>=<无符号整数>
<无符号整数> ::= <数字>{<数字>}
<变量说明部分> ::= var<标识符>{,<标识符>};
<过程说明部分> ::= <过程首部><分程序>{;<过程说明部分>}
<过程首部> ::= procedure<标识符>;
<语句> ::= <赋值语句>|<条件语句>|<当型循环语句>|<过程调用语句>|<读语句>|<写语句>|<复合语句>|<空语句>
<赋值语句> ::= <标识符>:=<表达式>
<条件语句> ::= if<条件表达式>then<语句>[else<语句>]
<当型循环语句> ::= while<条件表达式>do<语句>
<过程调用语句> ::= call<标识符>
<读语句> ::= read'('<标识符>{,<标识符>}')'
<写语句> ::= write'('<表达式>{,<表达式>}')'
<复合语句> ::= begin<语句>{;<语句>}end
<表达式> ::= [+|-]<项>{<加法运算符><项>}
<项> ::= <因子>{<乘法运算符><因子>}
<因子> ::= <标识符>|<无符号整数>|'('<表达式>')'
<条件> ::= <表达式><关系运算符><表达式>
<关系运算符> ::= =|<>|<|<=|>|>=
<标识符> ::= <字母>{<字母>|<数字>}
<数字> ::= 0|1|2|...|8|9
<字母> ::= a|b|...|y|z|A|B|...|Y|Z
```
根据以上文法规则,可以编写对应的语法分析函数,例如:
```c
void program() {
block();
if (sym != period) error();
}
void block() {
if (sym == constsym) {
const_declaration();
}
if (sym == varsym) {
var_declaration();
}
if (sym == procsym) {
proc_declaration();
}
statement();
}
void const_declaration() {
do {
getsym();
if (sym != ident) error();
getsym();
if (sym != eq) error();
getsym();
if (sym != number) error();
getsym();
} while (sym == comma);
if (sym != semicolon) error();
getsym();
}
void var_declaration() {
do {
getsym();
if (sym != ident) error();
getsym();
} while (sym == comma);
if (sym != semicolon) error();
getsym();
}
void proc_declaration() {
getsym();
if (sym != ident) error();
getsym();
if (sym != semicolon) error();
getsym();
block();
if (sym != semicolon) error();
getsym();
proc_declaration();
}
void statement() {
switch (sym) {
case ident:
assignment_statement();
break;
case ifsym:
if_statement();
break;
case whilesym:
while_statement();
break;
case callsym:
call_statement();
break;
case readsym:
read_statement();
break;
case writesym:
write_statement();
break;
case beginsym:
compound_statement();
break;
case semicolon:
getsym();
break;
default:
error();
break;
}
}
void assignment_statement() {
if (sym != ident) error();
getsym();
if (sym != becomes) error();
getsym();
expression();
}
void if_statement() {
getsym();
condition();
if (sym != thensym) error();
getsym();
statement();
if (sym == elsesym) {
getsym();
statement();
}
}
void while_statement() {
getsym();
condition();
if (sym != dosym) error();
getsym();
statement();
}
void call_statement() {
getsym();
if (sym != ident) error();
getsym();
}
void read_statement() {
getsym();
if (sym != lparen) error();
do {
getsym();
if (sym != ident) error();
getsym();
} while (sym == comma);
if (sym != rparen) error();
getsym();
}
void write_statement() {
getsym();
if (sym != lparen) error();
do {
getsym();
expression();
} while (sym == comma);
if (sym != rparen) error();
getsym();
}
void compound_statement() {
getsym();
statement();
while (sym == semicolon) {
getsym();
statement();
}
if (sym != endsym) error();
getsym();
}
void expression() {
if (sym == plus || sym == minus) {
getsym();
}
term();
while (sym == plus || sym == minus) {
getsym();
term();
}
}
void term() {
factor();
while (sym == times || sym == slash) {
getsym();
factor();
}
}
void factor() {
if (sym == ident) {
getsym();
} else if (sym == number) {
getsym();
} else if (sym == lparen) {
getsym();
expression();
if (sym != rparen) error();
getsym();
} else {
error();
}
}
void condition() {
expression();
if (sym != eql && sym != neq && sym != lss && sym != leq && sym != gtr && sym != geq) {
error();
} else {
getsym();
expression();
}
}
```
在具体实现过程中,还需要根据PL/0语言的词法规则,编写相应的词法分析函数和符号表管理函数,以及处理语法错误的函数。