posgreSQL源码分析:语法分析 gram.y

基础知识

首先 gram语法分析在pg中是配合词法解析的

在生成文件中 gram.y -> gram.c
存在一个栈 进行移进 规约 shift/reduce
使用lex 读取一个 一个关键字 入栈 这个过程叫移进过程,当发现有token可以进行规约 reduce的时候会把token出栈 换成规约后的标识符 重新入栈。
一般来说:已经在gram.y中定义的 token reduce可能少,除非到了语法最后步骤。常见的过程中 规约的 一般是 标识符.
像语句 CREATE TABLE t(a int);
一般来讲 CREATE TABLE 不会产生reduce 当我们读到 “t” 这个字符的时候 由于 gram.y含有该语法 ,假如他的定义是这样:

CREATE TABLE table_name …
{
}
table_name:
IDENT { $$=$1}
当 lex 读取到 “t”的时候 就会识别成 IDENT ,后续去gram.y一搜索 发现 IDENT 可以规约成 table_name 所以规约就产生了,以此类推。。。

对于gram.y的定义,常用的 (详细的学习请搜索bison语法或者yacc语法等等,这里只基于pg源码 说常用的 便于你快速阅读pg):

第一段:

(截取了部分):一般用来定义一些用到的 常量 结构体 还有 引入.h文件 即inclue。
%{

#include “postgres.h”

#include <ctype.h>
#include <limits.h>

#include “access/tableam.h”
#include “catalog/index.h”
#include “catalog/namespace.h”
#include “catalog/pg_am.h”

#define YYLLOC_DEFAULT(Current, Rhs, N)
do {
if ((N) > 0)
(Current) = (Rhs)[1];
else
(Current) = (-1);
} while (0)

#define YYMALLOC palloc
#define YYFREE pfree

/* Private struct for the result of import_qualification production */
typedef struct ImportQual
{
ImportForeignSchemaType type;
List *table_names;
} ImportQual;

/* Private struct for the result of opt_select_limit production */
typedef struct SelectLimit
{
Node *limitOffset;
Node *limitCount;
LimitOption limitOption;
} SelectLimit;

/* ConstraintAttributeSpec yields an integer bitmask of these flags: */
#define CAS_NOT_DEFERRABLE 0x01
#define CAS_DEFERRABLE 0x02
#define CAS_INITIALLY_IMMEDIATE 0x04
#define CAS_INITIALLY_DEFERRED 0x08

%}

第二段

1 开始定义我们的type

即一个语句的标签 像什么 createTableStmt 这种;
代表一个类型,假如如上举例,那么table_name 你就可以定义成:
%type 《str》 table_name
即可以认为 我需要传入一个字符串 这里看你想以什么类型传入。

%type stmt toplevel_stmt schema_stmt routine_body_stmt
AlterEventTrigStmt AlterCollationStmt
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
AlterObjectDependsStmt AlterObjectSchemaStmt AlterOwnerStmt
AlterOperatorStmt AlterTypeStmt AlterSeqStmt AlterSystemStmt AlterTableStmt
AlterTblSpcStmt AlterExtensionStmt AlterExtensionContentsStmt
AlterCompositeTypeStmt AlterUserMappingStmt

2 定义token 即关键字

这里就是可以定义我们所需的token,像 CREATE TABLE 都需要定义 且要按照 字母顺序排序
/* Begin - BUG:M0000079 /
%token MODE_PLISQL_EXPR
%token MODE_PLISQL_ASSIGN1
%token MODE_PLISQL_ASSIGN2
%token MODE_PLISQL_ASSIGN3
/
End - BUG:M0000079 */

3 这里是定义一些 优先级 或者 < > 类似的定义 运算优先级定义

/* Precedence: lowest to highest /
%nonassoc SET /
see relation_expr_opt_alias /
%left UNION EXCEPT
%left INTERSECT
%left OR
%left AND
%right NOT
%nonassoc IS ISNULL NOTNULL /
IS sets precedence for IS NULL, etc */
%nonassoc ‘<’ ‘>’ ‘=’ LESS_EQUALS GREATER_EQUALS NOT_EQUALS
%nonassoc BETWEEN IN_P LIKE ILIKE SIMILAR NOT_LA

4 规则段

这里开始正式写语法,像函数的互相调用一样 语法中 会包含一些其他语法:
例如:
1 CreateRoleStmt 语法中包含了OptRoleList
2 而OptRoleList 又包含了自己的语法内容
3 在OptRoleList中 包含的 CreateOptRoleElem
4 CreateOptRoleElem 又包含了自己的语法内容 如下所示:
(这里我把他们拼接到一起了 ,在源码中 大多下级标签有很多语法共用,不一定会写在一起。)
CreateRoleStmt:
CREATE ROLE RoleId opt_with OptRoleList
{
CreateRoleStmt *n = makeNode(CreateRoleStmt);
n->stmt_type = ROLESTMT_ROLE;
n->role = $3;
n->options = $5;
$$ = (Node *)n;
}
;

OptRoleList:
OptRoleList CreateOptRoleElem { KaTeX parse error: Can't use function '$' in math mode at position 12: = lappend($̲1, $2); } | … = NIL; }
;


CreateOptRoleElem:
AlterOptRoleElem { KaTeX parse error: Can't use function '$' in math mode at position 4: = $̲1; } /* The … = makeDefElem(“sysid”, (Node *)makeInteger($2), @1);
}
| ADMIN role_list
{
KaTeX parse error: Can't use function '$' in math mode at position 40: …bers", (Node *)$̲2, @1); } … = makeDefElem(“rolemembers”, (Node *)$2, @1);
}

上述就是基本的语法定义。
那么语法中的结构体 是什么意思呢?
基本知识: $$ 代表冒号左边的字符。 $1代表 冒号 : 右边 第一个字符 $2第二个 以此类推。。

如:CreateUserStmt: 语句
其中 CreateRoleStmt是一个自定义的结构体,一般在parsenodes.h 文件中 如下所示:所以你所需要的值将会在此 被赋值到你所需的结构体中 供后续使用

CreateUserStmt:
{				CreateRoleStmt *n = makeNode(CreateRoleStmt);
				n->stmt_type = ROLESTMT_USER;
				n->role = $3;
				n->options = $5;
				$$ = (Node *)n;
			}
	;

parsenodes.h :

 typedef struct CreateRoleStmt
 { NodeTag		type;
RoleStmtType stmt_type;		/* ROLE/USER/GROUP */
char	   *role;			/* role name */
List	   *options;		/* List of DefElem nodes */
} CreateRoleStmt;

第三段

一般是 保留关键字和非保留关键字(定义可自行百度)等一系列的定义,在添加新token的时候 也是需要在此按照顺序添加的。
unreserved_keyword:
ABORT_P
| ABSOLUTE_P
| ACCESS
| ACTION
| ADD_P
| ADMIN
| AFTER

到此一个粗略的 pg语法gram.y文件就已经介绍完毕!!

后续的:语法出来流程有时间 我会继续更新。。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值