目的:熟练掌握自上而下的语法分析方法,并能用程序实现。
FIRST(E) = FIRST(T) = FIRST(F) = { ( , id }
FIRST(E ') = {+, e}
FRIST(T ') = {*, e}
FOLLOW(E) = FOLLOW(E ') = { ), $}
FOLLOW(T) = FOLLOW (T ') = { +, ), $}
FOLLOW(F) = {+, *, ), $}
要求:
1. 使用的文法如下:
E -> TE '
E '-> + TE ' | e
T ->FT '
T '-> * FT '| e
F -> (E) | id
2. 对于任意给定的输入串(词法记号流)进行语法分析,递归下降方法实现。
3. 要有一定的错误处理功能。即对错误能提示,并且能在一定程度上忽略尽量少的记号来进行接下来的分析。可以参考书上介绍的同步记号集合来处理。
可能的出错情况:idid*id, id**id, (id+id, +id*+id ……
4. 输入串以#结尾,输出推导过程中使用到的产生式。例如:
输入:id+id*id#
输出:E -> TE '
T -> FT '
F -> id
E '->+ TE '
T -> FT '
……
有余力的同学可进一步考虑如下扩展:
import java.util.Scanner;
public class Test {
private static String Str = null; // 输入的表达式
private static String lookahead = null;// 当前记号
private static String Sub = null;// 剩余的子串
//private static boolean flag = false;
public static void match(String s) {
if (lookahead.equals(s)) {
lookahead = nextToken();
System.out.println("匹配" + s);
} else {
error();
}
}
public static void error() {
System.out.println("匹配失败");
}
public static String nextToken() {
if (Sub.length() >= 2) {
if (Sub.substring(0, 2).equals("id")) {
Sub = Sub.substring(2, Sub.length());
lookahead = "id";
} else {
lookahead = Sub.substring(0, 1);
Sub = Sub.substring(1, Sub.length());
}
} else if (Sub.length() == 1) {
lookahead = Sub.substring(0, 1);
}
return lookahead;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
System.out.println("请输入一个表达式:");
Str = in.nextLine();
Sub = Str;
lookahead = nextToken();
in.close();
E();
}
public static void E() {
if (lookahead.equals("(") || lookahead.equals("id"))// First(T)={(,id};
{
System.out.println("E -> TE'");
T();
E1();
} else if (lookahead.equals(")") || lookahead.equals("#"))// Follow(E')加入到E的同步记号集合中
{
error();
// 出错,但不作任何处理
} else {
lookahead = nextToken();
error();
E();
}
}
public static void E1() {
if (lookahead.equals("+")) {
System.out.println("E1 -> TE'");
match("+");
T();
E1();
} else if (lookahead.equals(")") || lookahead.equals("#"))
// Follow(E') = { ) , # };
{
System.out.println("E' -> ^");
if (lookahead.equals("#"))
{match("#");System.exit(0);}
} else// 出错,当前记号不在E'的同步记号集合中,跳过当前符号
{
error();
lookahead = nextToken();
E1();
}
}
public static void T() {
if (lookahead.equals("(") || lookahead.equals("id"))// First(F)={ ( , id };
{
System.out.println("T -> FT'");
F();
T1();
} else if (lookahead.equals("+") || lookahead.equals(")") || lookahead.equals("#"))
// Follow(T)加入到T的同步记号集合中
{
error();
if (lookahead.equals("#")) {
match("#");
System.exit(0);
}
// 出错,但无需跳过任何记号,跳过T即可,即不做任何处理
} else {
// 出错,当前记号不在T的同步记号集合中,跳过当前记号
error();
lookahead = nextToken();
T();
}
}
public static void T1() {
if (lookahead.equals("*")) {
System.out.println("T' -> *FT'");
match("*");
F();
T1();
} else if (lookahead.equals("+") || lookahead.equals(")") || lookahead.equals("#")) {
System.out.println("T' -> ^");
if (lookahead.equals("#")) {
match("#");
System.exit(0);
}
} else// 出错,当前记号不在T1的同步记号集合中,跳过当前记号
{
error();
lookahead = nextToken();
T1();
}
}
public static void F() {
if (lookahead.equals("(")) {
match("(");
E();
match(")");
System.out.println("F -> (E)");
} else if (lookahead.equals("id")) {
System.out.println("F -> id");
match("id");
} else if (lookahead.equals("+") || lookahead.equals("*") || lookahead.equals(")") || lookahead.equals("#"))
// Follow(F)集合加入到F的同步记号集合中
{
error();
// 出错,但无须跳过任何记号,跳过 F 即可,即不作任何处理
} else// 出错,当前记号不在F的同步记号集合中,跳过当前符号
{
error();
lookahead = nextToken();
F();
}
}
}
运行结果如下:
2、输入有错误的情况:
文章浏览阅读358次。情况一:当鼠标移入(onmouseover)父级div(红色)时,子div(蓝色)显示(黑点代表鼠标);情况二:当子div(蓝色)处于显示状态时,把鼠标移动到上面。此时鼠标已经脱离父div(红色),但子div仍然显示。白色代表鼠标移动轨迹。请问为什么鼠标移出父div(红色)时,为什么子div还能显示(蓝色)?这种表现背后的工作原理是什么样的呢?无标题文档*{margin:0;padding:0;}..._父元素下两个子元素,其中一个隐藏,鼠标经过另外一个子元素显示
文章浏览阅读1.2k次。《OpenCV 计算机视觉编程攻略》学习笔记(一:图像编程入门)_opencv计算机视觉编程攻略
文章浏览阅读838次。第二十三章 配置管理Ansible与Saltstack1、配置管理系统2、Ansible3、Saltstack第二十四章 虚拟化(略)第二十五章 容器第二十六章 持续集成与交付 CI/CD_application linux category is set to default "utility" reason=linux.category
文章浏览阅读671次。*Title : Excel Uploading***************************************************************TYPES: BEGIN OF t_datatab, col1(25) TYPE c, col2(30) TYPE c, col3(30) TYPE c, _abap summary. format color col_background intensified.
文章浏览阅读1.7k次,点赞29次,收藏27次。其中url可以直接浏览器访问地址直接解析页面,也可以通过分析页面请求接口(开启google浏览器F12开发者模式,刷新对应页面即可查看请求数据地址 -- >> 具体数据需要通过分享查看)_htmlunit java
文章浏览阅读556次,点赞8次,收藏8次。推荐项目:SpringBoot — 简化Java应用程序开发项目地址:https://gitcode.com/Foreveriss/SpringBootSpring Boot是由Pivotal Software开发的一个框架,它简化了基于Spring的应用程序初始搭建以及开发过程。通过内嵌Tomcat或Jetty服务器,自动配置Spring和提供运行时健康检查等功能,Spring Boot让...
文章浏览阅读1.5k次,点赞2次,收藏16次。自己电脑的GPU不支持cuda,所以尝试使用谷歌的Colabortory,免费提供GPU,最长运行时间12小时,因此一般需要挂载到谷歌云盘上,储存文件。数据集目标检测的数据集需要自己手动标注目标物体位置并对应生成xml文件表示目标框的位置,本文简单介绍windows系统下标注工具LabelImg的使用。LabelImg下载链接:LabeIImg下载好labelImg-master.zip后解压得到如下图所示。shift+右击空白处打开powershell窗口,输入Pyrcc5 -o resour_colabortory路径问题
文章浏览阅读392次。A triangle field is numbered with successive integers in the way shown on the picture below. The traveller needs to go from the cell with number M to the cell with number N. The traveller is able to_hdu1030题解
文章浏览阅读6.5k次,点赞4次,收藏20次。问题描述:三个未知量构成一个方程式,该CSV文件中一共有N行数据有关[x, y, z]的系数,求解三个未知量[x, y, z]的值。文章目录前言 一、工具包 二、使用步骤 1.读入文件 2.编写方程 总结前言三个未知量[x, y, z]之间的关系是:a*x + b*y + c*z = p。像这样的式子,csv文件中一共有N行,我的需求是根据这些不同的系数和不同的结果p值,求出三个未知量的值。一、工具包首先要使用到的工具主要是numpy和panda._python求解多元方程组
文章浏览阅读930次。尽管状态栏非常重要,但是它并不需要一直显示在 iPhone 屏幕的顶部。状态栏是 iOS 系统的主要特征之一,它能够为用户提供大量的信息,用户只需要瞥一眼就能了解 iPhone 当前的剩余电量、WiFi信号以及当前时间等等。尽管状态栏非常重要,但是它并不需要一直显示在 iPhone 屏幕的顶部。一款名为 TapTap Statusbar 的越狱插件能够在用户不需要的时候将状态栏隐藏起来,从而为 i..._h5隐藏状态栏
文章浏览阅读1.8k次。Nginx安装以及配置和使用_使用 nginx 打开webgl
文章浏览阅读949次,点赞18次,收藏25次。Spring是一个开源框架,2003 年兴起的一个轻量级的Java 开发框架,作者:Rod Johnson。Spring是为了解决企业级应用开发的复杂性而创建的,简化开发。学过javaweb的我们就知道,开发一个web应用,从最初开始接触Servlet结合Tomcat, 跑出一个Hello Wolrld程序,是要经历特别多的步骤;后来就用了框架SpringMVC,到了现在的SpringBoot,过一两年又会有其他web框架出现;