词法分析和语法分析1

  • 格式:pdf
  • 大小:160.20 KB
  • 文档页数:19

词法分析和语法分析1

为了造福⼤众,你懂的

⼀.实验⽬的1.创建⼀个词法分析程序,该程序⽀持分析常规语法。必须使⽤DFA(确定性有限⾃动机)或NFA(不确定性有限⾃动机)来实现此程序。程序有两个输⼊:⼀个本⽂档,包括⼀组3°语法(正规⽂法)的产⽣式;⼀个源代码⽂本⽂档,包括⼀组需要识别的字符串。程序的输出是⼀个令牌表,该表由五种token组成:关键词,标识符,常量,限定符和运算符。

2.创建⼀个采⽤LL(1)⽅法或LR(1)⽅法的语法分析程序。程序的输⼊是⼀个⽂本⽂件包括⼀组的2°⽂法⽣成(上下⽂⽆关⽂法)产⽣式集合和任务1⽣成的token令牌表。该程序的输出是yes或no,即,这源代码的字符串是否符合这2°语法。

⼆.说明src⾥⾯是源代码,编译需要配置qt环境

Executable⾥⾯是编译好的exe⽂件

运⾏后:Function Choose底下选择词法分析还是语法分析,词法分析成功后才能分析语法。

Load选项加载测试的代码⽂件,然后选择uage⽂件夹底下词法分析的5个词法规则⽂件,共有常量(⽀持浮点和科学计数法),标识符、关键字、界符和操作符5种词法。

加载完成后没有提⽰,直接点run运⾏,可以看到输出token表,词法分析完成,同⽬录下会⽣成⼀个中间⽂件⽤于保存token。

然后Function Choose切到语法分析,测试代码和token表⾃动填好了,选择load语法规则⽂件,只有⼀个,加载成功后可以看到左下⾓的LR分析表(Action和Goto表合并了)。

然后再run,右下⾓显⽰分析过程,右上⾓显⽰分析结果(yes/no)。

另外,程序不⽀持打开中⽂路径底下的⽂件,⽀持的词法和语法有限。

三.词法

词法规则⽂件内容共分为五种,作为词法分析的依据。1. 常量

[const]->'NUMBER'"C"

"C"->'NUMBER'"C"

"C"->'.'"G"

"C"->'e'"E"

"C"->'E'"E"

"C"->''

"C"->'i'

[const]->'.'"D"

"D"->'NUMBER'"G"

"G"->'NUMBER'"G"

"G"->'e'"E""G"->'E'"E"

"G"->''

"G"->'i'

"E"->'+'"H"

"E"->'-'"H"

"E"->'NUMBER'"I"

"H"->'NUMBER'"I"

"I"->'NUMBER'"I"

"I"->''

"I"->'i'

2. 标识符

[identifier]->'LETTER'

[identifier]->'LETTER'"L"

"L"->'LETTER'"L"

"L"->'NUMBER'"L"

"L"->'LETTER'

"L"->'NUMBER'

3. 界符

[limiter]->';'

[limiter]->','

[limiter]->'('

[limiter]->')'

[limiter]->'{'

[limiter]->'}'

[limiter]->','

4. 关键字

[keyword]->'void'

[keyword]->'int'

[keyword]->'double'

[keyword]->'char'

[keyword]->'if'

[keyword]->'else'

[keyword]->'for'

[keyword]->'break'

[keyword]->'continue'

[keyword]->'return'

5. 操作符

[operator]->'+'

[operator]->'-'[operator]->'*'

[operator]->'/'

[operator]->'%'

[operator]->'='

[operator]->'<'

[operator]->'>'

[operator]->'+'"op"

[operator]->'-'"op"

[operator]->'*'"op"

[operator]->'/'"op"

[operator]->'%'"op"

[operator]->'='"op"

[operator]->'<'"op"

[operator]->'>'"op"

"op"->'='

[operator]->'+'"A"

"A"->'+'

[operator]->'-'"S"

"S"->'-'

四.语法[START]->"X"

"X"->'@'

"X"->"FUN""X"

"STYLE"->'void'

"STYLE"->'int'

"FUN"->"STYLE"'identifier''('')''{'"STATEMENTS"'}'

"FUN"->"STYLE"'identifier''('"PRALIST"')''{'"STATEMENTS"'}'

"PRALIST"->"PRA""EXRTA"

"EXRTA"->','"PRA"

"EXRTA"->'@'

"PRA"->"STYLE"'identifier'

"CALLPRALIST"->"VALUE""EXRTAB"

"EXRTAB"->'@'

"EXRTAB"->','"VALUE"

"BLOCK"->'{'"STATEMENTS"'}'

"STATEMENTS"->'@'

"STATEMENTS"->"STATEMENT""STATEMENTS""STATEMENT"->"EXPRESSION"';'

"STATEMENT"->"DEFINE"';'

"STATEMENT"->'identifier''('')'';'

"STATEMENT"->'identifier''('"CALLPRALIST"')'';'

"STATEMENT"->"BRANCH"

"STATEMENT"->'return'';'

"STATEMENT"->'return'"EXPRESSION"';'

"BRANCH"->'if''('"EXPRESSION"')'"BLOCK"

"EXPRESSION"->"VALUE"'operator'"VALUE"

"EXPRESSION"->"VALUE"'operator'"VALUE"

"VALUE"->'('"EXPRESSION"')'

"VALUE"->'identifier'

"VALUE"->'const'

"DEFINE"->"STYLE"'identifier'

"DEFINE"->"STYLE"'identifier''operator'"EXPRESSION"

"BLOCK"->"STATEMENT"

"BLOCK"->'{'"STATEMENTS"'}'

五.模块设计以及程序主要代码1.分析器主要流程:

2.模块设计:

主函数模块:程序开始,设计简单,主要调⽤窗体模块;

窗体模块:主要分为两部分,⼀是窗⼝的设计部分,定义页⾯分布以及功能按钮的实现,创造界⾯,⼆是调⽤功能函数;

功能函数模块:功能函数分别是词法分析和语法分析,语法分析建⽴在词法分析基础上,需要先进⾏词法分析。主要功能包括⽂件输⼊与输出,产⽣式的读⼊,对单词种类的判断,对输⼊字符串的判断等等。

模块关系图如下

3.Main函数:

#include "mainwindow.h"

#include

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

MainWindow w;

w.show(); return a.exec();

}

4.Mainwindow:

主要构造了界⾯以及⽂法⽂件,测试代码的读⼊与中间⽂件,分析结果的输出,构造并显⽰分析表。1. 读⼊测试代码

void MainWindow::on_actionLoad_TestCode_triggered()

{

if(funcChoose==0){

QMessageBox::warning(this, tr("Analyzer"),tr("请先进⾏功能选择"));

return;

}

QString fileName = QFileDialog::getOpenFileName(this,"select testcode");

if (!fileName.isEmpty()) {

QFile file(fileName);

if (!file.open(QFile::ReadOnly | QFile::Text)) {

QMessageBox::warning(this, tr("分析器"),

tr("⽆法读取⽂件 %1:\n%2.")

.arg(fileName).arg(file.errorString()));

return; // 只读⽅式打开⽂件,出错则提⽰,并返回false

}

QTextStream in(&file); // 新建⽂本流对象

QApplication::setOverrideCursor(Qt::WaitCursor);

// 读取⽂件的全部⽂本内容,并添加到编辑器中

ui->textEdit_1->setPlainText(in.readAll());

QApplication::restoreOverrideCursor();

}

}

2. 读⼊⽂法

void MainWindow::on_actionLoad_Grammer_triggered()

{

if(funcChoose==1){ // 词法分析则有多个

if(lexical!=NULL)delete lexical;

lexical=new Lexical();

ui->textEdit_2->clear();

QStringList fileNames = QFileDialog::getOpenFileNames(this,"select lexical");

for(int i=0;i

QString qs=fileNames.at(i);

lexical->buildDFA(qs.toStdString());

}