从 PL/0 编译程序源码中抽出词法分析部分,只改写main函数,构建 PL/0 独立词法分析程序。功能:输入为 PL/0 源程序, 输出为单词符号的序列;对于标识符和无符号整数,显示单词种别和单词自身的值两项内容;对于其他单词符号,仅显示其单词种别。
时间: 2024-05-10 11:18:53 浏览: 16
以下是一个简单的 PL/0 独立词法分析程序,它从标准输入中读取 PL/0 源程序,将其转换为单词符号的序列,并在标准输出中显示单词种别和单词的值(对于标识符和无符号整数),或者仅显示单词种别(对于其他单词符号)。
```
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define MAX_IDENT_LEN 32
#define MAX_NUM_LEN 10
enum {
SYM_NULL,
SYM_IDENTIFIER,
SYM_NUMBER,
SYM_PLUS,
SYM_MINUS,
SYM_TIMES,
SYM_SLASH,
SYM_ODD,
SYM_EQU,
SYM_NEQ,
SYM_LES,
SYM_LEQ,
SYM_GTR,
SYM_GEQ,
SYM_LPAREN,
SYM_RPAREN,
SYM_COMMA,
SYM_SEMICOLON,
SYM_PERIOD,
SYM_BECOMES,
SYM_BEGIN,
SYM_END,
SYM_IF,
SYM_THEN,
SYM_WHILE,
SYM_DO,
SYM_CALL,
SYM_CONST,
SYM_VAR,
SYM_PROCEDURE
};
static char ch = ' ';
static int sym;
static char ident[MAX_IDENT_LEN + 1];
static int num;
static void next_ch(void)
{
ch = getchar();
}
static void error(const char *msg)
{
fprintf(stderr, "%s\n", msg);
exit(1);
}
static void get_sym(void)
{
while (isspace(ch))
next_ch();
if (isalpha(ch)) {
int i = 0;
do {
if (i < MAX_IDENT_LEN)
ident[i++] = ch;
next_ch();
} while (isalnum(ch));
ident[i] = '\0';
if (strcmp(ident, "odd") == 0)
sym = SYM_ODD;
else if (strcmp(ident, "begin") == 0)
sym = SYM_BEGIN;
else if (strcmp(ident, "end") == 0)
sym = SYM_END;
else if (strcmp(ident, "if") == 0)
sym = SYM_IF;
else if (strcmp(ident, "then") == 0)
sym = SYM_THEN;
else if (strcmp(ident, "while") == 0)
sym = SYM_WHILE;
else if (strcmp(ident, "do") == 0)
sym = SYM_DO;
else if (strcmp(ident, "call") == 0)
sym = SYM_CALL;
else if (strcmp(ident, "const") == 0)
sym = SYM_CONST;
else if (strcmp(ident, "var") == 0)
sym = SYM_VAR;
else if (strcmp(ident, "procedure") == 0)
sym = SYM_PROCEDURE;
else
sym = SYM_IDENTIFIER;
} else if (isdigit(ch)) {
num = 0;
do {
num = num * 10 + (ch - '0');
next_ch();
} while (isdigit(ch));
sym = SYM_NUMBER;
} else {
switch (ch) {
case '+':
sym = SYM_PLUS;
next_ch();
break;
case '-':
sym = SYM_MINUS;
next_ch();
break;
case '*':
sym = SYM_TIMES;
next_ch();
break;
case '/':
sym = SYM_SLASH;
next_ch();
break;
case '=':
sym = SYM_EQU;
next_ch();
break;
case '<':
next_ch();
if (ch == '=') {
sym = SYM_LEQ;
next_ch();
} else if (ch == '>') {
sym = SYM_NEQ;
next_ch();
} else {
sym = SYM_LES;
}
break;
case '>':
next_ch();
if (ch == '=') {
sym = SYM_GEQ;
next_ch();
} else {
sym = SYM_GTR;
}
break;
case '(':
sym = SYM_LPAREN;
next_ch();
break;
case ')':
sym = SYM_RPAREN;
next_ch();
break;
case ',':
sym = SYM_COMMA;
next_ch();
break;
case ';':
sym = SYM_SEMICOLON;
next_ch();
break;
case '.':
sym = SYM_PERIOD;
next_ch();
break;
case ':':
next_ch();
if (ch == '=') {
sym = SYM_BECOMES;
next_ch();
} else {
error("invalid symbol");
}
break;
default:
error("invalid symbol");
break;
}
}
}
int main(void)
{
while (ch != EOF) {
get_sym();
switch (sym) {
case SYM_IDENTIFIER:
printf("%d %s\n", SYM_IDENTIFIER, ident);
break;
case SYM_NUMBER:
printf("%d %d\n", SYM_NUMBER, num);
break;
default:
printf("%d\n", sym);
break;
}
}
return 0;
}
```
可以将上述代码保存为 `pl0lex.c`,并使用 C 编译器进行编译,例如:
```
$ gcc -o pl0lex pl0lex.c
```
然后,可以使用以下命令运行该程序:
```
$ ./pl0lex < input.pl0
```
其中 `input.pl0` 是 PL/0 源程序的文件名。程序将输出单词符号的序列,每个单词符号占一行,其中标识符和无符号整数的值也将被显示出来。