一. 类C语言语法描述和实验要求

  1. 类C语言中关键字有20个,见下表

| 序号 | 关键字 | 序号 | 关键字 | |---|---|---|---| | 1 | begin | 11 | exit | | 2 | do | 12 | if | | 3 | while | 13 | else | | 4 | for | 14 | select | | 5 | int | 15 | case | | 6 | string | 16 | break | | 7 | double | 17 | return | | 8 | bool | 18 | end | | 9 | char | 19 | write | | 10 | float | 20 | read |

  1. 类C语言中运算符见下表:

| 序号 | 运算符 | 序号 | 运算符 | |---|---|---|---| | 21 | + | 36 | ! | | 22 | - | 37 | && | | 23 | * | 38 | || | | 24 | / | 39 | ++ | | 25 | ** (乘方) | 40 | -- | | 26 | % (求余) | 41 | , | | 27 | = (赋值) | 42 | - (负号) | | 28 | += | 43 | & | | 29 | -= | 44 | % (格式运算符) | | 30 | == | | | | 31 | <> | | | | 32 | > | | | | 33 | >= | | | | 34 | < | | | | 35 | <= | | |

  1. 类C语言中分界符见下表:

| 序号 | 分界符 | 序号 | 分界符 | |---|---|---|---| | 45 | ( | 48 | ; | | 46 | ) | 49 | ' | | 47 | , | 50 | ' |

  1. 标识符和关键字的构词规则为'以大写字母(A-Z)或小写字母(a-z)开头,后面可以跟大写字母或小写字母或数字(0-9)或下划线。如果有下划线,只能出现一次,长度最多为15个'。区分大小写。

  2. 常量分为整型、实型、字符型、字符串型、布尔型。其中整型常量包括十进制、八进制和十六进制,实型包括十进制和科学计数法。其中:

(1) 整型常量八进制、十进制和十六进制与C语言要求一致。 (2) 实型常量要求与C语言要求一致。注意小数点的个数。 (3) 字符类型和字符串类型常量要求与C语言要求一致。 (4) 布尔型常量有2个,分别是TRUE和FALSE。

  1. 能识别出部分单词拼写错误并输出错误行数和错误信息。

  2. 以类C语言编写测试用例源程序,以二元式(单词类别、单词值)形式为输出结果。关键字、运算符、分界符、标识符单词类别自己指定或按照表格中的数字表示均可,标识符单词的值则以其在符号表中的地址表示;常量一个类型一种类别,并自己指定每种类型的单词类别,整型和实型常量单词值以二进制形式表示,其余类型照原样输出。

类C语言源程序样例:

int f(int a,double b)
begin 
  bool c=TRUE;
  char d;
  float e;
string f;
read('"%f"',&e);
d='345';
 while(a<=e)
   begin
     b=a**2+b/3;
     select(c)
     case   f='"a"';   break;
     case   e=-4.3+3.52e12.3+0x123-0123;
     case   a+=8; 
     case   c=5<>9;
   end
write('"%f%d"',e,a);
END

二. 实验步骤

  1. 用类C语言编写测试用例源程序(如上所示)。用C语言或其他语言编写能够编译该源程序的词法分析程序。
  2. 运行词法分析程序,读入类C语言源程序,进行词法分析,并以二元式形式输出结果。
  3. 词法分析程序出错可设立断点,单步运行词法分析程序,依次单个输出单词。分析和理解词法分析程序,解释词法分析程序中的数据和变量变化的原因和输出结果。
  4. 运行修改后的词法分析程序,读入修改后的类C语言测试用例源程序,进行词法分析。

类C语言词法分析程序示例 (C语言)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义关键字数组
char keywords[20][20] = {
    "begin", "do", "while", "for", "int",
    "string", "double", "bool", "char",
    "float", "exit", "if", "else", "select",
    "case", "break", "return", "end", "write", "read"
};

// 定义运算符数组
char operators[25][5] = {
    "+", "-", "*", "/", "**", "%", "=", "+", "-",
    "==", "<>", ">", ">=", "<", "<=", "!", "&&",
    "||", "++", "--", ",", "-", "&", "%"
};

// 定义分界符数组
char delimiters[5][2] = {
    "(", ")", ",", ";", "'"
};

// 判断是否为字母
int isLetter(char c) {
    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}

// 判断是否为数字
int isDigit(char c) {
    return c >= '0' && c <= '9';
}

// 判断是否为关键字
int isKeyword(char *word) {
    int i;
    for (i = 0; i < 20; i++) {
        if (strcmp(word, keywords[i]) == 0) {
            return i + 1;
        }
    }
    return 0;
}

// 判断是否为运算符
int isOperator(char *word) {
    int i;
    for (i = 0; i < 25; i++) {
        if (strcmp(word, operators[i]) == 0) {
            return i + 21;
        }
    }
    return 0;
}

// 判断是否为分界符
int isDelimiter(char *word) {
    int i;
    for (i = 0; i < 5; i++) {
        if (strcmp(word, delimiters[i]) == 0) {
            return i + 45;
        }
    }
    return 0;
}

// 词法分析函数
void lexAnalysis(char *sourceCode) {
    char word[20];
    int i = 0, j = 0;
    
    while (sourceCode[i] != '\0') {
        // 跳过空格和换行符
        if (sourceCode[i] == ' ' || sourceCode[i] == '\n') {
            i++;
            continue;
        }
        
        // 判断是否为字母或下划线,是则可能为关键字或标识符
        if (isLetter(sourceCode[i]) || sourceCode[i] == '_') {
            j = 0;
            while (isLetter(sourceCode[i]) || isDigit(sourceCode[i]) || sourceCode[i] == '_') {
                word[j] = sourceCode[i];
                i++;
                j++;
            }
            word[j] = '\0';
            
            // 判断是否为关键字
            int keywordIndex = isKeyword(word);
            if (keywordIndex != 0) {
                printf("(%d, %s)\n", keywordIndex, word);
            } else {
                printf("(ID, %s)\n", word);
            }
        }
        
        // 判断是否为数字,是则可能为整型常量或实型常量
        else if (isDigit(sourceCode[i])) {
            j = 0;
            while (isDigit(sourceCode[i])) {
                word[j] = sourceCode[i];
                i++;
                j++;
            }
            
            // 判断是否为实型常量
            if (sourceCode[i] == '.') {
                word[j] = sourceCode[i];
                i++;
                j++;
                while (isDigit(sourceCode[i])) {
                    word[j] = sourceCode[i];
                    i++;
                    j++;
                }
                word[j] = '\0';
                printf("(FLOAT_CONST, %s)\n", word);
            }
            
            // 判断是否为整型常量
            else {
                word[j] = '\0';
                printf("(INT_CONST, %s)\n", word);
            }
        }
        
        // 判断是否为运算符
        else if (sourceCode[i] == '+' || sourceCode[i] == '-' || sourceCode[i] == '*' || sourceCode[i] == '/' || sourceCode[i] == '%' || sourceCode[i] == '=' || sourceCode[i] == '<' || sourceCode[i] == '>' || sourceCode[i] == '!' || sourceCode[i] == '&' || sourceCode[i] == '|') {
            j = 0;
            while (sourceCode[i] == '+' || sourceCode[i] == '-' || sourceCode[i] == '*' || sourceCode[i] == '/' || sourceCode[i] == '%' || sourceCode[i] == '=' || sourceCode[i] == '<' || sourceCode[i] == '>' || sourceCode[i] == '!' || sourceCode[i] == '&' || sourceCode[i] == '|') {
                word[j] = sourceCode[i];
                i++;
                j++;
            }
            word[j] = '\0';
            
            // 判断是否为运算符
            int operatorIndex = isOperator(word);
            if (operatorIndex != 0) {
                printf("(%d, %s)\n", operatorIndex, word);
            }
        }
        
        // 判断是否为分界符
        else {
            j = 0;
            while (sourceCode[i] == '(' || sourceCode[i] == ')' || sourceCode[i] == ',' || sourceCode[i] == ';' || sourceCode[i] == "'") {
                word[j] = sourceCode[i];
                i++;
                j++;
            }
            word[j] = '\0';
            
            // 判断是否为分界符
            int delimiterIndex = isDelimiter(word);
            if (delimiterIndex != 0) {
                printf("(%d, %s)\n", delimiterIndex, word);
            }
        }
    }
}

int main() {
    char sourceCode[1000] = "int f(int a,double b)\nbegin\n  bool c=TRUE;
  char d;
  float e;
string f;
read('"%f"',&e);
d='345';
 while(a<=e)
   begin
     b=a**2+b/3;
     select(c)
     case   f='"a"';   break;
     case   e=-4.3+3.52e12.3+0x123-0123;
     case   a+=8; 
     case   c=5<>9;
   end
write('"%f%d"',e,a);
END";
    
    lexAnalysis(sourceCode);
    
    return 0;
}

注意:

  • 该示例程序仅提供一个基本的词法分析框架,可能无法处理所有情况。您需要根据实际需求进行修改和扩展。
  • 在实际应用中,需要使用更完善的词法分析算法,例如有限自动机 (DFA) 或正则表达式匹配等。
  • 您可以使用更强大的编程语言,例如 Python 或 Java,来编写更加复杂和高效的词法分析程序。

希望这些信息对您有所帮助!如果您还有其他问题,请随时提出。

类C语言词法分析程序:语法描述、实验要求及代码示例

原文地址: https://www.cveoy.top/t/topic/X1d 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录