Educoder 实验1《词法分析程序设计与实现》(C语言版)

任务描述

本关任务:加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。
相关知识

为了完成本关任务,你需要掌握:词法分析程序设计与实现。
词法分析的基本知识

词法分析程序( Lexical analyzer,简称 Lexer ),负责从左到右逐个字符地对源程序进行扫描和分解,根据语言的词法规则识别出一个个的单词符号。

因此一个词法分析程序应具备如下功能:

从左至右扫描构成源程序的字符流

识别出有词法意义的单词

返回单词记录,或词法错误信息

由上可知词法分析中的一个重要环节为识别单词符号类型,为了便于语法分析,通常将单词符号分为五类。

标识符
用来命名程序中出现的变量、数组、函数、过程、标号等,通常是一个字母开头的字母数字串,如 length,nextch 等。

基本字
也可以成为关键字或保留字。如 if,while,for,do,goto 等。他们具有标识符的形式,但他们不是由用户而是由语言定义的,其意义是约定的。多数语言中规定,他们不能作为标识符或者标识符的前缀,即用户不能使用它们来定义用户使用的名字,故我们称它为保留字,这些语言如 Pascal 和 C 等。但也有的语言允许将基本字作为标识符或者标识符的前缀,这类语言如 Fortran 等。

常数
包括各种类型的常数,如整型、实型、字符型、布尔型等。如:5、3.1415926、a、TRUE等都是常数。

运算符
算术运算符+、-、×、÷;关系运算符<,<=,>,>=,==,!=以及逻辑运算符&&,(),||或者!等。

界符
如,、;等单字界符和/,/,//等双字界符,空白符等。

在进行词法分析后,识别出来的单词应该采用某种中间表示形式,以便为编译后续阶段方便地引用。通常一个单词用一个二元式来表示:
(单词类别,单词的属性)
其中,第一元用于区分单词所属的类别,以整数编码表示。第二元用于区分该类别中的哪一个单词符号,即单词符号的值。
实验步骤

由一个词法分析程序应具备的功能来看,我们的程序具有如下要求:

对单词的构词规则有明确的定义;
编写的分析程序能够正确识别源程序中的单词符号;
识别出的单词以<种别码,值>的形式保存在符号表中,正确设计和维护符号表;
对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成整个源程序的词法分析;

下面我们进行实验代码的步骤分析。

定义目标语言的可用符号表和构词规则。
我们需要对五种单词符号进行识别分析,这里将单词符号分为三大块进行识别。首先判断字符是否为关键字或者标识符,并与已定义好的关键字进行比较,从而判断为关键字或者标识符;然后是数字的识别;最后是其他字符的判断,它们被一一定义好的判断进行识别,这样所有的字符便被识别出来了。标示符和关键字的判断

    if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))  //可能是标示符或者关键字 

字符与关键字的区别通过对比得出:

          if (strcmp(token, rwtab1[n]) == 0)
          {
              syn = 2;
              break;
          }
          else if (strcmp(token, rwtab[n]) == 0) {
              syn = 1;
              break;
          }
    }

对于数字的识别:
#include<stdio.h>  
#include<string.h>  
#include<iostream>  
using namespace std;  
char prog[80], token[20];  
char ch;  
int syn, p, m = 0, n, row, sum = 0;  
const char* rwtab[8] = { "if","int","for","while","do","return","break","continue" };  
const char* rwtab1[8] = { "main","a","b","c","d","e","f","g" };
void scaner()  
{  
    /*  
        共分为三大块,分别是标示符、数字、符号,对应下面的 if   else if  和 else  
    */  
    for (n = 0; n < 8; n++) token[n] = NULL;  
    ch = prog[p++];  
    while (ch == ' ')  
    {  
        ch = prog[p];  
        p++;  
    }  
    /*******Beign*******/  
    /*进行标示符或者关键字的识别*/  
    if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))  //可能是标示符或者关键字   
    {  
        m = 0;  
        while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))  
        {  
            token[m++] = ch;  
            ch = prog[p++];  
        }  
        token[m++] = '\0';  
        p--;  
        syn = 2;  
        for (n = 0; n < 8; n++)  //将识别出来的字符和已定义的关键字作比较,   
            if (strcmp(token, rwtab1[n]) == 0)  
            {  
                syn = 2;  
                break;  
            }  
            else if (strcmp(token, rwtab[n]) == 0) {  
                syn = 1;  
                break;  
            }  
    }  
    /********End********/
    /*******Beign*******/  
    /*进行数字的识别*/  
    else if ((ch >= '0' && ch <= '9'))  //数字   
    {  
        {  
            sum = 0;  
            while ((ch >= '0' && ch <= '9'))  
            {  
                sum = sum * 10 + ch - '0';  
                ch = prog[p++];  
                syn = 3;  
            }  
        }  
        p--;  
        syn = 3;  
        if (sum > 32767)  
            syn = -1;  
    }  
    /********End********/
    /*******Beign*******/  
    /*进行其他字符的识别*/  
    else switch (ch)   //其他字符   
    {  
    case'<':m = 0; token[m++] = ch;  
        ch = prog[p++];  
        if (ch == '>')  
        {  
            syn = 4;  
            token[m++] = ch;  
        }  
        else if (ch == '=')  
        {                                     
            syn = 4;  
            token[m++] = ch;  
        }  
        else  
        {  
            syn = 4;  
            p--;  
        }  
        break;  
    case'>':m = 0; token[m++] = ch;  
        ch = prog[p++];  
        if (ch == '=')  
        {  
            syn = 4;  
            token[m++] = ch;  
        }  
        else  
        {  
            syn = 4;  
            p--;  
        }  
        break;  
    case':':m = 0; token[m++] = ch;  
        ch = prog[p++];  
        if (ch == '=')  
        {  
            syn = 4;  
            token[m++] = ch;  
        }  
        else  
        {  
            syn = 4;  
            p--;  
        }  
        break;  
    case'*':syn = 4; token[0] = ch; break;  
    case'/':syn = 4; token[0] = ch; break;  
    case'+':syn = 4; token[0] = ch; break;  
    case'-':syn = 4; token[0] = ch; break;  
    case'=':syn = 4; token[0] = ch; break;  
    case';':syn = 5; token[0] = ch; break;  
    case',':syn = 5; token[0] = ch; break;  
    case'(':syn = 5; token[0] = ch; break;  
    case')':syn = 5; token[0] = ch; break;  
    case'{':syn = 5; token[0] = ch; break;  
    case'}':syn = 5; token[0] = ch; break;  
    case'#':syn = 0; token[0] = ch; break;  
    case'\n':syn = -2; break;  
    default: syn = -1; break;  
    }  
    /********End********/  
}
int main()  
{  
    /*******Beign*******/  
    /*输入*/  
    p = 0;  
    row = 1;  
    cout << "Please input string:" << endl;  
    do  
    {  
        cin.get(ch);  
        prog[p++] = ch;  
    } while (ch != '#');  
    /********End********/  
    /*******Beign*******/  
    /*输出*/  
    p = 0;  
    do  
    {  
        scaner();  
        switch (syn)  
        {  
        case 0: break;  
        case 3: cout << "(" << syn << "," << sum << ")" << endl; break;  
        case -1: cout << "Error in row " << row << "!" << endl; break;  
        case -2: row++; break;  
        default: cout << "(" << syn << "," << token << ")" << endl; break;  
        }  
    } while (syn != 0);  
    /********End********/  
}   
  • 14
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我很乐意为您介绍如何使用Java完成词法分析程序的设计与实现。 首先,词法分析是编译器的第一步,其作用是将源代码转换为一个个单词(Token),每个单词都是语法结构的基本单位。在Java中,可以使用正则表达式来实现词法分析。 以下是一个简单的Java程序,用于将一个输入的字符串分解为单词(Token): ```java import java.util.regex.Matcher; import java.util.regex.Pattern; public class Lexer { private String input; private Pattern pattern; private Matcher matcher; public Lexer(String input) { this.input = input; pattern = Pattern.compile("\\s*(\\d+|\\+|\\-|\\*|/|\\(|\\))\\s*"); matcher = pattern.matcher(input); } public boolean hasNextToken() { return matcher.find(); } public String getNextToken() { return matcher.group(1); } } ``` 在上面的代码中,我们首先定义了一个Lexer类,用于处理输入的字符串。在Lexer类的构造函数中,我们使用正则表达式将输入的字符串分解为单词(Token),并将其存储在一个Matcher对象中。在hasNextToken()方法中,我们判断Matcher对象中是否还有下一个单词(Token),如果有则返回true,否则返回false。在getNextToken()方法中,我们返回Matcher对象中的下一个单词(Token)。 下面是一个使用Lexer类的例子: ```java public class Main { public static void main(String[] args) { Lexer lexer = new Lexer("1 + 2 * (3 - 4) / 5"); while (lexer.hasNextToken()) { System.out.println(lexer.getNextToken()); } } } ``` 在上面的代码中,我们首先创建了一个Lexer对象,并将一个包含数学表达式的字符串作为输入。然后,在一个循环中,我们使用getNextToken()方法逐个输出Lexer对象中的单词(Token)。 以上就是使用Java完成词法分析程序的设计与实现的简单介绍。希望对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值