python语法详解_Python内核阅读(二十四): 语法分析器

起步

物理行: 由 回车字符 结尾的字符序列组成一个物理行.

逻辑行: 由一个或者多个物理行组成,可以明确地使用反斜杠(\)来连接多行物理行.

s = "hello \

wolrd"

s = """

hello

world

"""

l = [

1,

2,

]

d = {

"a": 1,

"b": 2,

}

Grammar 文件

[Grammar]

if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]

Lable

[grammar.h]

typedef struct {

int lb_type;

char *lb_str;

} label;

arc

typedef struct {

short a_lbl; /* Label of this arc */

short a_arrow; /* State where this arc goes to */

} arc;

state

/* A state in a DFA */

typedef struct {

int s_narcs;

arc *s_arc; // 出发边的集合

/* Optional accelerators */

int s_lower; /* Lowest label index */

int s_upper; /* Highest label index */

int *s_accel; /* Accelerator */

int s_accept; /* Nonzero for accepting state */

} state;

dfa

typedef struct {

int d_type; /* Non-terminal this represents */

char *d_name; /* For printing */

int d_initial; /* Initial state */

int d_nstates;

state *d_state; /* Array of states */

bitset d_first;

} dfa;

grammar

typedef struct {

int g_ndfas;

dfa *g_dfa; /* Array of DFAs */

labellist g_ll;

int g_start; /* Start symbol of the grammar */

int g_accel; /* Set if accelerators present */

} grammar;

语法结构的搭建

static arc arcs_0_0[3] = {

{2, 1},

{3, 1},

{4, 2},

};

static arc arcs_0_1[1] = {

{0, 1},

};

static arc arcs_0_2[1] = {

{2, 1},

};

static dfa dfas[86] = {

{256, "single_input", 0, 3, states_0,

"\004\050\340\000\002\000\000\000\012\076\011\007\262\004\020\002\000\300\220\050\037\102"},

{257, "file_input", 0, 2, states_1,

"\204\050\340\000\002\000\000\000\012\076\011\007\262\004\020\002\000\300\220\050\037\102"},

...

};

static label labels[176] = {

{0, "EMPTY"},

{256, 0},

{4, 0},

{270, 0},

...

};

grammar _PyParser_Grammar = {

86,

dfas,

{176, labels},

256

};

Accelerators

[acceler.c]

void PyGrammar_AddAccelerators(grammar *g)

{

dfa *d;

int i;

d = g->g_dfa;

for (i = g->g_ndfas; --i >= 0; d++)

fixdfa(g, d);

g->g_accel = 1;

}

[acceler.c]

static void fixdfa(grammar *g, dfa *d)

{

state *s;

int j;

s = d->d_state;

for (j = 0; j < d->d_nstates; j++, s++)

fixstate(g, s);

}

申请一个与 labels 个数相等的int数组空间, 让 accel 变量指向这个内存空间, 每个元素都初始为 -1 .

处理 state 的每条边 arc . 这个处理又分为3个情况:

如果该边的 label 是终结符, 则设置 accel[ibit] = a->a_arrow , 即目标状态, 这种情况下, 不会进入到另一个 DFA.

如果这条边的 label 是非终结符, 则找到对应的 DFA, 对 firstset 中每个 label 的 ibit 设置 accel[ibit] = 目标DFA+该边的目标状态

如果该边的 label 是 "EMPTY" , 则设置 s_accept=1 表明该状态为结束状态.

最后, 计算出 accel 数组中的最小边界和最大边界, 放到 s_lower 和 s_upper 中. 小于 s_lower 和大于 s_upper 的数组位置都是没有初始化过的, 因此此时的这部分没有意义了, 用 copy 把处于 [s_lower : s_upper+1] 之间内容取出. 计算一个 state 完毕.

PyParser

[node.h]

typedef struct _node {

short n_type;

char *n_str;

int n_lineno;

int n_col_offset;

int n_nchildren;

struct _node *n_child;

} node;

成员

说明

n_type

结点类型,终结符定义在token.h中,而非终结符定义在graminit.h中

n_str

结点所对应的字符串的内容

n_lineno

对应的行号

n_col_offset

列号

n_nchildren

子结点的个数

n_child

子结点数组,动态分配内存

[parser.h]

#define MAXSTACK 1500

typedef struct {

int s_state; // 当前dfa中的状态

dfa *s_dfa; // 当前的dfa指针

struct _node *s_parent; // 当前的父节点, PyParser会把新的结点作为Child加到栈顶状态的s_parent结点中去

} stackentry;

typedef struct {

stackentry *s_top; /* Top entry */

stackentry s_base[MAXSTACK];/* Array of stack entries */

/* NB The stack grows down */

} stack;

typedef struct {

stack p_stack; // PyParser状态栈

grammar *p_grammar; // 语法图指针

node *p_tree; // CST根节点

unsigned long p_flags;// PyParser的flags

} parser_state;

[parser.h]

parser_state *PyParser_New(grammar *g, int start);

void PyParser_Delete(parser_state *ps);

int PyParser_AddToken(parser_state *ps, int type, char *str, int lineno, int col_offset,

int *expected_ret);

void PyGrammar_AddAccelerators(grammar *g);

[parsetok.c parsetok]

// 省略了很多代码

ps = PyParser_New(g, start);

for (;;) {

char *a, *b;

int type;

size_t len;

char *str;

int col_offset;

type = PyTokenizer_Get(tok, &a, &b);

PyParser_AddToken(ps, (int)type, str,

tok->lineno, col_offset,

&(err_ret->expected))

}

PyParser API

[parsetok.h]

PyAPI_FUNC(node *) PyParser_ParseString(const char *, grammar *, int,

perrdetail *);

PyAPI_FUNC(node *) PyParser_ParseFile (FILE *, const char *, grammar *, int,

const char *, const char *,

perrdetail *);

PyAPI_FUNC(node *) PyParser_ParseStringFlags(const char *, grammar *, int,

perrdetail *, int);

...

PyParser_AddToken

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值