当前位置:网站首页>C专家编程 第3章 分析C语言的声明 3.8 理解所有分析过程的代码段
C专家编程 第3章 分析C语言的声明 3.8 理解所有分析过程的代码段
2022-08-03 16:09:00 【weixin_客子光阴】
/*主要的数据结构是一个堆栈,我们从左向右读取,把各个标记依次压入堆栈,直到读到标识符为止然后我们继续向右读入一个标记,也就是标识符右边的那个标记。接着,观察标识符左边的那个标记(需要从堆栈中弹出)。
*/
struct token {
char type;
char string[MAXTOKENLEN];
};
/*保存第一个标识之前的所有标记*/
struct token stack[MAXTOKENS];
/*保存刚读入的那个标记*/
struct token this;
/*伪码如下:
实用程序-------------*/
classify_string(字符串分类)
/*查看当前的标记,
*通过this.type返回一个值,内容为"type"(类型),
*"qualifier"(限定符)或"identifier"标识符
*/
gettoken(取标记);
/*把下一个标记读入this.string
*如果是字母数字组合,调用classify_string
*否则,它必是一个单字符标记,this.type = 该标记;
*用一个nul结束this.string
*/
read_to_first_identifier(读至第一个标识符)
/*调用gettoken,并把标记压入到堆栈中,直到遇到第一个
*标识符
*Print"identifier is"(标识符是), this.string
*继续调用gettoken
*/
//解析程序
deal_with_function_args(处理函数参数)
//当读取越过右括号')'后,打印"函数返回"
deal_with_arrays(处理函数数组)
//当你读取"[size]"后,将其打印并继续向右读取。
deal_with_any_pointers(处理任何指针)
//当你从堆栈中读取"*"时,打印"指向...的指针"并将其弹出堆栈。
deal_with_declarator(处理声明器)
if this.type is '[' deal_with_arrays
if this.type is '(' deal_with_function_args
deal_with_any_pointers
while 堆栈里还有东西
if 它是一个左括号'('
将其弹出堆栈,并调用gettoken;应该获得右括号')'
deal_with_declarator
else 将其弹出堆栈并打印它
//主程序___________
main
read_to_first_identifier
deal_with_declaration
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAXTOKENS 100
#define MAXTOKENLEN 64
enum type_tag {
IDENTIFIER, QUALIFIER, TYPE
};
struct token {
char type;
char string[MAXTOKENLEN];
};
int top = -1;
struct token stack[MAXTOKENS];
struct token this_2;
#define pop stack[top--]
#define push(s) stack[++top] = s
enum type_tag classify_string(void)
/*判断标识符的类型*/
{
char *s = this_2.string;
if (!strcmp(s, "const")) {
strcpy(s, "read-only");
return QUALIFIER;
}
if (!strcmp(s, "volatile")) {
return QUALIFIER;
}
if (!strcmp(s, "void")) {
return TYPE;
}
if (!strcmp(s, "char")) {
return TYPE;
}
if (!strcmp(s, "signed")) {
return TYPE;
}
if (!strcmp(s, "unsigned")) {
return TYPE;
}
if (!strcmp(s, "short")) {
return TYPE;
}
if (!strcmp(s, "int")) {
return TYPE;
}
if (!strcmp(s, "long")) {
return TYPE;
}
if (!strcmp(s, "float")) {
return TYPE;
}
if (!strcmp(s, "double")) {
return TYPE;
}
if (!strcmp(s, "struct")) {
return TYPE;
}
if (!strcmp(s, "union")) {
return TYPE;
}
if (!strcmp(s, "enum")) {
return TYPE;
}
return IDENTIFIER;
}
void gettoken(void) /*读取下一个标记到this_2*/
{
char *p = this_2.string;
/*省略空白字符*/
while ((*p = getchar()) == ' ');
if (isalnum(*p)) {
/*读入的标识符以A-Z或0-9开头*/
while (isalnum(*++p = getchar()));
ungetc(*p, stdin);
*p = '\0';
this_2.type = classify_string();
return;
}
if (*p == '*') {
strcpy(this_2.string, "pointer to");
this_2.type = '*';
return;
}
this_2.string[1] = '\0';
this_2.type = *p;
return;
}
/*理解所有分析过程的代码段*/
void read_to_first_identifier() {
gettoken();
while (this_2.type != IDENTIFIER) {
push(this_2);
gettoken();
}
printf("%s is ", this_2.string);
gettoken();
}
void deal_with_arrays() {
while(this_2.type == '[') {
printf("array ");
gettoken(); /*数字或']'*/
if (isdigit(this_2.string[0])) {
printf("0..%d ", atoi(this_2.string) - 1);
gettoken(); /*读取']' */
}
gettoken(); /*读取']'之后的再一个标记*/
printf("of ");
}
}
void deal_with_function_args() {
while(this_2.type != ')') {
gettoken();
}
gettoken(); /*读取')'之后的再一个标记*/
printf("function returning ");
}
void deal_with_pointers() {
while (stack[top].type == '*') {
printf("%s ", pop.string);
}
}
deal_with_declarator() {
/*处理标识符之后可能存在的数组/函数*/
switch(this_2.type) {
case '[': deal_with_arrays(); break;
case '(': deal_with_function_args(); break;
}
deal_with_pointers();
/*处理在读入到标识符之前压入到堆栈中的符号*/
while (top >= 0) {
if (stack[top].type == '(') {
pop;
gettoken(); /*读取')'符号*/
deal_with_declarator();
} else {
printf("%s ", pop.string);
}
}
}
int main() {
read_to_first_identifier();
deal_with_declarator();
printf("\n");
return 0;
}
/* 输出:
*/
/*小启发*/
/*使字符串的比较看上去更自然
*strcmp()函数用于比较两个字符串:它所存在的一个问题是:当两个字符串相等时函数的返回值
*为零。当字符串比较是条件语句的一部分时,这个问题就是导致令人费解的代码:
*/
if (!strcmp(s, "volatile")) return QUALIFIER;
/*返回值零使条件语句的结果为假,所以我们不得不对其取反,得到需要的结果
*这里有一个更好的办法
*/
#define STRCMP(a, R, b) (strcmp(a, b) R 0)
if (STRCMP(s, ==, "volatile"))
Data Structures with Abstract Data Types
这本书覆盖了范围很广的数据结构,包括字符串、列表、堆栈、队列、树,堆、集合和图。
推荐大家阅读本书。
边栏推荐
猜你喜欢
DAYU200 OpenHarmony标准系统HDMI全屏显示
ModelWhale 云端运行 WRF 中尺度数值气象模式,随时随地即开即用的一体化工作流
ReentrantLock详解
MPLS的wpn实验
How to get the 2 d space prior to ViT?UMA & Hong Kong institute of technology & ali SP - ViT, study for visual Transformer 2 d space prior knowledge!.
【Unity入门计划】制作RubyAdventure01-玩家的创建&移动
leetcode SVM
MATLAB | 七夕节快到了,还不给朋友安排上这个咕呱小青蛙?
leetcode-693.交替位二进制数
Hannah荣获第六季完美童模全球总决赛全球人气总冠军
随机推荐
使用VS Code搭建ESP-IDF环境
如何分析周活跃率?
13、OOM模拟
When mobile applications go overseas, is your "network optimization" holding back?
新版本 MaxCompute 的SQL 中支持的 EXTRACT 函数有什么作用?
出海季,互联网出海锦囊之本地化
【Unity入门计划】基本概念(8)-瓦片地图 TileMap 02
EA 改口,称单人游戏是产品组合中“非常重要的一部分”
JD6606SP5_JD6606SSP_JD6606SASP_JD6621W7百盛新纪元授权代理商
一文看懂推荐系统:召回02:Swing 模型,和itemCF很相似,区别在于计算相似度的方法不一样
leetcode SVM
生态剧变,电子签名SaaS模式迎来新突破,网络效应加速到来
Kubernetes 笔记 / 入门 / 生产环境 / 用部署工具安装 Kubernetes / 用 kubeadm 启动集群 / 安装 kubeadm
"Avnet Embedded Weekly" Issue 276: 2022.07.25--2022.07.31
一文看懂推荐系统:召回03:基于用户的协同过滤(UserCF),要计算用户之间的相似度
ModelWhale 云端运行 WRF 中尺度数值气象模式,随时随地即开即用的一体化工作流
Why do I strongly recommend using smart async?
MarkDown常用代码片段和工具
leetcode-693.交替位二进制数
Some optional strategies and usage scenarios for PWA application Service Worker caching