C语言设计实现扫描器的自动机的示例详解

 更新时间:2022年12月28日 10:51:25   作者:heart_6662  
这篇文章主要为大家详细介绍了如何利用C语言设计实现扫描器的自动机,可识别的单词包括:关键字、界符、标识符和常整型数,感兴趣的小伙伴可以了解一下

题目内容

内容:

1.设计扫描器的自动机;

2.设计翻译、生成Token的算法;

3.编写代码并上机调试运行通过。

要求:

扫描器可识别的单词包括:关键字、界符、标识符和常整型数。

其中关键字表、界符表、标识符表、常整数表如下:

关键字表K(1int 2void 3break 4float 5while 6do 7struct 8coust 9case 10for 11return 12if 13default 14else)

界符表 P(1 - 2 / 3 ( 4 ) 5 -- 6<= 7< 8+ 9* 10> 11= 12, 13; 14++ 15 { 16 } 17 ' 18 " )

标识符表I (1 2 3 4 5 6 7 8 9 10 11 12 13 14)

常整数表C(1 2 3 4 5 6 7 8 9 10 11 12 13 14)

【输入形式】

源程序文件。

【输出形式】

(1)相应单词的Token序列;

(2)标识符表,常数表。

【测试用例1】

输入:x10=x+y1*120+10;

输出:

Token序列:(I 1)(P 11)等等

标识符表:x10 x y1

常数表:120 10

思路

题目中的输出形式是:(1)相应单词的Token序列;(2)标识符表,常数表。因此,我们可以在上述代码中调整输出的格式。

对于 Token 序列的输出,我们可以将其格式化为如下形式:

Token序列:(<单词种类>, <单词内容>)

例如:(KEYWORD, int)(IDENTIFIER, x)(DELIMITER, =)(INTEGER, 10)

对于标识符表和常整数表的输出,我们可以将其格式化为如下形式:

标识符表: x y

常整数表: 10 20

为了实现这种输出格式,我们可以在输出 Token 序列之后,再输出标识符表和常整数表。

代码

#include <stdio.h>
#include <string.h>
#include <ctype.h>
 
// 定义单词种类
typedef enum {
  KEYWORD,   // 关键字
  DELIMITER, // 界符
  IDENTIFIER,// 标识符
  INTEGER    // 常整型数
} TokenType;
 
// 关键字表
char *keywords[] = {
  "int", "void", "break", "float", "while", "do",
  "struct", "const", "case", "for", "return", "if",
  "default", "else"
};
 
// 界符表
char delimiters[] = {
  '-', '/', '(', ')', '--', '<=', '<', '+', '*', '>',
  '=', ',', ';', '++', '{', '}', '\'', '"'
};
 
// 标识符表
char *identifiers[100];
int identifier_count = 0;
 
// 常整数表
int integers[100];
int integer_count = 0;
 
// Token 序列
struct Token {
  TokenType type; // 单词种类
  char *lexeme;   // 单词内容
  int value;      // 单词值
} tokens[100];
int token_count = 0;
 
// 读入的源程序
char source[100];
int source_pos = 0;
 
// 读入下一个字符
char get_char() {
  return source[source_pos++];
}
 
// 跳过空白符
void skip_space() {
  while (isspace(source[source_pos])) source_pos++;
}
 
// 读入单词
void get_token() {
  skip_space();
 
  char ch = get_char();
 
  // 如果是字母,则读入单词
  if (isalpha(ch)) {
    int lexeme_pos = 0;
    char lexeme[100];
    while (isalpha(ch) || isdigit(ch)) {
      lexeme[lexeme_pos++] = ch;
      ch = get_char();
    }
    lexeme[lexeme_pos] = '\0';
    source_pos--; // 将最后读入的非字母或数字字符放回去
 
    // 判断是否为关键字
for (int i = 0; i < 14; i++) {
if (strcmp(keywords[i], lexeme) == 0) {
tokens[token_count].type = KEYWORD;
tokens[token_count].lexeme = lexeme;
token_count++;
return;
}
}
 
 
// 如果不是关键字,则加入标识符表
identifiers[identifier_count] = lexeme;
tokens[token_count].type = IDENTIFIER;
tokens[token_count].lexeme = lexeme;
tokens[token_count].value = identifier_count;
identifier_count++;
token_count++;
return;
}
 
// 如果是数字,则读入常整数
if (isdigit(ch)) {
int value = 0;
while (isdigit(ch)) {
value = value * 10 + (ch - '0');
ch = get_char();
}
source_pos--; // 将最后读入的非数字字符放回去
 
 
// 加入常整数表
integers[integer_count] = value;
tokens[token_count].type = INTEGER;
tokens[token_count].value = value;
integer_count++;
token_count++;
return;
}
 
// 如果是界符,则读入界符
for (int i = 0; i < 18; i++) {
if (delimiters[i] == ch) { 
// 加入 Token 序列
tokens[token_count].type = DELIMITER;
tokens[token_count].lexeme = ch;
token_count++;
return;
}
}
}
 
int main() {
// 读入源程序
scanf("%s", source);
 
// 读入 Token 序列
while (source_pos < strlen(source)) {
get_token();
}
 
// 输出 Token 序列
for (int i = 0; i < token_count; i++) {
if (tokens[i].type == KEYWORD) {
printf("(KEYWORD, %s)\n", tokens[i].lexeme);
} else if (tokens[i].type == IDENTIFIER) {
printf("(IDENTIFIER, %s)\n", tokens[i].lexeme);
} else if (tokens[i].type == INTEGER) {
printf("(INTEGER, %d)\n", tokens[i].value);
} else if (tokens[i].type == DELIMITER) {
printf("(DELIMITER, %c)\n", tokens[i].lexeme);
}
}
 
// 输出标识符表
printf("\nIdentifier Table:\n");
for (int i = 0; i < identifier_count; i++) {
printf("%s\n", identifiers[i]);
}
 
// 输出常整数表
printf("\nInteger Table:\n");
for (int i = 0; i < integer_count; i++) {
printf("%d\n", integers[i]);
}
 
return 0;
}

到此这篇关于C语言设计实现扫描器的自动机的示例详解的文章就介绍到这了,更多相关C语言扫描器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++之异常处理详解

    C++之异常处理详解

    C++中处理异常的过程是这样的:在执行程序发生异常,可以不在本函数中处理,而是抛出一个错误信息,把它传递给上一级的函数来解决,上一级解决不了,再传给其上一级,由其上一级处理
    2013-08-08
  • C++数据模型应用在QML委托代理机制中

    C++数据模型应用在QML委托代理机制中

    这篇文章主要介绍了在QML委托代理机制中使用C++数据模型,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • C语言实现餐饮结账管理系统

    C语言实现餐饮结账管理系统

    这篇文章主要为大家详细介绍了C语言实现餐饮结账管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-11-11
  • C语言计算代码执行所耗CPU时钟周期

    C语言计算代码执行所耗CPU时钟周期

    本文给大家介绍的是使用C语言来计算代码执行所耗CPU时钟周期的代码,非常的简单实用,不过要依托于sync,有需要的小伙伴自己参考下吧。
    2015-03-03
  • c语言尾队列tailq使用示例分享

    c语言尾队列tailq使用示例分享

    这篇文章主要介绍了c语言尾队列tailq使用示例,大家参考使用吧
    2014-01-01
  • C语言全面细致精讲操作符的使用

    C语言全面细致精讲操作符的使用

    C 语言提供了丰富的操作符,有:算术操作符,移位操作符,位操作符,赋值操作符,单目操作符,关系操作符,逻辑操作符,条件操作符等。接下了让我们详细了解掌握它
    2022-05-05
  • 基于OpenCV实现图像分割

    基于OpenCV实现图像分割

    这篇文章主要为大家详细介绍了基于OpenCV实现图像分割,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • C语言指针原来也可以这样了解

    C语言指针原来也可以这样了解

    这篇文章非常详细的讲解了C语言中指针的概念,包含多种方法,多种定义,全面的说明了C语言的特性,希望能给你带来帮助
    2021-08-08
  • C++中Cbitmap,HBitmap,Bitmap区别及联系

    C++中Cbitmap,HBitmap,Bitmap区别及联系

    这篇文章主要介绍了C++中Cbitmap,HBitmap,Bitmap区别及联系的相关资料,需要的朋友可以参考下
    2015-06-06
  • C语言实现合并字符串

    C语言实现合并字符串

    今天小编就为大家分享一篇C语言实现合并字符串,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12

最新评论