📄 readme.txt
字号:
: type_specifer ID
| type_specifer '*' ID
| type_specifer ID '[' ']'
| ELLIPSIS
;
用InsertSym加入符号表时若返回值为0,说明它已被定义过
提示出错:redefinition
4.2.3 类型错误
4.2.3.1 运算符操作数两边的类型
在用到运算符的地方
simple_expression => additive_expression relop additive_expression
additive_expression => additive_expression ADDOP term
term => term mulop unary_expression
unary_expression => unaryop unary_expression
判断操作数是否具有所需要的类型
若不是提示出错:illegal, left(或right) operand is not constant( or character)
4.2.3.2 等号两边的类型
在用到等号的地方
expression => var = expression
判断等号两边的类型
若不匹配提示出错:the left and the right type does not match
4.2.3.3 函数调用参数
在函数表funtable里已存放了函数的传入参数的个数和类型
在调用函数时
call => ID ( args )
将传入参数和funtable里的对应函数比较即可
这里用的是LookUpFun函数,它不仅在funtable寻找是否定义了ID这个函数,
并检查传入参数是否正确,它的返回值是函数返回值的类型(找不到返回0)
若找不到函数提示出错:undeclared function
传入参数太少提示出错:too few actual parameters
传入的第i个参数类型不对提示出错:
different types for formal and actual parameter i
4.3 函数调用参数检查的实现
●函数声明时的参数用argtemp缓冲区保存,并在InsertFun函数里,把它加入相应的
struct fun
全局变量typecount指示参数个数
●调用函数时传入参数用arg_in缓冲区保存,在LookUpFun函数里用它和函数的声明时
的参数比较
全局变量typecheck指示参数个数
5. debug mode
●为了方便调式: ) 在程序中加入很多printf语句
它将输出当前词法分析器运行到哪一步,归约的产生式是什么(只给出一些主要的,若
要更详细的可以去掉在lab3.y的语义动作中的注释符/**/)
●通过输入带-d参数的命令行进入debug模式,见 三. 编译及运行
6. main函数
做成命令行程序,带一个参数,表示输入的C--文件名
若带两个参数,则第二个要为 -d,表示进入debug模式,第三个参数为输入的C--文件名
----------------------------------------------------------------------------
三. 编译及运行
----------------------------------------------------------------------------
1. 源程序名(源程序位于src目录下)
lab3.l
lex.yy.c(这是由flex lab3.l生成的)
lab3.y
lab3.tab.h lab3.tab.c(由bison lab3.y -d生成的)
lab3.c lab3.h
2. 如何编译生成可执行程序
操作系统 Windows
使用的编译器 Visual C++ 6.0(SP6)
flex 版本2.5.4
bison 版本1.28
console mode
(1)运行cmd
(2)进入src目录
(3)src>set BISON_HAIRY=bison.hairy /*为bison设置环境变量*/
src>set BISON_SIMPLE=bison.simple
src>bison -d lab3.y
src>flex lab3.l
src>cl lab3.c lab3.tab.c lex.yy.c /Felab3
更方便的,我写了一个批处理文件compile.bat
src>compile
3. 如何运行程序
实例(该目录下含老师的测试文件s2.c s3.c和我放的s1.c):
src>lab3 //参数错误,输出提示信息
lab3.exe -- Copyright (C) 2007 cj4 No.04120004
Usage: lab3 [-d] filename
----------------------------------------------------
filename specifies the name of input file
-d debug mode
src>lab3 s1.c
line 8 error: unknown character
line 8 error: unknown character
line 14 error: j :redefinition
line 16 error: = :the left and the right type does not match
line 18 error: < :illegal, right operand is not constant or character
line 19 error: % :illegal, left operand is not constant
line 21 error: + :illegal, right operand is not constant
line 24 error: u :undeclared identifier
line 25 error: min : too few actual parameters
src>lab3 s2.c
Well done! /* s2.c没有错 */
src>lab3 s3.c
line 15 error: min : different types for formal and actual parameter 2
src>lab3 -d s3.c /* debug mode */
============= debug mode =============
make symboltable[0]
type_specifer => INT
type_specifer => INT
===========================================================
qt->level=0 level=1 insert_symbol_name=i potential_symboltable[0]
maketable symboltable[1]
actually insert symboltable[1]
===========================================================
param => type_specifer ID
type_specifer => INT
===========================================================
qt->level=1 level=1 insert_symbol_name=j potential_symboltable[1]
actually insert symboltable[1]
===========================================================
param => type_specifer ID
===========================================================
insert function: min in funtable[433]
argument: int int
===========================================================
fun_tag => type_specifer ID
===========================================================
lookup id: i in symboltable[1] hash h=105
tp->buckets[105]->sym.name=i
I find it
===========================================================
var => ID
factor => var
relop => LT
===========================================================
lookup id: j in symboltable[1] hash h=106
tp->buckets[106]->sym.name=j
I find it
===========================================================
var => ID
factor => var
simple_expression => additive_expression relop additive_expression
===========================================================
lookup id: i in symboltable[1] hash h=105
tp->buckets[105]->sym.name=i
I find it
===========================================================
var => ID
factor => var
return_stmt => RETURN expression ;
===========================================================
lookup id: j in symboltable[1] hash h=106
tp->buckets[106]->sym.name=j
I find it
===========================================================
var => ID
factor => var
return_stmt => RETURN expression ;
if_stmt => IF ( expression ) statement ELSE statement
declaration => fun_declaration
type_specifer => VOID
params => VOID
===========================================================
insert function: main in funtable[874]
argument: void
===========================================================
fun_tag => type_specifer ID
type_specifer => INT
===========================================================
qt->level=0 level=1 insert_symbol_name=i potential_symboltable[0]
maketable symboltable[1]
actually insert symboltable[1]
===========================================================
var_declaration => type_specifer ID ;
type_specifer => INT
===========================================================
qt->level=1 level=1 insert_symbol_name=j potential_symboltable[1]
actually insert symboltable[1]
===========================================================
var_declaration => type_specifer ID ;
===========================================================
lookup id: j in symboltable[1] hash h=106
tp->buckets[106]->sym.name=j
I find it
===========================================================
var => ID
factor => NUM
expression => var = expression
expression_stmt => expression ;
===========================================================
lookup id: i in symboltable[1] hash h=105
tp->buckets[105]->sym.name=i
I find it
===========================================================
var => ID
===========================================================
lookup id: j in symboltable[1] hash h=106
tp->buckets[106]->sym.name=j
I find it
===========================================================
var => ID
factor => var
factor => NUM
additive_expression => additive_expression ADDOP term
expression => var = expression
expression_stmt => expression ;
===========================================================
lookup id: i in symboltable[1] hash h=105
tp->buckets[105]->sym.name=i
I find it
===========================================================
var => ID
factor => NUM
factor => NUM
additive_expression => additive_expression ADDOP term
expression => var = expression
expression_stmt => expression ;
===========================================================
lookup id: j in symboltable[1] hash h=106
tp->buckets[106]->sym.name=j
I find it
===========================================================
var => ID
===========================================================
lookup id: i in symboltable[1] hash h=105
tp->buckets[105]->sym.name=i
I find it
===========================================================
var => ID
factor => var
factor => STRING_LITERAL
===========================================================
lookup function: min in funtable[433] and check arguments
===========================================================
line 15 error: min : different types for formal and actual parameter 2
call => ID ( args )
factor => call
expression => var = expression
expression_stmt => expression ;
declaration => fun_declaration
program => declaration_list
四. 花了多少时间?
合起来大概有3天:
一天看yacc/bison的介绍和文档等
一天写程序和调试
一天调试,写实验报告
五. 和谁讨论(还是独立完成)?
独立完成,遇到问题google,百度。。。
六. 问题,解决和体会
1. 使用yacc一般出错在两个地方
●一是
invalid input:
ill-formed rule: initial symbol not followed by colon
一个非终结符对应多个产生式时要用 | 号
token和非终结符要由字母,点,下划线组成,数字(不在第一个位置)
Names may be of arbitrary length, and may be made up of letters, dot ``.'',
underscore ``_'', and non-initial digits. Upper and lower case letters are
distinct. The names used in the body of a grammar rule may represent tokens or
nonterminal symbols.
●还有就是
leftside
: aaa bbb
{在这里面$$ $1 $2用错了,类型不匹配等}
;
2. 至少还有两个问题没解决
●对于char a[100]的a没有很好的处理,这里只是将它简单的处理成char类型
●对与id_hash_table symboltable funtable中由malloc生成的结构没有释放
●此外较新的bison版本提供了很好用的功能,可以做更好的错误提示,有时间的话将
改进
3. 看了一些yacc的例子,不如直接自己写了解的快
4. 老师的 C--编译器的示例代码 很有帮助
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -