当前位置:网站首页>编译原理——LL1分析程序实验(C#)
编译原理——LL1分析程序实验(C#)
2022-08-08 20:47:00 【郭麻花】
LL(1)分析程序实验目的与要求
编制一个能识别由词法分析给出的单词符号序列是否是给定文法的正确句子(程序),输出对输入符号串的分析过程。
实验内容
对于这个实验,核心内容是Process类。该类是一个带有三个参数的构造函数。将初始分析栈,输入的句子,预测分析表作为参数注入该类,调用BeginAnalyze()函数进行分析,同时Process本身属性在函数的循环中发生迭代变化,其自身的属性代表了每一分析步骤的结果,打印即可。
实验步骤
- 主函数内容:先打印出给定文法,预测分析表,然后对用户输入,构造Process类,进行分析。
- 获取推导所用的产生式或匹配:GetProductionRule()
需要调用GetRowIndex(StackTop)和 GetColIndex(Terminal)根据分析栈的栈顶元素与输入字符串首字符来获取预测分析表的内容。 - 反转字符串函数 Reverse(string s):该函数用于将产生式元素逆序入栈
private string Reverse(string s)
{
char[] cs= s.ToCharArray();
Array.Reverse(cs);
return new string(cs);
}
值得一提的是本程序并没有使用Stack数据结构来完成,而是使用了对字符串的操作来代替Stack。


using System;
using System.Collections.Generic;
using static System.Console;
namespace LL1
{
class Program
{
/// <summary>
/// 文法
/// </summary>
static List<string> Grammar = new List<string>()
{
"E->TB","B->+TB|ε",
"T->FY","Y->*FY|ε",
"F->i|(E)"
};
/// <summary>
/// 预测分析表
/// </summary>
/// <param name="args"></param>
static string[,] predictTab =
{
{" ", "i", "+", "*", "(", ")", "#" },
{"E" , "TB", "NULL", "NULL", "TB", "NULL", "NULL" },
{"B" , "NULL", "+TB", "NULL", "NULL", "ε", "ε"},
{"T" , "FY", "NULL", "NULL", "FY", "NULL", "NULL" },
{"Y" , "NULL", "ε", "*FY", "NULL", "ε", "ε" },
{"F" , "i", "NULL", "NULL", "(E)", "NULL", "NULL" }
};
static void Main(string[] args)
{
DisplayG();
DisplayTab();
WriteLine("请输入要分析的串:");
string inputString = ReadLine();
WriteLine("--------------------------------------------------------------------------");
string symbolStack = "#E";
Process process = new Process(symbolStack, inputString, predictTab);
process.BeginAnalyze();
}
/// <summary>
/// 打印文法列表
/// </summary>
static void DisplayG()
{
WriteLine("文法列表 (将课件例题中的 E' 换成了 B , T' 换成了 Y)");
foreach (string s in Grammar)
{
WriteLine(s);
}
WriteLine("--------------------------------------------------------------------------");
}
/// <summary>
/// 打印预测分析表
/// </summary>
static void DisplayTab()
{
WriteLine("{0,35}", "预测分析表");
for (int i = 0; i < predictTab.GetLength(0); i++)
{
for (int j = 0; j < predictTab.GetLength(1); j++)
{
Write($"{predictTab[i, j],-10}");
}
WriteLine();
}
WriteLine("--------------------------------------------------------------------------");
}
class Process
{
public int index;//步骤
public string symbolStack;//分析栈
public string residueString;//剩余串
public string productionRule;//产生式或匹配
public string[,] predictTab;//预测表
public Process(string symbolStack, string inputString, string[,] predictTab)
{
this.index = 1;
this.symbolStack = symbolStack;
this.residueString = inputString;
this.predictTab = predictTab;
}
//当前输入符号
public string Terminal
{
get
{
return residueString.Substring(0, 1);
}
}
//分析栈栈顶元素
public string StackTop
{
get
{
return symbolStack.Substring(symbolStack.Length - 1, 1);
}
}
//产生式首字符
public string ruleTop
{
get
{
return productionRule.Substring(0,1);
}
}
/// <summary>
/// LL(1) 分析
/// </summary>
public void BeginAnalyze()
{
while (true)
{
productionRule = GetProductionRule();
Display();
symbolStack = symbolStack.Substring(0, symbolStack.Length - 1);
if (productionRule== "ε")
{
index++;
continue;
}
if (ruleTop == Terminal)
{
if (residueString.Length == 1)
{
WriteLine(" 分析完成,匹配成功!");
return;
}
else
{
residueString = residueString.Substring(1, residueString.Length-1);
if (productionRule.Length > 1)
{
symbolStack += Reverse(productionRule.Substring(1, productionRule.Length - 1));
}
}
}
else
{
residueString = residueString.Substring(0, residueString.Length);
symbolStack += Reverse(productionRule);
}
index++;
}
}
/// <summary>
/// 获取推导所用的产生式或匹配
/// </summary>
/// <returns></returns>
private string GetProductionRule()
{
int row = GetRowIndex(StackTop);
int col = GetColIndex(Terminal);
string rule = predictTab[row, col];
if (rule == "NULL")
{
Error();
}
return rule;
}
/// <summary>
/// 根据栈顶元素获取行号
/// </summary>
/// <param name="stackTop"></param>
/// <returns></returns>
private int GetRowIndex(string stackTop)
{
int index = -1;
for(int i = 0; i < predictTab.GetLength(0); i++)
{
if (predictTab[i, 0] == stackTop)
{
index = i;
}
}
if (index == -1)
{
Error();
}
return index;
}
/// <summary>
/// 根据当前终结符获取列号
/// </summary>
/// <param name="terminal"></param>
/// <returns></returns>
private int GetColIndex(string terminal)
{
int index = -1;
for (int i = 0; i < predictTab.GetLength(1); i++)
{
if (predictTab[0, i] == terminal)
{
index = i;
}
}
if (index == -1)
{
Error();
}
return index;
}
/// <summary>
/// 反转字符串
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
private string Reverse(string s)
{
char[] cs= s.ToCharArray();
Array.Reverse(cs);
return new string(cs);
}
/// <summary>
/// 打印当前步骤
/// </summary>
private void Display()
{
WriteLine($"{index,-20}{symbolStack,-20}{residueString,-20}{productionRule,-20}");
}
/// <summary>
/// 出错处理程序
/// </summary>
private void Error()
{
WriteLine("!!!!!!!!!!!!!! 语句非法 !!!!!!!!!!!!!!");
Environment.Exit(0);
}
}
}
}
边栏推荐
- Mendix:企业成功执行数字化转型的9个因素
- 随手记:laravel、updateOrCreate 和 updateOrInsert 的区别
- 正则表达式的限定符、或运算符、字符类、元字符、贪婪/懒惰匹配
- Mysql management commands
- Some useful frameworks in Kotlin
- 文件上传接入阿里云OSS
- 第十三届蓝桥杯(Web 应用开发)线上模拟赛【第九题】(知乎首页数据动态化)
- 借问变量何处存,牧童笑称用指针,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang类型指针(Pointer)的使用EP05
- 分门别类输入输出,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang基本数据类型和输入输出EP03
- Flask 教程 第七章:错误处理
猜你喜欢

Web3到底是什么?

Maykel Studio OpenHarmony Device Development Training Notes - Chapter 6 Study Notes
Flask 教程 第二章:模板

com.alibaba.fastjson.JSONException: default constructor not found. class

OpenEuler's Ways to Improve Resource Utilization 02: Effects under Typical Applications

磁控胶囊胃镜:具有良好耐受性的非侵入性胃镜检查

二分查找的坑

知乎高赞:如果一个程序员工作5年后还没成为大牛,是不是该考虑别的路子了?

Linux下使用kill杀不死Mysql进程一直杀不死的问题解决方案

新库上线 | CnOpenData信息传输、软件和信息技术服务业工商注册企业基本信息数据
随机推荐
瑞吉外卖项目实战Day06--手机端
Use fontforge to modify font, keep only numbers
关于Mac终端自定义命令和Mysql命令问题
Superman is coming!Flutter realizes full-screen power animation!
com.alibaba.fastjson.JSONException: default constructor not found. class
MySQL8 免安装版安装
Float.parseFloat()的作用
C语言初阶-指针
高数_复习_第3章:一元函数积分学
买股票安全吗 资金能取出来吗
LitJson使用中的一些问题
技术分享 | 接口自动化测试之JSON Schema模式该如何使用?
Kotlin Notes - Difference Between ForEach and ForEachIndexed
基于opencv的图片人像移除
Swoole 健康检查
自定义MVC
基于opencv的实时睡意检测系统
Flask 教程 第八章:粉丝
Flask 教程 第十章:邮件支持
二分查找的坑