HUST编译原理实验2

news2025/1/9 1:55:53

语法分析,建立并显示语法树

以识别 a = 10.01; 为例,阐述语法分析的构造过程

1. 建立AST储存结构

由a = 10.01得知,语法构成为:

SentenceList->Sentence->Exp SEMI->ID ASSIGNOP FLOAT SEMI

因此,需要储存结构如下

typedef struct ASTNode {
	int kind;						//保存结点类型
	union {
		 char type_id[33];        //由标识符生成的叶结点
		 int type_int;            //由整常数生成的叶结点
		 float type_float;        //由浮点常数生成的叶结点
	};
    union {//第1指针域
        struct ASTNode *Sentence;		//句子
	 	struct ASTNode *Exp1;		  //表达式1
        struct ASTNode *ID;         //标识符
    };
    union {//第2指针域
        struct ASTNode *SentenceList;	//句子集
        struct ASTNode *Exp2;       //表达式2
    };
    int type;                       //用以标识表达式结点的类型
    int pos;                        //语法单位所在位置行号
} ASTNode;

2. 设定标识符

1)在parser.y文件中设定定义的词法类型

%union {
	int    type_int;
	float  type_float;
	char   type_id[32];
	struct ASTNode *ptr;
};

2)定义符号类型

将非终结符定义为ASTNode类型

Program ->SentenceList->Sentence->Exp SEMI->ID ASSIGNOP FLOAT SEMI
中得知

%type  <ptr>  program SentenceList Sentence Exp  

将终结符定义为语义值类型

%token <type_id> ID     			/*指定ID的语义值是type_id*/
%token <type_float> FLOAT          /*指定FLOAT的语义值是type_float*/

定义enum型标识符:

符号标识符有SEMI ASSIGNOP
识别标识符(用于识别该文法类型)有SentenceList_ Sentence_

%token SentenceList_ Sentence_ SEMI ASSIGNOP

3.词法分析:标识符,=,Float,SEMI

1)Test.l文件中的一些设定:

%option yylineno. //行号自动加1

2)识别

定义段:

		id   [A-Za-z][A-Za-z0-9]*  
		floatconst  [0-9]*\.?[0-9]*

规则段:

%%

"="			{strcpy(yylval.type_id, yytext);return ASSIGNOP;}
{id}        {strcpy(yylval.type_id,  yytext); return ID;}
";"		  {return SEMI;}
{floatconst}  {yylval.type_float=atof(yytext); return FLOAT;}




[ \r\t]   {}   
[\n]    {}   
.		{printf("Error type A :Mysterious character \"%s\"\n\t at Line %d\n",yytext,yylineno);}
%%

4.语法分析

注:program SentenceList Sentence Exp的类型为struct ASTNode *
在使用时,可用$$=(ASTNode *)malloc(sizeof(ASTNode));创建内存。
使用$$->kind,$$->Sentence创造节点属性。

program: SentenceList { display($1,0);};      //显示语法树,语义分析

SentenceList:	{$$=NULL;} 
	|	Sentence SentenceList {
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = SentenceList_;
			$$->pos=yylineno;
			$$->Sentence=$1;
			$$->SentenceList=$2;
		}
	;
Sentence:	Exp  SEMI{
			//表达式
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = Sentence_;
			$$->pos=yylineno;
			$$->Exp1=$1;
		}
 			;
		Exp  :		Exp ASSIGNOP Exp{
					$$=(ASTNode *)malloc(sizeof(ASTNode));
					$$->kind = ASSIGNOP;
					$$->pos=yylineno;
					$$->Exp1=$1;
					$$->Exp2=$3;
					strcpy($$->type_id,"=");
				}
			|		ID{
					$$=(ASTNode *)malloc(sizeof(ASTNode)); 
					$$->kind=ID;
$$->pos=yylineno;  
					strcpy($$->type_id,$1);
				}
			|	FLOAT{
					$$=(ASTNode *)malloc(sizeof(ASTNode)); 
					$$->kind=FLOAT;
$$->pos=yylineno; 
					$$->type=FLOAT; 
					$$->type_float=$1;
				}

Main函数:

int main(int argc, char *argv[]){
	yyin=fopen(argv[1],"r");
	if (!yyin) return 0;
	yylineno=1;
	yyparse();
	return 0;
	}
#include<stdarg.h>
void yyerror(const char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    fprintf(stderr, "Grammar Error at Line %d Column %d: ", yylloc.first_line,yylloc.first_column);
    vfprintf(stderr, fmt, ap);
    fprintf(stderr, ".\n");
}

5.显示语法树

void display(struct ASTNode *T,int indent)
{//对抽象语法树的先根遍历
  int i=1;
  struct ASTNode *T0;

  	if (T)
{
		switch (T->kind) {
		case SentenceList_: 
			display(T->Sentence, indent);
			display(T->SentenceList, indent);
			break;
		case Sentence_:
			printf_(indent);
			printf("表达式语句:");
			display(T->Exp1, indent + 4);
			break;
		case ID:
			printf_(indent);
			printf("变量:%s",T->type_id);
			break;
		case FLOAT:
			printf_(indent);
			printf("浮点常量:%.6f",T->type_float);
			break;
		case ASSIGNOP:
			printf_(indent);
        	printf("%s",T->type_id);
        	display(T->Exp1,indent+4);
        	display(T->Exp2,indent+4);
        	break;
       }
    }
}

6.在此基础上按照1~5的步骤添加其他语法

IF LP Exp RP Sentence ELSE Sentence
WHILE LP Exp RP LC SentenceList RC
SCAN ID SEMI
PRINT Exp SEMI

7.编译运行

使用bat语言进行命令行输入,代码文件名为lex.lparser.y,生成文件parser.exe

@echo on
flex lex.l
bison -d parser.y
gcc -o parser  lex.yy.c parser.tab.c ast.c

实现编译,编译文件为test.c.

parser test.c

完整代码

lex.l

%option  yylineno
%{
#include "parser.tab.h"
#include "string.h"
#include "def.h"

int yycolumn=1;


int lastToken;

%}

id   [A-Za-z][A-Za-z0-9]*  
intconst    [0-9]+
floatconst  [0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?

%%
"int"       {strcpy(yylval.type_id,  yytext);return TYPE;}
"float"     {strcpy(yylval.type_id,  yytext);return TYPE;}

"return"   {return RETURN;}
"if"        	{return IF;}
"else"      	{return ELSE;}
"while"   	{return WHILE;}
"for"       	{return FOR;}
"scan"	{return SCAN;}
"print"	{return PRINT;}



{id}        {strcpy(yylval.type_id,  yytext); return ID;}
";"		  {return SEMI;}
","		  {return COMMA;}
">"|"<"|">="|"<="|"=="|"!=" {strcpy(yylval.type_id, yytext);return RELOP;}
"="			{strcpy(yylval.type_id, yytext);return ASSIGNOP;}
"++"			{strcpy(yylval.type_id, yytext);return DPLUS;}
"+"			{strcpy(yylval.type_id, yytext);return PLUS;}
"-"			{strcpy(yylval.type_id, yytext);return MINUS;}
"*"			{strcpy(yylval.type_id, yytext);return STAR;}
"/"			{strcpy(yylval.type_id, yytext);return DIV;}
"&&"         {return AND;}
"||"           {return OR;}
"!"			{return NOT;}
"("			{return LP;}
")"			{return RP;}
"{"			{return LC;}
"}"			{return RC;}
{intconst}      {yylval.type_int=atoi(yytext); return INT;}
{floatconst}     {yylval.type_float=atof(yytext);     return FLOAT;}
[ \r\t]     {}   

[\n]            {yycolumn=1;}   
.			{printf("Error type A :Mysterious character \"%s\"\n\t at Line %d\n",yytext,yylineno);}

%%

int yywrap()
{
return 1;
}

parser.y

%error-verbose
%locations
%{
#include "stdio.h"
#include "math.h"
#include "string.h"
#include "def.h"
extern int yylineno;
extern char *yytext;
extern FILE *yyin;
void yyerror(const char* fmt, ...);
void display(struct ASTNode *,int);
int yylex();
%}


%union {
	int    type_int;
	float  type_float;
	char   type_id[32];
	struct ASTNode *ptr;
};


//  %type 定义非终结符的语义值类型
%type  <ptr>  program SentenceList Sentence Exp  

//% token 定义终结符的语义值类型
%token <type_int> INT              /*指定INT的语义值是type_int,有词法分析得到的数值*/
%token <type_id> ID  RELOP TYPE    /*指定ID,RELOP 的语义值是type_id,有词法分析得到的标识符字符串*/



%token <type_float> FLOAT          /*指定ID的语义值是type_id,有词法分析得到的标识符字符串*/
    
//GE GT LE LT NE LB RB 
%token DPLUS  LP RP  LC RC SEMI  COMMA    /*用bison对该文件编译时,带参数-d,生成的exp.tab.h中给这些单词进行编码,可在lex.l中包含parser.tab.h使用这些单词种类码*/
%token SCAN PRINT PLUS MINUS STAR DIV  ASSIGNOP AND OR NOT IF ELSE WHILE RETURN STRUCT FOR SWITCH CASE COLON DEFAULT 
/*以下为接在上述token后依次编码的枚举常量,作为AST结点类型标记*/
%token SentenceList_ Sentence_  IF_ELSE UMINUS 
//%token FUNC_CALL ARGS FUNCTION PARAM ARG CALL LABEL GOTO JLT JLE JGT JGE EQ NEQ


%left ASSIGNOP
%left OR
%left AND
%left RELOP
%left PLUS MINUS
%left STAR DIV
%right UMINUS NOT DPLUS

%nonassoc ELSE


%%

program: SentenceList { display($1,0);};      //显示语法树,语义分析
         
SentenceList:	{$$=NULL;} 
	|	Sentence SentenceList {
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = SentenceList_;
			$$->pos=yylineno;
			$$->Sentence=$1;
			$$->SentenceList=$2;
			//printf("SentenceList:	 ->Sentence SentenceList\n");
		}
	;
Sentence:	Exp  SEMI{
			//表达式
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = Sentence_;
			$$->pos=yylineno;
			$$->Exp1=$1;
			//printf("Sentence:	 ->Exp  SEMI\n");
		}
	|	SCAN ID SEMI{
			//scan输入
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = SCAN;
			$$->pos=yylineno;
			strcpy($$->type_id,$2);
			//printf("Sentence:->SCAN ID\n");
		}
	|	PRINT Exp SEMI{
			//print输出
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = PRINT;
			$$->pos=yylineno;
			$$->ID = $2;
			//printf("Sentence:->PRINT  ID\n");
		}
	|	IF LP Exp RP Sentence ELSE Sentence{
			//if-else语句
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = IF_ELSE;
			$$->pos=yylineno;
			$$->Exp1 = $3;
			$$->SentenceIF = $5;
			$$->SentenceElse = $7;
			//printf("Sentence:->IF LP Exp RP SentenceList ELSE SentenceList\n");
		}
	|	WHILE LP Exp RP LC SentenceList RC{
			//While语句
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = WHILE;
			$$->pos=yylineno;
			$$->Exp1 = $3;
			$$->SentenceListWhile= $6;
		}
	;
Exp  :		Exp ASSIGNOP Exp{
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = ASSIGNOP;
			$$->pos=yylineno;
			$$->Exp1=$1;
			$$->Exp2=$3;
			strcpy($$->type_id,"=");
			//printf("Exp = Exp \n");
		}
	|	MINUS Exp %prec UMINUS{
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = UMINUS;
			$$->pos=yylineno;
			$$->Exp1=$2;
			strcpy($$->type_id,"-");
			//printf("-Exp \n");
		}
	|	LP Exp RP{
			$$=$2;
			//printf("(Exp) \n");
		}
	|	Exp RELOP Exp{
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = RELOP;
			$$->pos=yylineno;
			$$->Exp1=$1;
			$$->Exp2=$3;
			strcpy($$->type_id,$2);
			//printf("Exp %s Exp\n",$2);
		}
	|	Exp MINUS Exp{
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = MINUS; 
			$$->pos=yylineno;
			$$->Exp1=$1;
			$$->Exp2=$3;
			strcpy($$->type_id,"-");
			//printf("Exp - Exp\n");
		}
	|	Exp PLUS Exp{
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = PLUS; 
			$$->pos=yylineno;
			$$->Exp1=$1;
			$$->Exp2=$3;
			strcpy($$->type_id,"+");
			//printf("Exp + Exp\n");
		}
	|	Exp STAR Exp{
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = STAR; 
			$$->pos=yylineno;
			$$->Exp1=$1;
			$$->Exp2=$3;
			strcpy($$->type_id,"*");
			//printf("Exp * Exp\n");
		}
	|	Exp DIV Exp{
			$$=(ASTNode *)malloc(sizeof(ASTNode));
			$$->kind = DIV; 
			$$->pos=yylineno;
			$$->Exp1=$1;
			$$->Exp2=$3;
			strcpy($$->type_id,"/");
			//printf("Exp / Exp\n");
		}
	|	ID{
			$$=(ASTNode *)malloc(sizeof(ASTNode)); 
			$$->kind=ID;
                               		$$->pos=yylineno;  
			strcpy($$->type_id,$1);
			//printf("Exp :->ID,ID = %s\n",$1);
		}
	|	FLOAT{
			$$=(ASTNode *)malloc(sizeof(ASTNode)); 
			$$->kind=FLOAT;
                               		$$->pos=yylineno; 
			$$->type=FLOAT; 
			$$->type_float=$1;
			//printf("FLOAT = %f\n",$1);
		}
	|	INT{
			$$=(ASTNode *)malloc(sizeof(ASTNode)); 
			$$->kind=INT;
                               		$$->pos=yylineno; 
			$$->type=INT; 
			$$->type_int=$1;
			//printf("INT = %d\n",$1);
		}
	;
%%

int main(int argc, char *argv[]){
	yyin=fopen(argv[1],"r");
	if (!yyin) return 0;
	yylineno=1;
	yyparse();
	return 0;
	}
#include<stdarg.h>
void yyerror(const char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    fprintf(stderr, "Grammar Error at Line %d Column %d: ", yylloc.first_line,yylloc.first_column);
    vfprintf(stderr, fmt, ap);
    fprintf(stderr, ".\n");
}

def.h

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "stdarg.h"
#include "parser.tab.h"

typedef struct ASTNode {
        //以下对结点属性定义没有考虑存储效率,只是简单地列出要用到的一些属性
	int kind;
	union {
		 char type_id[33];        //由标识符生成的叶结点
		 int type_int;            //由整常数生成的叶结点
		 float type_float;        //由浮点常数生成的叶结点
	};
    union {//第1指针域
        struct ASTNode *Sentence;
	 	struct ASTNode *Exp1;
        struct ASTNode *ID;         //标识符
    };
    union {//第2指针域
        struct ASTNode *SentenceList;
        struct ASTNode *Exp2;       //表达式2
        struct ASTNode *SentenceIF;
        struct ASTNode *SentenceListWhile;
    };
    union {//第3指针域
        struct ASTNode* SentenceElse;
    };
    int type;                       //用以标识表达式结点的类型
    int pos;                        //语法单位所在位置行号

} ASTNode;


ast.c

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "def.h"
#include "parser.tab.h"

int Enter = 0;

void printf_(int indent) {
	if (Enter == 1) {
		printf("\n");
	}
	else {
		Enter = 1;
	}
	if (indent != 0) {
		printf("%*c", indent, ' ');
	}
}

void display(struct ASTNode *T,int indent)
{//对抽象语法树的先根遍历
  int i=1;
  struct ASTNode *T0;

  if (T)
	{
	switch (T->kind) {
	case SentenceList_: 
		display(T->Sentence, indent);
		display(T->SentenceList, indent);
		break;
	case Sentence_:
		printf_(indent);
		printf("表达式语句:");
		display(T->Exp1, indent + 4);
		break;
	case ID:
		printf_(indent);
		printf("变量:%s",T->type_id);
		break;
	case INT:
		printf_(indent);
		printf("整型常量:%d",T->type_int);
		break;
	case FLOAT:
		printf_(indent);
		printf("浮点常量:%.6f",T->type_float);
		break;
	case ASSIGNOP:
	case AND:
	case OR:
	case RELOP:
	case PLUS:
	case MINUS:
	case STAR:
	case DIV:
		printf_(indent);
        printf("%s",T->type_id);
        display(T->Exp1,indent+4);
        display(T->Exp2,indent+4);
        break;
	case UMINUS:
		printf_(indent);
		printf("单目%s", T->type_id);
		display(T->Exp1, indent + 4);
		break;
	case SCAN:
		printf_(indent);
		printf("输入变量:%s", T->type_id);
		break;
	case PRINT:
		printf_(indent);
		printf("输出表达式:");
		display(T->ID, indent + 4);
		break;
	case IF_ELSE:
		printf_(indent);
		printf("条件语句(if_then_else):");
		printf_(indent+4);
		printf("条件:");
		display(T->Exp1, indent + 8);
		printf_(indent+4);
		printf("if子句:");
		display(T->SentenceIF, indent + 8);
		printf_(indent+4);
		printf("else子句:");
		display(T->SentenceElse, indent + 8);
		break;
	case WHILE:
		printf_(indent);
		printf("循环语句:");
		printf_(indent + 4);
		printf("条件:");
		display(T->Exp1, indent + 8);
		printf_(indent + 4);
		printf("循环体:");
		display(T->SentenceListWhile, indent + 8);
		break;
	}
  }
}

测试文件test.c

a = 10.1;
scan b;
if (a > b)
max = a;
else max = b;
print max;

i = 1;
sum = 0;
while (i <= 10)
{
	sum = sum + i;
	i = i + 1;
}
print sum;

a = (1 + 3) * 2 / -(13.56 - 5) > 100 == 1;

test.bat

@echo on
flex lex.l
bison -d parser.y
gcc -o parser  lex.yy.c parser.tab.c ast.c 

运行结果

在这里插入图片描述
在这里插入图片描述
编译成功
在这里插入图片描述
在这里插入图片描述
运行成功

实验总结:

熟悉了flex、bison的使用,联合使用,以及和其他文件(.c)的联合使用,学会了创建语法树,实现语法树的显示输出。

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

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

相关文章

Java数据结构与Java算法学习Day10---图的了解和无向图(简略笔记记录)

目录 1.1图的定义及分类 142 1.2无向图 143 1.2.1图的相关术语 143 1.2.2无向图的存储结构 144 1.3图的API设计 145 1.4图的搜索 146 1.4.1深度优先搜索 146 1.4.2深度优先搜索API设计 147 1.5广度优先搜素 149 1.5.1广度优先搜索API设计及代码实现 150 1.5.2广度…

QT 系统学习 day04 事件(鼠标,键盘), UDP 通信, TCP 通信,多个定时器,重写绘画事件

1. 事件 (有 键盘按下&#xff0c; 鼠标按下&#xff0c; 鼠标双击等) 1.重写键盘按下事件&#xff0c; 函数&#xff1a; void keyPressEvent(QKeyEvent *event) /*** 按键按下事件 ***/ 代码&#xff1a; void keyPressEvent(QKeyEvent *event) /*** 按键按下事件 ***/{q…

【吴恩达机器学习笔记】十五、大规模机器学习

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为学习吴恩达机器学习视频的同学提供的随堂笔记。 &#x1f4da;专栏简介&#xff1a;在这个专栏&#xff0c;我将整理吴恩达机器学习视频的所有内容的笔记&…

低代码开发平台——体验系统的重要性

什么是优秀的体验&#xff1f; 简而言之&#xff0c;优质的体验意味着可以随时随地根据客户的需求提供服务&#xff0c;这在数字化的世界中&#xff0c;意味着真正的多重体验。Gartner早在2018年就定义了MXDP&#xff08;多体验开发平台&#xff09;&#xff0c;以应对我们日常…

游戏开发38课 unity 模板测试

ShaderLab 命令&#xff1a;模板 配置与 GPU 上的模板缓冲区相关的设置。 模板缓冲区为帧缓冲区中的每个像素存储一个 8 位整数值。为给定像素执行片元着色器之前&#xff0c;GPU 可以将模板缓冲区中的当前值与给定参考值进行比较。这称为模板测试。如果模板测试通过&#xff…

liunx如何重启mysql

Linux如何重启MySQL Linux中重启MySQL可以使用service mysql restart命令和脚本启动方式/etc/inint.d/mysql restart。 推荐&#xff1a;MySQL教程 其他命令如下&#xff1a; 一、 启动 1、使用 service 启动&#xff1a;service mysql start 2、使用 mysqld 脚本启动&am…

使用redis做分布式锁

思路步骤 获取锁, 使用 SETNX 命令设置一个key.如果没获取到&#xff0c;从新拿锁&#xff0c;返回步骤1 ; 从新拿锁可以设置等待时间;也可以记录拿锁次数为了做“避免死循环”.如果获取到&#xff0c;使用 EXPIRE 给锁加存活时间&#xff1b;接步骤3&#xff0c;执行业务&…

微机----------------中断控制器8259A(可编程的中断控制器)

目录 功能8259A的引脚8259A的工作方式中断响应顺序8259A的中断优先级管理8259A中断屏蔽管理⭐8259A的中断结束管理功能 ①单片825能管理8级中断,并且可级联管理64级 ②可对任一级中断单独屏蔽或允许 ③中断被响应后,可直接提供中断类型号 ④可通过编程选择其工作方式 IRR中断…

C++入门篇

入门C命名空间命名空间定义命名空间的使用C输入&#xff0c;输出缺省参数缺省参数概念缺省参数分类函数重载函数重载概念C支持函数重载的原因引用引用概念引用特性具体应用const修饰的常量进行引用&#xff08;常引用&#xff09;传值&#xff0c;传引用的效率引用和指针的区别…

【无标题】3 GENERIC语句 和 INTEGER类型

【VHDL】【作业】3 GENERIC语句 和 INTEGER类型 文章目录【VHDL】【作业】3 GENERIC语句 和 INTEGER类型前言什么是GENERIC语句&#xff1f;32位加法器仿真波形总结每天进步一点点 笔记仅供自学&#xff0c;用来回看复习&#xff0c;不一定适合你&#xff0c;如有错误请指出。前…

SpringBoot:概述

Spring Boot 是 Spring 开源组织下的子项目&#xff0c;是 Spring 组件一站式解决方案&#xff0c;主要是简化了使用 Spring 的难度&#xff0c;简省了繁重的配置&#xff0c;提供了各种启动器&#xff0c;开发者能快速上手。 &#xff5e; 本篇内容包括&#xff1a;Spring Boo…

[选型] 实时数仓之技术选型

数仓技术路线选型 对于已有的hive数据仓&#xff0c;怎样改造成实时数仓的要求呢&#xff1f; 2.关于实时数仓的选型 如果选择hbase&#xff0c;建议选择kudu 如果选择kudu, 还可以选择doris 如果选择doris&#xff0c;建议选择iceberg 以上三种选择&#xff0c;要配合具体…

C++实现身份证号码过滤与排序

1.描述 警察办案里检索到一批(n个)身份证号码&#xff0c;希望按出生日期对它们进行从大到小排序&#xff0c;如果有相同日期&#xff0c;则按身份证号码大小进行排序&#xff0c;如果是错误的身份证号&#xff0c;则从排序列表中删除(仅需判断前两位省级地区编码是否在下面的…

知识图谱-KGE-语义匹配-双线性模型-2016:NAM

【paper】 Probabilistic Reasoning via Deep Learning: Neural Association Models【简介】 本文是中科大和科大讯飞联合发表在 IJCAI 2016 上的工作&#xff0c;本文提出了 NAM&#xff08;Neural Association Model&#xff09;用于概率推理&#xff0c;并具体化为 DNN&…

十二月7号

一、uboot概念 1.1 uboot和bootloader关系 1.bootloader:是一系列引导加载程序的统称 boot:引导 loader&#xff1a;加载 2.uboot是引导加载程序中的一种 1.2 uboot特点 1.uboot是由德国DNEX小组进行维护的 2.uboot是一个开源分布式系统 3.uboot支持多种硬件架构平台(ARM/X8…

Blazor 部署 pdf.js 不能正确显示中文资源解决办法

原文链接 [https://www.cnblogs.com/densen2014/p/16964858.html] 在Blazor项目嵌入 pdf.js 时不能正确显示中文,浏览器F12显示如下错误 错误 l10n.js /web/locale/locale.properties not found. 我找到了解决方案。它不仅消除了上面提到的错误&#xff08;即 404 - locale.p…

nextjs13 webpack5 使用wasm报错

问题描述&#xff1a; 在next 13, webpack 5, react 18的项目中使用Rust编写的wasm报错&#xff1a; ./node_modules/image-map-path/image_map_path_bg.wasm Module parse failed: Unexpected character (1:0) The module seem to be a WebAssembly module, but module is n…

freemarker

文章目录创建项目引入依赖创建配置文件创建启动类和测试类语法listMapif运算符处理空值使用??指定缺失变量默认值内建函数集合长度数据类型布尔值时间类型数值类型字符串类型sequence序列类型hash类型常见指令assign自定义变量指令json转成对象实例list通过下标取值map取值通…

「Redis数据结构」集合对象(Set)

「Redis数据结构」集合对象&#xff08;Set&#xff09; 文章目录「Redis数据结构」集合对象&#xff08;Set&#xff09;一、概述二、结构三、编码转换四、小结一、概述 Set是Redis中的单列集合&#xff0c;其特点为不保证有序性、保证元素唯一、可以求交集、并集、差集。 从…

Python入门自学进阶-Web框架——28、DjangoAdmin项目应用-只读字段与后端表单验证

有时候&#xff0c;记录的某些字段在生成后就不允许再修改了&#xff0c;这时前端只能显示&#xff0c;不能修改。这时&#xff0c;可在AdminClass中进行设置&#xff1a;readonly_fields[字段名&#xff0c;字段名&#xff0c;。。。]&#xff0c;前端格式就显示成只显示不能修…