编译原理 SysY语言的词法分析程序
Posted Ice丨shine
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译原理 SysY语言的词法分析程序相关的知识,希望对你有一定的参考价值。
- 实验目的与内容
对SysY语言进行词法分析,可以查出语言中可能包含的词法错误。
从控制台输入字符串,如有出错则输出错误,没有错误则按照二元组的方式输出 - 设计方法
对SysY语法进行分析如下:
(1) 保留字: if else for while do continue return break int const main void
注意:所有关键词都是小写的。
(2) 标识符ID,与标准C语言一致,即:以下划线或字母开头的字母数字下划线组成的符号串。
(3)运算符和分界符: +、-、*、/、% 、==、!=、<、>、<=、>= 、!、&&、|| 、(、)、{、}、[、]。
(4) 空白符包括空格、制表符和换行符,用于分割标识符、保留字、运算符和分界符,词法分析阶段要忽略空白符。
本程序使用Java编写
程序启动输入后,字符串保留在instr中。先对字符串进行预处理,去除两个词之间多余的空格,再按空格进行切割。切割完成后逐个单词进行判断,分别判断是否属于保留字、数字、运算符和分界符等等,如果匹配成功则输出。每次判断时使用token逐个读取字符串的各个字符直到一个单词结束并且进行判断。
package cn.hdu;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Word {//1.词法分析程序
public static boolean IsLetter(char ch){
if ((ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z'))
return true;
return false;
}
//判断是否为数字
public static boolean IsDigit(char ch)
{
if (ch >= '0'&&ch <= '9')
return true;
return false;
}
//判断是否为分界符
public static int IsSymbol(char ch)
{
char symbol[]= { '(',')',',',';','<','>','{','}','[',']'};
for (int i = 0; i < 8; i++)
{
if (ch == symbol[i])
return i;
}
return -1;
}
//判断是否为关键字
public static int IsKeyword(String str)
{
String keyword[] = {"if","else","for","while","do", "continue", "return", "break" ,"int", "const", "main", "void" };
for (int i = 0; i < keyword.length; i++)
{
if (str.equals(keyword[i]) )
{
return i;
}
}
//不是关键字即为标识符
return 30;
}
public static boolean IsRight(String str)
{
char[] chars = str.toCharArray();
// System.out.println(chars.length);
int f = 0;
//for (int i = 0; i < str.length()-1; i++)
//{
/* if (IsLetter(chars[i]) ||"_".equals( chars[i]))
f=1;*/
if (IsDigit(chars[0]))
if (IsLetter(chars[1]) || chars[1] == '_')
return false;
//}
/* if(f==0) return true;
if(!(IsLetter(chars[0])||chars[0]=='_')) return false;
for (int i = 0; i < str.length(); i++)
{
if (!(IsDigit(chars[i])||IsLetter(chars[i]) ||"_".equals( chars[i])))
return false;
}*/
return true;
}
//多余空格处理
public static String HandleSpace(String str)
{
int j = 0;
char[] word=new char[255];
boolean temp = false;
char[] a = str.toCharArray();
for (int i = 0; i < a.length; i++)
{
if (a[i] != ' ' && a[i] != '\\t')
{
word[j++] = a[i];
temp = false;
}
else
{
if (!temp&&a[i] != '\\t')
{
word[j++] = a[i];
temp = true;
}
}
}
char[] ans = new char[j];
for (int i = 0; i < j; i++) {
ans[i]=word[i];
}
return String.valueOf(ans);
}
public static void main(String[] args) {
String token= new String();//存放字符串
String[] str;
String instr;
boolean flag=false;
int k=0;
Map<Integer,String> identifiers= new HashMap<>();
Scanner sc = new Scanner(System.in);
while(sc.hasNextLine()){
instr = sc.nextLine();
if(instr.equals("")) break;
str = HandleSpace(instr).split(" ");//处理多余空格后按空格分隔
for (int j = 0; j < str.length; j++) {
//System.out.println(i+str[i]);
char[] strtemp = str[j].toCharArray();//将分隔好的字符串装换为字符数组
if (!IsRight(str[j]))
{
System.out.println(str[j]+" 为非法输入");
break;
}
for (int i = 0; i<strtemp.length&&strtemp[i]!=' '; i++) {
//标识符,关键词
if ((IsLetter((strtemp[i])) || (strtemp[i]) == '_') && !flag)
{
while (i<strtemp.length&&(IsLetter(strtemp[i]) || IsDigit(strtemp[i]) || strtemp[i] == '_'))
{
//System.out.println("strtemp:"+strtemp[i]);
token += strtemp[i];
i++;
}
i--;
//System.out.println("token"+token);
//System.out.println("istoken"+IsKeyword(token));
if (IsKeyword(token) != 30)
{
System.out.println("(<保留字>"+token+")");
}
else{
if(identifiers.containsKey(token)){
System.out.println("(<标识符>,"+token+")");
}else{
identifiers.put(k,token);
System.out.println("(<标识符>,"+token+")");
k++;
}
}
token = "";
}
else if (IsDigit(strtemp[i]) && !flag)
{
while (i<strtemp.length&&IsDigit(strtemp[i]))
{
token +=strtemp[i];
i++;
}
i--;
System.out.println("(<数字> "+token+")");
token = "";
}
//<,<=,<>
else if (strtemp[i] == '<' && !flag)
{
if (i+1<strtemp.length&&strtemp[i+1] == '=')
{
System.out.println("(<运算符> <=)");
}
else if (i+1<strtemp.length&&strtemp[i+1] == '>')
{
System.out.println("(<运算符> <>)");
}
else
{
System.out.println("(<运算符> < )");
}
}
//>,>=
else if (strtemp[i] == '>' && !flag)
{
if (i+1<strtemp.length&&strtemp[i+1] == '=')
{
System.out.println("(<运算符> >=)");
i++;
}
else
{
System.out.println("(<运算符> >)");
}
}
//!,!=
else if (strtemp[i] == '!' && !flag)
{
if (i+1<strtemp.length&&strtemp[i+1] == '=')
{
System.out.println("(<运算符> !=)");
i++;
}
else
{
System.out.println("(<运算符> !)");
}
}
//+,++
else if (strtemp[i] == '+' && !flag)
{
if (i+1<strtemp.length&&strtemp[i+1] == '+')
{
System.out.println("(<运算符> ++)");
i++;
}
else
{
System.out.println("(<运算符> +)");
}
}
//-,--
else if (strtemp[i] == '-' && !flag)
{
if (i+1<strtemp.length&&strtemp[i+1] == '-')
{
System.out.println("(<运算符> --)");
i++;
}
else
{
System.out.println("(<运算符> -)");
}
}
else if (strtemp[i] == '*' && !flag)
{
System.out.println("(<运算符> * )");
}
else if (strtemp[i] == '/' && !flag)
{
System.out.println("(<运算符> / )");
}
//=,==
else if (strtemp[i] == '=' && !flag)
{
if (i+1<strtemp.length&&strtemp[i+1] == '=')
{
System.out.println("(<运算符> ==)");
i++;
}
else
{
System.out.println("(<运算符> =)");
}
}
//余下定界符等
else if (IsSymbol(strtemp[i]) != -1 && !flag)
{
System.out.println("(<分界符> "+strtemp[i]+")");
}
else if(!flag)
{
System.out.println(str[j]+"为非法标识符");
break;
}
}
}
}
}
}
- 程序测试
1.输入:
int main(){
return 0;
}
输出:
(<保留字>int)
(<保留字>main)
(<分界符> ()
(<分界符> ))
(<分界符> {)
(<保留字>return)
(<数字> 0)
(<分界符> 😉
(<分界符> })
2.输入:
int a;
int main(){
a=10;
return 0;
}
输出:
(<保留字>int)
(<标识符>,a)
(<分界符> 😉
(<保留字>int)
(<保留字>main)
(<分界符> ()
(<分界符> ))
(<分界符> {)
(<标识符>,a)
(<运算符> =)
(<数字> 10)
(<分界符> 😉
(<保留字>return)
(<数字> 0)
(<分界符> 😉
(<分界符> })
3.输入:
int main(){
int 4a;
}
输出:
(<保留字>int)
(<保留字>main)
(<分界符> ()
(<分界符> ))
(<分界符> {)
(<保留字>int)
4a; 为非法输入
(<分界符> })
4.输入:
int ifElse() {
int a;
a = 5;
if (a == 5) {
a = 25;
} else {
a = a * 2;
}
return (a);
}
4.int main() {
return (ifElse());
}
输出:
(<保留字>int)
(<标识符>,ifElse)
(<分界符> ()
(<分界符> ))
(<分界符> {)
(<保留字>int)
(<标识符>,a)
(<分界符>;)
(<标识符>,a)
(<运算符> =)
(<数字> 5)
(<分界符>;)
(<保留字>if)
(<分界符> ()
(<标识符>,a)
(<运算符> ==)
(<数字> 5)
(<分界符> ))
(<分界符> {)
(<标识符>,a)
(<运算符> =)
(<数字> 25)
(<分界符>;)
(<标识符>,a)
(<运算符> =)
(<数字> 25)
(<分界符>;)
(<分界符> })
(<保留字>else)
(<分界符> {)
(<标识符>,a)
(<运算符> =)
(<标识符>,a)
(<运算符> * )
(<数字> 2)
(<分界符>;)
(<分界符> })
(<保留字>return)
(<分界符> ()
(<标识符>,a)
(<分界符> ))
(<分界符>;)
(<分界符> })
(<保留字>int)
(<保留字>main)
(<分界符> ()
(<分界符> ))
(<分界符> {)
(<保留字>return)
(<分界符> ()
(<标识符>,ifElse)
(<分界符> ()
(<分界符> ))
(<分界符> ))
(<分界符>;)
(<分界符> })
以上是关于编译原理 SysY语言的词法分析程序的主要内容,如果未能解决你的问题,请参考以下文章