Compiler Construction using Flex and Bison(译4--上下文)

本文介绍如何使用Lex和Bison处理上下文敏感信息,通过构建符号表来确保变量在引用前已声明。文章详细说明了符号表的设计与实现,并展示了如何修改语法分析器以进行上下文检测。

Lex和Bison文件可以扩展以处理上下文敏感信息.例如,为简单起见,假设我们想要求这样,我们要求变量在引用前必须先声明.因此,语法分析器应该可以把变量引用与变量声明对比.(看是否一致)
为了完成这些,一种方法是当语法分析到一个变量构造一个变量列表,而当分析到变量引用时从变量列表中检测变量引用.这样的列表称为符号表.符号表可以用链表,树和哈希表实现.
我们修改Lex文件,把标识符的字符串信息赋给全局变量yylval,因为这些信息将在属性文法用到.

符号表模块
为了保存属性文法所需要的信息,我们构造一个符号表.一个符号表包含关于各种程序设计语言结构的属性的环境信息.特别地,应包含类型和作用域信息.

符号表将被作为一个模块包含在yacc/bison的文件中.

Simple的符号表包含一条标识符的链表,初始为空.这里是一个链表结点的声明,初始链表为空,和两个操作:putsym把一个标识符放入表中,而getsym返回一个与标识符一致的符号表项的指针.
struct symrec
{
char * name; /*name of symbol*/
struct symrec *next; /*link field*/
};
typedef struct symrec symrec;
symrec *sym_table = (symrec *)0;
symrec *putsym();
symrec *getsym();

symrec*
putsym ( char *sym_name) /*头插入*/
{
symrec *ptr;
ptr = (symrec *)malloc(sizeof(symrec));
ptr -> name =(char *)malloc(strlen(stm_name)+1);
strcpy(ptr->name,sym_name);
ptr->next = (struct symrec *)sym_table;
sym_table = ptr;
return ptr;
}

symrec *
getsym ( char *sym_name)
{
symrec *ptr;
for (ptr=sym_table;ptr!=(symrec *)0;
ptr = (symrec *)ptr->next)
if(strcmp(ptr->name,sym_name)==0)
return ptr;
return 0;
}

语法分析器修改

Yacc/Bison文件被修改成包含符号表和其相应的操作函数,以执行把标识符装入到符号表中和上下文检测.

%{
#include <stdlib.h> /*For malloc in symbol table*/
#include <string.h> /*For strcmp in symbol table*/
#include <stdio.h> /*For error message */
#include "ST.h"  /* The Symbol Table Module */
#define YYDEBUG 1 /*For debugging */
install ( char *sym_name)
{
symrec *s;
s = getsym (sym_name);
if (s==0)
s = putsym (sym_name);
else{errors++;
printf ( "%s is already defined/n",sym_name);
}
}
context_check( char *sym_name)
{if ( getsym( sym_name ) = =0)
printf( "%s is an undeclared identifier/n",sym_name);
}
%}
Parser declarations
%%
Grammar rules and actions
%%
C subroutines

因为扫瞄器(Lex文件)将返回标识符,所以要求用静态语义记录保存其值,而IDENT与这静态语义记录关联.

C declarations
%union{ /*SEMANTIC RECORD*/
char *id; /*For returning identifier */
}
%token INT SKIP IF THEN ELSE FI WHILE DO END
%token <id> IDENT /* Simple identifier */
%left '-' '+'
%left '*' '/'
%right '^'
%%
Grammar rules and actions
%%
C subroutines

非终结符...

 上下文无关文法修改包含intall和上下文检测函数调用.$n是Yacc的内部变量,它指引用与产生式右部第n个符号一致的语义记录.$$指与产生式左部非终结符一致的语义录.

C and parser declarations
%%
...
declarations : /* empty */
| INTEGER id_seq IDENTIFIER '.' { install( $3); }
;
id_seq : /* empty */
| id_seq IDENTIFIER ',' {install($2);}
;
command : SKIP
| READ IDENTIFIER {context_check( $2 );}
| IDENT ASSGNOP exp {context_check( $2 );}
...
exp : INT
| IDENT { context_check( $2 ); }
...
%%
C subroutines

语法分析树的实现隐式包含关于一个变量在表达式引用之前是否已被赋值的注释信息.语法树的注释信息被收集到符号表中.

扫瞄器修改

扫瞄器必须修改成返回与标识符相关联的字符常量.(记号的语义值).语义值通过yylval返回.yylval的类型是一个在语法分析文件中用%union定义的联合体.语义值必须存放在合适的联合体成员中.因为联合体声明如下:
%union{ char *id;
}
所以语义值是由全局变量yytext(包含输入文本)复制到yylval.id中.因为函数strdup被用到(string.h中定义),所以这个头文件必须包含.扫瞄器文件最终改为:

%{
#include <string.h>  /*for strdup */
#include "Simple.tab.h" /* for token definitions and yylval */
%}
DIGIT   [0-9]
ID    [a-z][a-z0-9]
%%
":="    {return (ASSGNOP); }
{DIGIT}+  {return (NUMBER); }
do    {return (DO )  ; }
else    {return (ELSE)   ; }
end    { return (END) ;}
fi    { return (FI)  ; }
if    { return (IF)  ; }
in    { return (IN)  ; }
integer   { return (INGETER);}let    { return (LET)  ; }
read    { return (READ)  ; }
skip    { return (SKIP)  ; }
then    { return (THEN) ; }
while   { return (WHILE) ; }
write   { return (WRITE) ; }
{ID}   { yylval.id = (char *) strdup(yytext);
return (IDENTIFIER) ;}
[ /t/n]+   /* eat up whiteespace */
.    { return (yytext[0] ) ; }
%%

中间表示

许多编译器在语法分析阶段把源代码转为中间表示.在我们的例子中,语法表示是一个语法树.语法树保留在栈中但它可以显示构造.另一些中间表示通用的选择包括抽象语法树,三元地址,当然也有四元地址,和后缀码.在我们的例子中,我们选择跳过中间表示而直接生成代码.这节说到有关代码生成的原则也适用于中间代码生成.

内容概要:本文介绍了基于贝叶斯优化的CNN-LSTM混合神经网络在时间序列预测中的应用,并提供了完整的Matlab代码实现。该模型结合了卷积神经网络(CNN)在特征提取方面的优势与长短期记忆网络(LSTM)在处理时序依赖问题上的强大能力,形成一种高效的混合预测架构。通过贝叶斯优化算法自动调参,提升了模型的预测精度与泛化能力,适用于风电、光伏、负荷、交通流等多种复杂非线性系统的预测任务。文中还展示了模型训练流程、参数优化机制及实际预测效果分析,突出其在科研与工程应用中的实用性。; 适合人群:具备一定机器学习基基于贝叶斯优化CNN-LSTM混合神经网络预测(Matlab代码实现)础和Matlab编程经验的高校研究生、科研人员及从事预测建模的工程技术人员,尤其适合关注深度学习与智能优化算法结合应用的研究者。; 使用场景及目标:①解决各类时间序列预测问题,如能源出力预测、电力负荷预测、环境数据预测等;②学习如何将CNN-LSTM模型与贝叶斯优化相结合,提升模型性能;③掌握Matlab环境下深度学习模型搭建与超参数自动优化的技术路线。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注贝叶斯优化模块与混合神经网络结构的设计逻辑,通过调整数据集和参数加深对模型工作机制的理解,同时可将其框架迁移至其他预测场景中验证效果。
器构建是一个复杂的过程,需要使用一些工具和技术来实现。而FlexBison是非常流行的用于构建编器的工具之一。 Flex是一个用于生成词法分析器的工具,它基于一组正则表达式规则,将输入的字符流分解成一个个的词法单元。通过定义一些规则,Flex可以将输入的源代码转化成一系列的词法单元,供后续的语法分析使用。 而Bison是一个用于生成语法分析器的工具,它通过定义一组语法规则和语义动作,将词法分析生成的词法单元序列转化成一颗语法树。Bison可以根据语法规则,自动生成语法分析器的代码,通过递归下降的方式对输入的源代码进行语法分析。 使用FlexBison构建编器的过程通常分为以下几个步骤: 1. 设计词法规则:根据编程语言的词法规范,使用正则表达式定义一组词法规则,用于将输入的字符流拆分成一个个的词法单元。 2. 设计语法规则:根据编程语言的语法规范,使用BNF(巴科斯-诺尔范式)或类似的语法表示方法,定义一组语法规则,用于将词法单元转化成语法树。 3. 实现词法分析器:使用Flex根据词法规则生成词法分析器的C代码,该代码将输入字符流转化成一系列词法单元。 4. 实现语法分析器:使用Bison根据语法规则生成语法分析器的C代码,该代码将词法单元序列转化成语法树。 5. 实现语义动作:在Bison生成的语法分析器中,添加适当的语义动作,用于对语法树进行语义分析和中间代码生成等操作。 6. 实现语言特性:根据编程语言的特性,添加相应的功能,例如处理变量声明、函数调用、控制结构等。 通过以上步骤,使用FlexBison可以快速构建一个简单的编器。当然,这只是编器构建过程的一部分,还需要考虑符号表管理、优化和代码生成等方面。但FlexBison提供了强大的词法和语法分析功能,为编器的开发提供了很好的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值