编译原理 | 课程设计 — 语法分析

news2024/11/26 23:24:31

第1关:使用C/C++语言编写PL/0编译程序的语法分析程序

1、任务描述

基于第二章的词法分析程序,使用C/C++语言编写PL/0编译程序的语法分析程序。

2、编程要求

完成上述编程任务,将C/C++语言源程序复制粘贴到右侧代码编辑器,点击“评测”按钮,运行程序,系统会自动进行结果对比。

3、测试说明

平台会对你编写的代码进行测试:

测试输入:

const a = 10;
var   b, c;
procedure p;
    if a <= 10 then
        begin
            c := b + a;
        end;
begin
    read(b);
    while b # 0 do
        begin
            call p;
            write(2 * c);
            read(b);
        end;
end.

预期输出:

语法正确

测试输入:

const a := 10;
var   b, c;
procedure p;
    if a <= 10 then
        begin
            c := b + a;
        end;
begin
    read(b);
    while b # 0 do
        begin
            call p;
            write(2 * c);
            read(b);
        end;
end.

预期输出:

(语法错误,行号:1)

测试输入:

const a = 10;
var   b, c;
//单行注释
/*
* 多行注释
*/
procedure p;
    if a <= 10 then
        begin
            c := b + a
        end;
begin
    read(b);
    while b # 0 do
        begin
            call p;
            write(2 * c);
            read(b);
        end;
end.

预期输出:

(语法错误,行号:13)

测试输入:

const a = 10;
var   b, c;
//单行注释
/*
* 多行注释
*/
procedure p;
    if a <= 10 then
        begin
            c := b + a;
        end;
begin
    read(b);
    while b # 0
        begin
            call p;
            write(2 * c);
            read(b);
        end;
end.

预期输出:

(语法错误,行号:17)

测试输入:

const a := 10;
var   b, c d;
//单行注释
/*
* 多行注释
*/
procedure procedure fun1;
    if a <= 10 
        begin
            c = b + a
        end;
begin
    read(b;
    while b # 0 
        begin
            call fun1;
            write 2 * c);
            read(b);
        end;
end.

预期输出:

(语法错误,行号:1)
(语法错误,行号:2)
(语法错误,行号:10)
(语法错误,行号:11)
(语法错误,行号:13)
(语法错误,行号:16)
(语法错误,行号:17)
(语法错误,行号:20)

4、代码 

        语法分析的代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include <iostream>
#include <sstream>
using namespace std;

/* ------------ 全局变量声明定义 ------------ */
int lineNumber = 1; // 当前行号

char charTable[2000];				// 字符表 —— 存储输入程序的 所有字符,包括空格、换行等
string wordTable[200] = { "\0" };	// 单词表 —— 存储输入程序的 所有单词,包括换行
char word[88] = "\0";				// 存储单个字符,添加到 wordTable 中

string ENDsign = "end.";	// 结束标识符
int charIndex = 0;			// 记录当前 charTable 字符个数
int wordIndex = 0;			// 记录当前 wordTable 单词个数

int errorNum = 0;			// 语法错误个数
int errorLine = 0;			// 语法错误行

string reservedWord[20] = { // 保留字
	"begin","call", "const","do","end","if",
	"odd","procedure", "read","then",
	"var","while","write"
};


/* ------------ 函数声明 ------------ */
void LexicalAnalysis();		// 词法分析
void GrammaticalAnalysis();	// 语法分析

void StrConnect(char* str, char ch);	// 拼接字符串
int StrLength(char* str);			// 计算字符串长度

int IsChar(char ch);			// 判断是否是字符
int IsOperator(char ch);		// 判断是否是运算符
int IsDigit(char ch);			// 判断是否是数字
int IsBoundary(char ch);		// 判断是是否界符
int IsReservedWord(char* str);	// 判断是否是保留字

void ProcessString(char ch);	// 判断字符串是否合法,合法则保存到单词表中
void ProcessNumber(char ch);	// 判断数字串是否合法,合法则保存到单词表中

void PrintError(int type);		//语法错误输出

int id();					// 变量名声明判断
void subroutine();			// 子程序
void constant();		// 常量定义
void variable();		// 变量定义
void sentence();			// 语句分析
void annotation();			// 注释
void condition();			// 条件分析
void expression();			// 表达式
void term();				// 项
void factor();				// 因子
void identifier();			// 标识符
void number();				// 数字



/* ------------ 函数定义 ------------ */
// 词法分析
void LexicalAnalysis() {
	while (charTable[charIndex] != '\0') { // 当前字符表未识别到结束符 '\0'
		if (charTable[charIndex] == '\0')
			break;
		if (charTable[charIndex] == ' ') {
			charIndex++;
			continue;
		}
		if (charTable[charIndex] == '\n') {
			wordTable[wordIndex++] = "\n";  // 将 换行符 保存到单词表 wordTable 中
			charIndex++;
			lineNumber++;	// 程序换行,行数加一
		}
		// 识别到字符
		else if (IsChar(charTable[charIndex])) {
			ProcessString(charTable[charIndex]); // 处理该字符之后的字符串
			continue;
		}
		// 识别到数字
		else if (IsDigit(charTable[charIndex])) {
			ProcessNumber(charTable[charIndex]); // 处理该数字之后的数字串
			continue;
		}
		// 识别到'/' 符
		else if (charTable[charIndex] == '/') {
			// 之后是 '/' ,说明是注释 //
			if (charTable[charIndex + 1] == '/') {
				wordTable[wordIndex++] = "//";
				charIndex = charIndex + 2;
				word[0] = '\0';

				while (charTable[charIndex] != '\n') // 将未换行的字符全部识别为注释
					StrConnect(word, charTable[charIndex++]);
				wordTable[wordIndex++] = word;
				wordTable[wordIndex++] = "\n";
				charIndex++;
				continue;
			}
			// 之后是 '*' ,说明是注释 /*
			else if (charTable[charIndex + 1] == '*') {
				wordTable[wordIndex++] = "/*";
				charIndex = charIndex + 2;
				while (!(charTable[charIndex] == '*' && charTable[charIndex + 1] == '/')) {
					if (charTable[charIndex] == '\n') {
						wordTable[wordIndex++] = "\n";
						charIndex++;
						continue;
					}
					word[0] = '\0';
					while (charTable[charIndex] != '\n') StrConnect(word, charTable[charIndex++]);
					wordTable[wordIndex++] = word;
					wordTable[wordIndex++] = "\n";
					charIndex++;
				}
				wordTable[wordIndex++] = "*/";
				charIndex = charIndex + 2;
				word[0] = '\0';
				continue;
			}
			// 是非法字符(串)
			else {
				while (charTable[charIndex] != ' ' && IsBoundary(charTable[charIndex]) != 1 && charTable[charIndex] != '\0') {
					StrConnect(word, charTable[charIndex]);
					charIndex++;
				}
				printf("(非法字符(串),%s,行号:%d)\n", word, lineNumber);
				word[0] = '\0';
				break;
			}
		}
		// 识别到比较符
		else if (charTable[charIndex] == '<' || charTable[charIndex] == '>') {
			charIndex++;
			// 是 <= 或者 >= 符
			if (charTable[charIndex] == '=') {
				if (charTable[charIndex - 1] == '<')
					wordTable[wordIndex] = "<="; // 保存单词表
				else
					wordTable[wordIndex] = ">="; // 保存单词表
				wordIndex++;
				charIndex++;
				continue;
			}
			// 是 < 或者 > 符
			else {
				if (charTable[charIndex - 1] == '<')
					wordTable[wordIndex] = "<"; // 保存单词表
				else
					wordTable[wordIndex] = ">"; // 保存单词表
				wordIndex++;
				continue;
			}
		}
		// 识别到':'
		else if (charTable[charIndex] == ':') {
			charIndex++;
			if (charTable[charIndex] == '=') {
				wordTable[wordIndex++] = ":="; // 保存单词表
				charIndex++;
				continue;
			}
			else {
				printf(":后面不是=号\n");
				continue;
			}
		}
		// 识别到运算符
		else if (IsOperator(charTable[charIndex])) {
			wordTable[wordIndex++] = charTable[charIndex]; // 保存单词表
			charIndex++;
			continue;
		}
		// 识别到界符
		else if (IsBoundary(charTable[charIndex])) {
			wordTable[wordIndex++] = charTable[charIndex]; // 保存单词表
			charIndex++;
			continue;
		}
		// 识别到非法字符(串)
		else {
			printf("(非法字符(串),%c,行号:%d)\n", charTable[charIndex], lineNumber);
			charIndex++;
		}
	}
}
// 语法分析
void GrammaticalAnalysis() {
	subroutine();
	if (!wordTable[wordIndex].compare(".")) {
		if (errorNum == 0)
			printf("语法正确\n");
	}
	else {
		PrintError(0); // 输出语法错误以及行号
		return;
	}
}
// 打印语法错误
void PrintError(int type) {
	if (type == 1) {
		if (errorLine != lineNumber) {
			errorLine = lineNumber;
			printf("(语法错误,行号:%d)\n", lineNumber);
			errorNum++;
		}
	}
	else {
		while (wordTable[wordIndex].compare("\n") != 0) 
			wordIndex++;
		if (errorLine != lineNumber) {
			errorLine = lineNumber;
			printf("(语法错误,行号:%d)\n", lineNumber);
			errorNum++;
		}
	}
}


// 拼接字符串
void StrConnect(char* str, char ch) {        
	int i = 0;
	while (str[i] != '\0') i++;
	str[i] = ch;
	str[i + 1] = '\0';
}
// 计算字符串长度
int StrLength(char* str) {     
	int i = 0;
	while (str[i] != '\0') 
		i++;
	return i;
}

// 判断是否是字符
int IsChar(char ch) {
	if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
		return 1;
	else
		return 0;
}
// 判断是否是运算符
int IsOperator(char ch) {                    
	if (ch == '>' || ch == '<' || ch == '=' || ch == '*' || ch == '-' || ch == '+' || ch == '#')
		return 1;
	else
		return 0;
}
// 判断是否是数字
int IsDigit(char ch) {               
	if ((ch >= '0' && ch <= '9'))
		return 1;
	else
		return 0;
}
// 判断是是否界符
int IsBoundary(char ch) {          
	if (ch == ';' || ch == '.' || ch == ',' || ch == '(' || ch == ')')
		return 1;
	else
		return 0;
}
// 判断是否是保留字
int IsReservedWord(char* str) {          
	for (int i = 0; i < 20; i++) 
		if (reservedWord[i].compare(str) == 0) 
			return 1;
	return 0;
}

// 判断字符串是否合法,合法则保存到单词表中
void ProcessString(char ch) {
	// 字符串 或 数字
	if (IsChar(ch) || IsDigit(ch)) { 
		StrConnect(word, ch);
		charIndex++;
		ProcessString(charTable[charIndex]); //处理下一个字符
	}
	// 运算符或界符等,表示当前单词停止
	else if (ch == ' ' || ch == '\n' || ch == '\0' || IsOperator(ch) || IsBoundary(ch)) {
		// 判断为保留字
		if (IsReservedWord(word)) {
			wordTable[wordIndex++] = word; // 保存到单词表 wordTable 中
			word[0] = '\0';	// word变量初始化
		}
		// 否则判断为标识符
		else {
			if (StrLength(word) >= 8) 
				printf("(标识符长度超长,%s,行号:%d)\n", word, lineNumber);
			else 
				wordTable[wordIndex++] = word; 
			word[0] = '\0';
		}
	}
	// 非法字符(串)
	else {
		StrConnect(word, ch);
		printf("(非法字符(串),%s,行号:%d)\n", word, lineNumber);
		charIndex++;
		word[0] = '\0';
	}
}
// 判断数字串是否合法,合法则保存到单词表中
void ProcessNumber(char ch) {
	// 数字
	if (IsDigit(ch)) {
		StrConnect(word, charTable[charIndex]);
		charIndex++;
		ProcessNumber(charTable[charIndex]);
	}
	// 无符号整数
	else if (!IsChar(ch)) {
		if (StrLength(word) >= 6) 
			printf("(无符号整数越界,%s,行号:%d)\n", word, lineNumber);
		else 
			wordTable[wordIndex++] = word; // 保存到单词表 wordTable 中
		word[0] = '\0';
	}
	// 非法字符(串)
	else {
		while (charTable[charIndex] != ' ' && IsBoundary(charTable[charIndex]) != 1 && charTable[charIndex] != '\0') {
			StrConnect(word, charTable[charIndex]);
			charIndex++;
		}
		printf("(非法字符(串),%s,行号:%d)\n", word, lineNumber);
		word[0] = '\0';
	}
}

// 变量名声明判断
int id() {
	// 拷贝当前读取的单词到word变量中
	int i = 0;
	for (i = 0; i < wordTable[wordIndex].length(); i++) 
		word[i] = wordTable[wordIndex][i];
	word[i] = '\0';
	// 判断该单词不是保留字且不为空
	if (!IsReservedWord(word) && word[0] != '.') {
		wordIndex++;
	}
	else PrintError(1);
}
// 子程序
void subroutine() {
	// 当前单词表匹配 const —— 常量定义
	if (!wordTable[wordIndex].compare("const")) {
		wordIndex++;
		constant();
		// 匹配 "," 说明存在多个变量定义 
		while (!wordTable[wordIndex].compare(",")) {
			wordIndex++;
			constant(); // 处理判断下一个常量
		}
		// 匹配 ";" 说明变量声明结束
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			// 匹配换行符,进入下一行的识别
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++; // 函数加一
				annotation();
			}
			subroutine();
		}
		// 否则出错
		else {
			PrintError(0);
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
				annotation();
			}
			subroutine();
		}
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
			annotation();
		}
	}
	// 当前单词表匹配 var
	else if (!wordTable[wordIndex].compare("var")) {
		wordIndex++;
		variable(); // 读下一个单词,变量 语法判断
		// 匹配 "," 说明有多个变量
		while (!wordTable[wordIndex].compare(",")) {
			wordIndex++;
			variable();
		}
		// 匹配 ";" 说明变量声明结束
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			while (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			annotation();
			subroutine();
		}
		// 否则出错
		else {
			PrintError(0);
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
				annotation();
			}
			subroutine();
		}

	}
	// 当前单词表匹配 procedure
	else if (!wordTable[wordIndex].compare("procedure")) {
		wordIndex++;
		id();
		// 匹配 ";" 说明变量声明结束
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			subroutine();
			if (!wordTable[wordIndex].compare(";")) {
				annotation();
				while (!wordTable[wordIndex].compare("\n")) {
					wordIndex++;
					lineNumber++;
					annotation();
				}
				wordIndex++;
			}
			else {
				PrintError(1);

			}
		} 
		// 否则出错
		else {
			PrintError(0);
			subroutine();
		}
		while (!wordTable[wordIndex].compare("procedure")) {
			wordIndex++;
			id();
			if (!wordTable[wordIndex].compare(";")) {
				wordIndex++;
				subroutine();
				if (!wordTable[wordIndex].compare(";")) wordIndex++;
				else  PrintError(1);
			}
			else {
				PrintError(0);
				subroutine();
			}
		}
	}
	// 当前单词表匹配 换行符
	if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}

	sentence(); // 迭代判断
}
// 常量
void constant() {    
	// 标识符处理判断
	identifier();
	// 匹配等号 = 
	if (!wordTable[wordIndex].compare("=")) {
		wordIndex++;
		number(); // 读入下一个数字进行判断
	}
	// 打印错误
	else PrintError(0);
}
// 变量
void variable() {    
	id();
}
// 语句分析
void sentence() {
	// 匹配 if 语句
	if (!wordTable[wordIndex].compare("if")) {
		wordIndex++;
		condition(); // 读下一个单词,条件 语法判断
		// 条件判断后,匹配 then 语句
		if (!wordTable[wordIndex].compare("then")) {
			wordIndex++;
			// 如果换行,行数加一
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence(); // 读下一个单词,语句 语法判断
		}
		// 不匹配,报错
		else {
			PrintError(0);
			sentence();
		}
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
	}
	// 匹配 while 语句
	else if (!wordTable[wordIndex].compare("while")) {
		wordIndex++;
		condition(); // 读下一个单词,条件 语法判断
		// 条件判断后,匹配 do 语句
		if (!wordTable[wordIndex].compare("do")) {
			wordIndex++;
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence(); // 读下一个单词,语句 语法判断
		}
		// 不匹配,报错
		else {
			PrintError(1);
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence();
		}
	}
	// 匹配 call 语句
	else if (!wordTable[wordIndex].compare("call")) {
		wordIndex++;
		id();
	}
	// 匹配 read 语句
	else if (!wordTable[wordIndex].compare("read")) {
		wordIndex++;
		if (!wordTable[wordIndex].compare("(")) {
			wordIndex++;
			id(); 
			// 匹配 "," 说明有多个变量
			while (!wordTable[wordIndex].compare(",")) {
				wordIndex++;
				id();
			}
			// "(" 匹配 ")" ,结束判断
			if (!wordTable[wordIndex].compare(")")) 
				wordIndex++;
			else  
				PrintError(1);
		}
		else if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
		else  PrintError(0);
	}
	// 匹配 write 语句
	else if (!wordTable[wordIndex].compare("write")) {
		wordIndex++;
		if (!wordTable[wordIndex].compare("(")) {
			wordIndex++;
			expression(); // 读下一个单词 表达式语法判断
			// 匹配 "," 说明有多个表达式
			while (!wordTable[wordIndex].compare(",")) {
				wordIndex++;
				expression();
			}
			// "(" 匹配 ")" ,结束判断
			if (!wordTable[wordIndex].compare(")")) 
				wordIndex++;
			else if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			else PrintError(0);
		}
		else {
			PrintError(1);
			expression();
			while (!wordTable[wordIndex].compare(",")) {
				wordIndex++;
				expression();
			}
			if (!wordTable[wordIndex].compare(")")) wordIndex++;
			else if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			else PrintError(0);
		}
	}
	// 匹配 begin 语句
	else if (!wordTable[wordIndex].compare("begin")) {
		wordIndex++;
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
		sentence();  // 读下一个单词 语句语法判断
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			annotation();
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence();
		}
		else {
			PrintError(0);
			sentence();
		}

		while (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			annotation();
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence();
		}
		// 匹配 end 语句,说明语句判断结束
		if (!wordTable[wordIndex].compare("end")) {
			wordIndex++;
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
		} else {
			PrintError(0);
			return;
		}
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
	}
	// 匹配 换行符
	else if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
	// 匹配 注解
	else if (!wordTable[wordIndex].compare("//") || !wordTable[wordIndex].compare("/*")) {
		annotation();
		subroutine();
	}
	else {
		int tt = 0;
		for (tt = 0; tt < wordTable[wordIndex].length(); tt++) word[tt] = wordTable[wordIndex][tt];
		word[tt] = '\0';
		if (!IsReservedWord(word) && word[0] != '.') {
			id();
			if (!wordTable[wordIndex].compare(":=")) wordIndex++;
			expression();
		}
	}
}
// 注释
void annotation() {
	// 匹配 "\n" 行数加一
	if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
	// 匹配 "//" 为单行注解
	if (!wordTable[wordIndex].compare("//")) {
		wordIndex++;
		wordIndex++;
		while (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
		annotation();
	}
	// 匹配 "/*" 为多行注解
	else if (!wordTable[wordIndex].compare("/*")) {
		wordIndex++;
		while (wordTable[wordIndex].compare("*/")) {
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			else {
				wordIndex++;
			}
		}
		wordIndex++;
	}
	// 一直换行则行数一直加1
	while (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
}
// 条件分析
void condition() {        
	expression(); // 先进行 表达式 判断
	if (!wordTable[wordIndex].compare("=") || !wordTable[wordIndex].compare("#") || !wordTable[wordIndex].compare("<") || !wordTable[wordIndex].compare("<=") || !wordTable[wordIndex].compare(">") || !wordTable[wordIndex].compare(">=")) {
		wordIndex++;
		expression();
	}
	else if (!wordTable[wordIndex].compare("odd")) {
		wordIndex++;
		expression();
	}
	else 
		PrintError(0);
}
// 表达式
void expression() {       
	term(); // 先进行 项 判断
	if (!wordTable[wordIndex].compare("+") || !wordTable[wordIndex].compare("-")) {
		wordIndex++;
		term();
		while (!wordTable[wordIndex].compare("+") || !wordTable[wordIndex].compare("-")) {
			wordIndex++;
			term();
		}

	}
}
// 项
void term() {
	factor();// 先进行 因子 判断
	while (!wordTable[wordIndex].compare("*") || !wordTable[wordIndex].compare("/")) {
		wordIndex++;
		factor();
	}
}
// 因子
void factor() {       
	if (!wordTable[wordIndex].compare("(")) {
		wordIndex++;
		expression();
		if (!wordTable[wordIndex].compare(")")) {
			wordIndex++;
		}
		else PrintError(0);
	}
	else if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
	else wordIndex++;
}
// 数字
void number() {
	wordIndex++;
}
// 标识符
void identifier() {
	wordIndex++;
}


int main() {
	// 程序字符串输入
	charTable[0] = '\0';
	scanf("%[^\.]", charTable); // 读取输入流中的字符,直到遇到第一个句点('.')为止
	charTable[StrLength(charTable)] = '.'; // 在程序字符串结尾添加'.'作为标识符

	// 进行词法分析
	LexicalAnalysis();

	// 进行语法分析
	charIndex = 0;
	wordIndex = 0;
	lineNumber = 1;
	GrammaticalAnalysis();

	return 0;
}

        运行结果如下:

5、扩展

        添加文件输入的功能,程序能够读取指定目录下的源程序字符串txt文件,进行语法分析并将结果输出到指定的文件下。代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include <iostream>
#include <sstream>
using namespace std;

/* ------------ 全局变量声明定义 ------------ */
int lineNumber = 1; // 当前行号

char charTable[2000];				// 字符表 —— 存储输入程序的 所有字符,包括空格、换行等
string wordTable[200] = { "\0" };	// 单词表 —— 存储输入程序的 所有单词,包括换行
char word[88] = "\0";				// 存储单个字符,添加到 wordTable 中

string ENDsign = "end.";	// 结束标识符
int charIndex = 0;			// 记录当前 charTable 字符个数
int wordIndex = 0;			// 记录当前 wordTable 单词个数

char errorMsg[2000] = "";	// 语法错误输出串,用于文件写入
int errorNum = 0;			// 语法错误个数
int errorLine = 0;			// 语法错误行

string reservedWord[20] = { // 保留字
	"begin","call", "const","do","end","if",
	"odd","procedure", "read","then",
	"var","while","write"
};


/* ------------ 函数声明 ------------ */
void LexicalAnalysis();			// 词法分析
void GrammaticalAnalysis();		// 语法分析
void OutputError(int type);		//语法错误输出
int ReadFile(char* path);		// 读取文件
int WriteFile(char* path);		// 写入文件
char* GenerateMessage(int lineNumber);// 生成语法错误字符串

void StrConnect(char* str, char ch);	// 拼接字符串
int StrLength(char* str);				// 计算字符串长度

int IsChar(char ch);			// 判断是否是字符
int IsOperator(char ch);		// 判断是否是运算符
int IsDigit(char ch);			// 判断是否是数字
int IsBoundary(char ch);		// 判断是是否界符
int IsReservedWord(char* str);	// 判断是否是保留字

void ProcessString(char ch);	// 判断字符串是否合法,合法则保存到单词表中
void ProcessNumber(char ch);	// 判断数字串是否合法,合法则保存到单词表中


int id();					// 变量名声明判断
void subroutine();			// 子程序
void constant();			// 常量定义
void variable();			// 变量定义
void sentence();			// 语句分析
void annotation();			// 注释
void condition();			// 条件分析
void expression();			// 表达式
void term();				// 项
void factor();				// 因子
void identifier();			// 标识符
void number();				// 数字


/* ------------ 函数定义 ------------ */
// 词法分析
void LexicalAnalysis() {
	while (charTable[charIndex] != '\0') { // 当前字符表未识别到结束符 '\0'
		if (charTable[charIndex] == '\0')
			break;
		if (charTable[charIndex] == ' ') {
			charIndex++;
			continue;
		}
		if (charTable[charIndex] == '\n') {
			wordTable[wordIndex++] = "\n";  // 将 换行符 保存到单词表 wordTable 中
			charIndex++;
			lineNumber++;	// 程序换行,行数加一
		}
		// 识别到字符
		else if (IsChar(charTable[charIndex])) {
			ProcessString(charTable[charIndex]); // 处理该字符之后的字符串
			continue;
		}
		// 识别到数字
		else if (IsDigit(charTable[charIndex])) {
			ProcessNumber(charTable[charIndex]); // 处理该数字之后的数字串
			continue;
		}
		// 识别到'/' 符
		else if (charTable[charIndex] == '/') {
			// 之后是 '/' ,说明是注释 //
			if (charTable[charIndex + 1] == '/') {
				wordTable[wordIndex++] = "//";
				charIndex = charIndex + 2;
				word[0] = '\0';

				while (charTable[charIndex] != '\n') // 将未换行的字符全部识别为注释
					StrConnect(word, charTable[charIndex++]);
				wordTable[wordIndex++] = word;
				wordTable[wordIndex++] = "\n";
				charIndex++;
				continue;
			}
			// 之后是 '*' ,说明是注释 /*
			else if (charTable[charIndex + 1] == '*') {
				wordTable[wordIndex++] = "/*";
				charIndex = charIndex + 2;
				while (!(charTable[charIndex] == '*' && charTable[charIndex + 1] == '/')) {
					if (charTable[charIndex] == '\n') {
						wordTable[wordIndex++] = "\n";
						charIndex++;
						continue;
					}
					word[0] = '\0';
					while (charTable[charIndex] != '\n') StrConnect(word, charTable[charIndex++]);
					wordTable[wordIndex++] = word;
					wordTable[wordIndex++] = "\n";
					charIndex++;
				}
				wordTable[wordIndex++] = "*/";
				charIndex = charIndex + 2;
				word[0] = '\0';
				continue;
			}
			// 是非法字符(串)
			else {
				while (charTable[charIndex] != ' ' && IsBoundary(charTable[charIndex]) != 1 && charTable[charIndex] != '\0') {
					StrConnect(word, charTable[charIndex]);
					charIndex++;
				}
				printf("(非法字符(串),%s,行号:%d)\n", word, lineNumber);
				word[0] = '\0';
				break;
			}
		}
		// 识别到比较符
		else if (charTable[charIndex] == '<' || charTable[charIndex] == '>') {
			charIndex++;
			// 是 <= 或者 >= 符
			if (charTable[charIndex] == '=') {
				if (charTable[charIndex - 1] == '<')
					wordTable[wordIndex] = "<="; // 保存单词表
				else
					wordTable[wordIndex] = ">="; // 保存单词表
				wordIndex++;
				charIndex++;
				continue;
			}
			// 是 < 或者 > 符
			else {
				if (charTable[charIndex - 1] == '<')
					wordTable[wordIndex] = "<"; // 保存单词表
				else
					wordTable[wordIndex] = ">"; // 保存单词表
				wordIndex++;
				continue;
			}
		}
		// 识别到':'
		else if (charTable[charIndex] == ':') {
			charIndex++;
			if (charTable[charIndex] == '=') {
				wordTable[wordIndex++] = ":="; // 保存单词表
				charIndex++;
				continue;
			}
			else {
				printf(":后面不是=号\n");
				continue;
			}
		}
		// 识别到运算符
		else if (IsOperator(charTable[charIndex])) {
			wordTable[wordIndex++] = charTable[charIndex]; // 保存单词表
			charIndex++;
			continue;
		}
		// 识别到界符
		else if (IsBoundary(charTable[charIndex])) {
			wordTable[wordIndex++] = charTable[charIndex]; // 保存单词表
			charIndex++;
			continue;
		}
		// 识别到非法字符(串)
		else {
			printf("(非法字符(串),%c,行号:%d)\n", charTable[charIndex], lineNumber);
			charIndex++;
		}
	}
}
// 语法分析
void GrammaticalAnalysis() {
	subroutine();
	if (!wordTable[wordIndex].compare(".")) {
		if (errorNum == 0) {
			printf("语法正确\n");
			strcat(errorMsg, "语法正确\n");
		}
			

	}
	else {
		OutputError(0); // 输出语法错误以及行号
		return;
	}
}
// 输出语法错误
void OutputError(int type) {
	if (type == 1) {
		if (errorLine != lineNumber) {
			errorLine = lineNumber;
			printf("(语法错误,行号:%d)\n", lineNumber);
			strcat(errorMsg, GenerateMessage(lineNumber));
			errorNum++;
		}
	}
	else {
		while (wordTable[wordIndex].compare("\n") != 0) 
			wordIndex++;
		if (errorLine != lineNumber) {
			errorLine = lineNumber;
			printf("(语法错误,行号:%d)\n", lineNumber);
			strcat(errorMsg, GenerateMessage(lineNumber));
			errorNum++;
		}
	}
}
// 读取文件
int ReadFile(char* path) {
	FILE* file;
	file = fopen(path, "r");
	if (file == NULL) {
		printf("file is error.");
		return -1;
	}
	int len;
	for (len = 0; len < 2048; len++) {
		fscanf(file, "%c", &charTable[len]);
		if (charTable[len] == '.') {
			len++;
			break;
		}
	}
	charTable[len] = '\0';
	fclose(file);
	return len;
}
// 写入文件
int WriteFile(char* path) {
	FILE* file = NULL;
	file = fopen(path, "w+");
	if (file == NULL) {
		printf("file is error.");
		return -1;
	}
	fputs(errorMsg, file);
	fclose(file);
	return 1;
}
// 生成语法错误字符串
char* GenerateMessage(int lineNumber) {
	char msg[24] = "(语法错误,行号:";
	char endMsg[5] = ")\n";
	char num[5];
	_itoa_s(lineNumber, num, 10);
	strcat(msg, num);
	strcat(msg, endMsg);
	return msg;
}

// 拼接字符串
void StrConnect(char* str, char ch) {        
	int i = 0;
	while (str[i] != '\0') i++;
	str[i] = ch;
	str[i + 1] = '\0';
}
// 计算字符串长度
int StrLength(char* str) {     
	int i = 0;
	while (str[i] != '\0') 
		i++;
	return i;
}

// 判断是否是字符
int IsChar(char ch) {
	if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
		return 1;
	else
		return 0;
}
// 判断是否是运算符
int IsOperator(char ch) {                    
	if (ch == '>' || ch == '<' || ch == '=' || ch == '*' || ch == '-' || ch == '+' || ch == '#')
		return 1;
	else
		return 0;
}
// 判断是否是数字
int IsDigit(char ch) {               
	if ((ch >= '0' && ch <= '9'))
		return 1;
	else
		return 0;
}
// 判断是是否界符
int IsBoundary(char ch) {          
	if (ch == ';' || ch == '.' || ch == ',' || ch == '(' || ch == ')')
		return 1;
	else
		return 0;
}
// 判断是否是保留字
int IsReservedWord(char* str) {          
	for (int i = 0; i < 20; i++) 
		if (reservedWord[i].compare(str) == 0) 
			return 1;
	return 0;
}

// 判断字符串是否合法,合法则保存到单词表中
void ProcessString(char ch) {
	// 字符串 或 数字
	if (IsChar(ch) || IsDigit(ch)) { 
		StrConnect(word, ch);
		charIndex++;
		ProcessString(charTable[charIndex]); //处理下一个字符
	}
	// 运算符或界符等,表示当前单词停止
	else if (ch == ' ' || ch == '\n' || ch == '\0' || IsOperator(ch) || IsBoundary(ch)) {
		// 判断为保留字
		if (IsReservedWord(word)) {
			wordTable[wordIndex++] = word; // 保存到单词表 wordTable 中
			word[0] = '\0';	// word变量初始化
		}
		// 否则判断为标识符
		else {
			if (StrLength(word) >= 8) 
				printf("(标识符长度超长,%s,行号:%d)\n", word, lineNumber);
			else 
				wordTable[wordIndex++] = word; 
			word[0] = '\0';
		}
	}
	// 非法字符(串)
	else {
		StrConnect(word, ch);
		printf("(非法字符(串),%s,行号:%d)\n", word, lineNumber);
		charIndex++;
		word[0] = '\0';
	}
}
// 判断数字串是否合法,合法则保存到单词表中
void ProcessNumber(char ch) {
	// 数字
	if (IsDigit(ch)) {
		StrConnect(word, charTable[charIndex]);
		charIndex++;
		ProcessNumber(charTable[charIndex]);
	}
	// 无符号整数
	else if (!IsChar(ch)) {
		if (StrLength(word) >= 6) 
			printf("(无符号整数越界,%s,行号:%d)\n", word, lineNumber);
		else 
			wordTable[wordIndex++] = word; // 保存到单词表 wordTable 中
		word[0] = '\0';
	}
	// 非法字符(串)
	else {
		while (charTable[charIndex] != ' ' && IsBoundary(charTable[charIndex]) != 1 && charTable[charIndex] != '\0') {
			StrConnect(word, charTable[charIndex]);
			charIndex++;
		}
		printf("(非法字符(串),%s,行号:%d)\n", word, lineNumber);
		word[0] = '\0';
	}
}

// 变量名声明判断
int id() {
	// 拷贝当前读取的单词到word变量中
	int i = 0;
	for (i = 0; i < wordTable[wordIndex].length(); i++) 
		word[i] = wordTable[wordIndex][i];
	word[i] = '\0';
	// 判断该单词不是保留字且不为空
	if (!IsReservedWord(word) && word[0] != '.') {
		wordIndex++;
	}
	else OutputError(1);
}
// 子程序
void subroutine() {
	// 当前单词表匹配 const —— 常量定义
	if (!wordTable[wordIndex].compare("const")) {
		wordIndex++;
		constant();
		// 匹配 "," 说明存在多个变量定义 
		while (!wordTable[wordIndex].compare(",")) {
			wordIndex++;
			constant(); // 处理判断下一个常量
		}
		// 匹配 ";" 说明变量声明结束
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			// 匹配换行符,进入下一行的识别
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++; // 函数加一
				annotation();
			}
			subroutine();
		}
		// 否则出错
		else {
			OutputError(0);
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
				annotation();
			}
			subroutine();
		}
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
			annotation();
		}
	}
	// 当前单词表匹配 var
	else if (!wordTable[wordIndex].compare("var")) {
		wordIndex++;
		variable(); // 读下一个单词,变量 语法判断
		// 匹配 "," 说明有多个变量
		while (!wordTable[wordIndex].compare(",")) {
			wordIndex++;
			variable();
		}
		// 匹配 ";" 说明变量声明结束
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			while (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			annotation();
			subroutine();
		}
		// 否则出错
		else {
			OutputError(0);
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
				annotation();
			}
			subroutine();
		}

	}
	// 当前单词表匹配 procedure
	else if (!wordTable[wordIndex].compare("procedure")) {
		wordIndex++;
		id();
		// 匹配 ";" 说明变量声明结束
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			subroutine();
			if (!wordTable[wordIndex].compare(";")) {
				annotation();
				while (!wordTable[wordIndex].compare("\n")) {
					wordIndex++;
					lineNumber++;
					annotation();
				}
				wordIndex++;
			}
			else {
				OutputError(1);

			}
		} 
		// 否则出错
		else {
			OutputError(0);
			subroutine();
		}
		while (!wordTable[wordIndex].compare("procedure")) {
			wordIndex++;
			id();
			if (!wordTable[wordIndex].compare(";")) {
				wordIndex++;
				subroutine();
				if (!wordTable[wordIndex].compare(";")) wordIndex++;
				else  OutputError(1);
			}
			else {
				OutputError(0);
				subroutine();
			}
		}
	}
	// 当前单词表匹配 换行符
	if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}

	sentence(); // 迭代判断
}
// 常量
void constant() {    
	// 标识符处理判断
	identifier();
	// 匹配等号 = 
	if (!wordTable[wordIndex].compare("=")) {
		wordIndex++;
		number(); // 读入下一个数字进行判断
	}
	// 打印错误
	else OutputError(0);
}
// 变量
void variable() {    
	id();
}
// 语句分析
void sentence() {
	// 匹配 if 语句
	if (!wordTable[wordIndex].compare("if")) {
		wordIndex++;
		condition(); // 读下一个单词,条件 语法判断
		// 条件判断后,匹配 then 语句
		if (!wordTable[wordIndex].compare("then")) {
			wordIndex++;
			// 如果换行,行数加一
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence(); // 读下一个单词,语句 语法判断
		}
		// 不匹配,报错
		else {
			OutputError(0);
			sentence();
		}
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
	}
	// 匹配 while 语句
	else if (!wordTable[wordIndex].compare("while")) {
		wordIndex++;
		condition(); // 读下一个单词,条件 语法判断
		// 条件判断后,匹配 do 语句
		if (!wordTable[wordIndex].compare("do")) {
			wordIndex++;
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence(); // 读下一个单词,语句 语法判断
		}
		// 不匹配,报错
		else {
			OutputError(1);
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence();
		}
	}
	// 匹配 call 语句
	else if (!wordTable[wordIndex].compare("call")) {
		wordIndex++;
		id();
	}
	// 匹配 read 语句
	else if (!wordTable[wordIndex].compare("read")) {
		wordIndex++;
		if (!wordTable[wordIndex].compare("(")) {
			wordIndex++;
			id(); 
			// 匹配 "," 说明有多个变量
			while (!wordTable[wordIndex].compare(",")) {
				wordIndex++;
				id();
			}
			// "(" 匹配 ")" ,结束判断
			if (!wordTable[wordIndex].compare(")")) 
				wordIndex++;
			else  
				OutputError(1);
		}
		else if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
		else  OutputError(0);
	}
	// 匹配 write 语句
	else if (!wordTable[wordIndex].compare("write")) {
		wordIndex++;
		if (!wordTable[wordIndex].compare("(")) {
			wordIndex++;
			expression(); // 读下一个单词 表达式语法判断
			// 匹配 "," 说明有多个表达式
			while (!wordTable[wordIndex].compare(",")) {
				wordIndex++;
				expression();
			}
			// "(" 匹配 ")" ,结束判断
			if (!wordTable[wordIndex].compare(")")) 
				wordIndex++;
			else if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			else OutputError(0);
		}
		else {
			OutputError(1);
			expression();
			while (!wordTable[wordIndex].compare(",")) {
				wordIndex++;
				expression();
			}
			if (!wordTable[wordIndex].compare(")")) wordIndex++;
			else if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			else OutputError(0);
		}
	}
	// 匹配 begin 语句
	else if (!wordTable[wordIndex].compare("begin")) {
		wordIndex++;
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
		sentence();  // 读下一个单词 语句语法判断
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			annotation();
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence();
		}
		else {
			OutputError(0);
			sentence();
		}

		while (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			annotation();
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence();
		}
		// 匹配 end 语句,说明语句判断结束
		if (!wordTable[wordIndex].compare("end")) {
			wordIndex++;
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
		} else {
			OutputError(0);
			return;
		}
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
	}
	// 匹配 换行符
	else if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
	// 匹配 注解
	else if (!wordTable[wordIndex].compare("//") || !wordTable[wordIndex].compare("/*")) {
		annotation();
		subroutine();
	}
	else {
		int tt = 0;
		for (tt = 0; tt < wordTable[wordIndex].length(); tt++) word[tt] = wordTable[wordIndex][tt];
		word[tt] = '\0';
		if (!IsReservedWord(word) && word[0] != '.') {
			id();
			if (!wordTable[wordIndex].compare(":=")) wordIndex++;
			expression();
		}
	}
}
// 注释
void annotation() {
	// 匹配 "\n" 行数加一
	if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
	// 匹配 "//" 为单行注解
	if (!wordTable[wordIndex].compare("//")) {
		wordIndex++;
		wordIndex++;
		while (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
		annotation();
	}
	// 匹配 "/*" 为多行注解
	else if (!wordTable[wordIndex].compare("/*")) {
		wordIndex++;
		while (wordTable[wordIndex].compare("*/")) {
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			else {
				wordIndex++;
			}
		}
		wordIndex++;
	}
	// 一直换行则行数一直加1
	while (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
}
// 条件分析
void condition() {        
	expression(); // 先进行 表达式 判断
	if (!wordTable[wordIndex].compare("=") || !wordTable[wordIndex].compare("#") || !wordTable[wordIndex].compare("<") || !wordTable[wordIndex].compare("<=") || !wordTable[wordIndex].compare(">") || !wordTable[wordIndex].compare(">=")) {
		wordIndex++;
		expression();
	}
	else if (!wordTable[wordIndex].compare("odd")) {
		wordIndex++;
		expression();
	}
	else 
		OutputError(0);
}
// 表达式
void expression() {       
	term(); // 先进行 项 判断
	if (!wordTable[wordIndex].compare("+") || !wordTable[wordIndex].compare("-")) {
		wordIndex++;
		term();
		while (!wordTable[wordIndex].compare("+") || !wordTable[wordIndex].compare("-")) {
			wordIndex++;
			term();
		}

	}
}
// 项
void term() {
	factor();// 先进行 因子 判断
	while (!wordTable[wordIndex].compare("*") || !wordTable[wordIndex].compare("/")) {
		wordIndex++;
		factor();
	}
}
// 因子
void factor() {       
	if (!wordTable[wordIndex].compare("(")) {
		wordIndex++;
		expression();
		if (!wordTable[wordIndex].compare(")")) {
			wordIndex++;
		}
		else OutputError(0);
	}
	else if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
	else wordIndex++;
}
// 数字
void number() {
	wordIndex++;
}
// 标识符
void identifier() {
	wordIndex++;
}



int main() {
	// 程序字符串输入
	char readPath[200];
	char writePath[200];
	printf("输入源程序路径:");
	scanf("%s", readPath);
	printf("输入语法输出文件路径:");
	scanf("%s", writePath);

	if (ReadFile(readPath) != -1) {
		// 进行词法分析
		LexicalAnalysis();

		// 进行语法分析
		charIndex = 0;
		wordIndex = 0;
		lineNumber = 1;
		GrammaticalAnalysis();

		WriteFile(writePath);
	}
	return 0;
}

        指定的文件如下:

         运行结果如下:

       读取源程序文件:

         写入结果文件:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/629439.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

bthclsbthclsbthcls

Sql简单查询 创建数据库/表 进入数据库&#xff1a;mysql -uroot -p123456 支持中文字符&#xff1a; Set character_set_databaseutf8; Set character_set_serverutf8; 1.创建数据库 create database demo; use demo; 2.创建数据表 create table score( id int primar…

Day_48堆排序

目录 一. 关于堆排序 1. 堆的定义 二. 堆排序的实现 1. 堆排序的思路 2. 堆排序的问题分析 3. 堆排序的具体实施 4. 效率分析 三. 堆排序的代码实现 1. 堆排序 2. 调整堆&#xff08;核心代码&#xff09; 四. 代码展示 五. 数据测试 六. 总结 一. 关于堆排序 1. 堆的定义…

Shell脚本学习记录

shell教程 第一个shell脚本 打开文本编辑器(可以使用 vi/vim 命令来创建文件)&#xff0c;新建一个文件 test.sh&#xff0c;扩展名为 sh&#xff08;sh代表shell&#xff09;。 #!/bin/bash echo "Hello World !" #! 是一个约定的标记&#xff0c;它告诉系统这个…

ieda codeformatV2.xml

ieda codeformatV2.xml 目录概述需求&#xff1a; 设计思路实现思路分析1.codeformatV22.codeformatV23.codeformatV24.codeformatV25.数据处理器 拓展实现 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&…

MySQL数据库基础 08

第八章 聚合函数 1. 聚合函数介绍1.1 AVG和SUM函数1.2 MIN和MAX函数1.3 COUNT函数 2. GROUP BY2.1 基本使用2.2 使用多个列分组2.3 GROUP BY中使用WITH ROLLUP 3. HAVING3.1 基本使用3.2 WHERE和HAVING的对比 4. SELECT的执行过程4.1 查询的结构4.2 SELECT执行顺序4.3 SQL 的执…

MT1619

MT1619 是一款PD快充开关电源转换器芯片&#xff0c;其内部集成了一颗高集成度、高性能的电流模式 PWM 控制器和一颗功率 MOSFET。它适用于小于 30W 的开关电源设备。MT1619 具有恒功率功能&#xff0c;特别适用于 PD 充电器、电源适配器等中小功率的开关电源设备。极低的启动电…

[golang 微服务] 5. 微服务服务发现介绍,安装以及consul的使用,Consul集群

一.服务发现介绍 引入 上一节讲解了使用 gRPC创建微服务,客户端的一个接口可能需要调用 N个服务,而不同服务可能存在 不同的服务器,这时&#xff0c;客户端就必须知道所有服务的 网络位置&#xff08;ipport&#xff09;&#xff0c;来进行连接服务器操作,如下图所示: 以往的做…

赋值运算符重载实例:Date类(结尾附源码)

赋值运算符重载实例&#xff1a;Date类 文章目录 赋值运算符重载实例&#xff1a;Date类一、构造日期类二、获取某年某月天数以及检查合法1.获取某年某月天数2.检查日期合法3.打印日期类 三、不同运算符的重载&#xff08;1&#xff09; ; !&#xff08;2&#xff09;> ; &g…

Lecture 13 Formal Language Theory Finite State Automata

目录 什么是语言&#xff1f;Formal Language Theory 形式语言理论动机例子除了从属问题之外的问题Regular Languages 正则语言Finite State Acceptor 正则语言的性质Derivational MorphologyWeighted FSAFinite State Transducer (FST)FST for Inflectional MorphologyNon-Reg…

Java Web实现用户登录功能

文章目录 一、纯JSP方式实现用户登录功能&#xff08;一&#xff09;实现思路1、创建Web项目2、创建登录页面3、创建登录处理页面4、创建登录成功页面5、创建登录失败页面6、编辑项目首页 &#xff08;三&#xff09;测试结果 二、JSPServlet方式实现用户登录功能&#xff08;一…

软考A计划-系统架构师-官方考试指定教程-(11/15)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

第四十周周报

学习目标&#xff1a; 一、Stable Diffusion 论文 学习时间&#xff1a; 2023.6.3-2023.6.9 学习产出&#xff1a; 一、模型进展 相比前两周的结果&#xff0c;本周改进了一下参数&#xff0c;FID达到了9 前两周结果为10.258 本周相比前两周FID降低1 二、High-Resolu…

数据结构之树与二叉树——算法与数据结构入门笔记(五)

本文是算法与数据结构的学习笔记第五篇&#xff0c;将持续更新&#xff0c;欢迎小伙伴们阅读学习。有不懂的或错误的地方&#xff0c;欢迎交流 引言 前面章节介绍的都是线性存储的数据结构&#xff0c;包括数组、链表、栈、队列。本节带大家学习一种非线性存储的数据结构&…

【MySQL】- 05 sql 语句练习题

sql 语句练习题 一 测试数据的准备二、数据查询1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数3、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩4、…

MySQL数据库基础 06

第六章 多表查询 1. 一个案例引发的多表连接1.1 案例说明1.2 笛卡尔积&#xff08;或交叉连接&#xff09;的理解1.3 案例分析与问题解决 2. 多表查询分类讲解分类1&#xff1a;等值连接 vs 非等值连接等值连接非等值连接 分类2&#xff1a;自连接 vs 非自连接分类3&#xff1a…

动态网站开发02:Java Web概述

文章目录 一、 XML基础&#xff08;一&#xff09;XML概述1、XML2、XML与HTML的比较 &#xff08;二&#xff09;XML语法1、XML文档的声明2、XML元素的定义3、XML属性的定义4、XML注释的定义5、XML文件示例 &#xff08;三&#xff09;DTD约束1、什么是XML约束2、什么是DTD约束…

MM32F3273G8P火龙果开发板MindSDK开发教程5 - Gcc编译环境的配置

MM32F3273G8P火龙果开发板MindSDK开发教程5 - Gcc编译环境的配置 1、准备工作 用了几天Keil后&#xff0c;实在用不习惯&#xff0c;只好回到macos系统中来搭建gcc的编译环境。但是百问网火龙果开发板自带的DAP-Link在pyocd中根本识别不到&#xff0c;所以烧录还需要重新购置…

MySQL数据库基础 07

第七章 单行函数 1. 函数的理解1.1 什么是函数1.2 不同DBMS函数的差异1.3 MySQL的内置函数及分类 2. 数值函数2.1 基本函数2.2 角度与弧度互换函数2.3 三角函数2.4 指数与对数2.5 进制间的转换 3. 字符串函数4. 日期和时间函数4.1 获取日期、时间 4.2 日期与时间戳的转换 4.3 获…

一个关于宏定义的问题,我和ChatGPT、NewBing、Google Bard、文心一言 居然全军覆没?

文章目录 一、问题重述二、AI 解题2.1 ChatGPT2.2 NewBing2.3 Google Bard2.4 文心一言2.5 小结 一、问题重述 今天在问答模块回答了一道问题&#xff0c;要睡觉的时候&#xff0c;又去看了一眼&#xff0c;发现回答错了。 问题描述&#xff1a;下面的z的值是多少。 #define…

【Redis】Redis持久化机制RDB与AOF

目录 一、RDB 1、概念 2、RDB文件保存 3、执行RDB 4、触发RDB 5、fork原理 6、RDB的缺点 二、AOF 1、概念 2、开启AOF 3、触发AOF 4、触发重写AOF 三、区别 一、RDB 1、概念 RDB全称为Redis Database Backup File&#xff08;Redis数据备份文件&#xff09;&…