Skip to content

Whale-lyi/SysY-Compiler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lab1实验报告

实验思路

  1. 首先根据SysY词法规则中的词法规则编写SysYLexer.g4,然后为其生成词法分析器SysYLexer.java

  2. main方法接收文件路径,并将文件内容传给词法分析器

  3. 实现一个继承自BaseErrorListener的MyErrorListener并添加给SysYLexer

    • 之后遇到错误时会向MyErrorListener发送错误信息,调用synTaxError()方法,因此只需要重写synTaxError()方法,按要求的格式输出错误信息即可

    • 因为需要输出全部错误信息,所以在MyErrorListener类中定义一个boolean成员变量used,用来判断是否发生了词法错误

      • 通过在syntaxError()方法中将used设为true实现
  4. 通过sysYLexer.getAllTokens()函数触发sysYLexer的错误检查并获得所有token

  5. 如果myErrorListener.used为false,即没有发生词法错误,打印正常情况token内容,通过sysYLexer.getRuleNames()获取所有.g4文件中定义的规则

  6. 遍历所有的token,通过ruleNames[token.getType() - 1]获得Token类型

    • 此处 -1 是因为SysYLexer中的RuleNames下标是从 0 开始的,而token.getType()从 1 开始
  7. 在遇到INTEGR_CONST时需要将 8 进制与 16 进制转化为 10 进制,通过编写静态函数实现,之后按要求输出即可

精巧的设计

  • 通过在MyErrorListener中添加成员变量来判断输入文件是否有词法错误
  • 使用Integer.parseInt(s, radix)来快速进行 8 进制与 16 进制到 10 进制的转化
    • 先判断16进制的'0x'开头,然后再判断8进制的'0'开头,来区分这两种进制,并且8进制字符串长度要大于1

遇到的困难及解决办法

问题主要集中在main函数调用完sysYLexer.getAllTokens()后不知道有没有出现语法错误,SysYLexer没有一个函数或者成员变量可以获取到这一点。

如果不做处理的话,输入文本全部正确的的情况下没有问题,一旦有词法错误就会打印完错误信息后继续打印全部的token信息

一开始我选择在MyErrorListener.synTaxError()方法结尾抛出运行时异常,在main方法中捕捉,但这样只能解决只有一个词法错误的情况

随后我发现通过在MyErrorListener类中添加成员变量used即可完美解决这个问题,如果调用了synTaxError()方法,就将used设为true,因为MyErrorListener是在main中创建,因此可以直接获取到used的值

About

NJUSE Compilers Labs

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published