- ParseImport/ParseImportFrom/ParseImportAlias:alias 节点缺 lineno/col_offset(vast 有),编译器符号注册可能按节点位置关联 - MakeKeyword:keyword 节点缺位置属性(4 个调用点:函数调用/类定义的 k=v 与 **kwargs) - 修复后 includes/ + TransPyV/App 全部 201 个 .vp 文件 vast_c vs vast 的 dump 与位置属性完全一致(此前差异 6 文件 keyword + 2 文件 alias)
6415 lines
189 KiB
C
6415 lines
189 KiB
C
/* vast_c - C 版 Viper/Python 语法解析器(vast 加速层)
|
||
*
|
||
* 完整 Python 3.12 + Viper 软关键字(fn/fun/func/function → def)解析器,
|
||
* 直接构造 lib.vast.Nodes 的节点类实例,输出与 vast.parse 结构完全一致
|
||
* (vast.dump 逐字节相同)。
|
||
*
|
||
* 编译(MSYS2 MinGW gcc,Python 3.12,注意 -l 必须在源文件之后):
|
||
* gcc -shared -O2 -std=c11 -I D:\Python312\include lib\vast_c\vast_c.c \
|
||
* -L D:\Python312\libs -lpython312 -o lib\vast_c\_parser.pyd
|
||
*
|
||
* 使用:
|
||
* from lib.vast_c import parse # 由 lib/vast_c/__init__.py 导出
|
||
* tree = parse("x = 1") # 与 vast.parse 同结构
|
||
*/
|
||
#define PY_SSIZE_T_CLEAN
|
||
#include <Python.h>
|
||
|
||
#include <stdbool.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
/* ================= 记号(Token) ================= */
|
||
|
||
typedef enum {
|
||
TK_ENDMARKER = 0,
|
||
TK_NAME,
|
||
TK_NUMBER,
|
||
TK_STRING,
|
||
TK_FSTRING,
|
||
TK_OP,
|
||
TK_NEWLINE,
|
||
TK_NL,
|
||
TK_INDENT,
|
||
TK_DEDENT,
|
||
} TokenKind;
|
||
|
||
typedef struct {
|
||
TokenKind Kind;
|
||
const char *Start; /* 指向源码(UTF-8 字节) */
|
||
const char *End;
|
||
int Line; /* 1-based 行号 */
|
||
int Col; /* 0-based UTF-8 字节列偏移 */
|
||
int EndLine;
|
||
int EndCol;
|
||
int StartOff; /* 源码字节偏移 */
|
||
int EndOff;
|
||
} Token;
|
||
|
||
/* ================= 词法分析器(Lexer) ================= */
|
||
|
||
typedef struct {
|
||
const char *Src;
|
||
Py_ssize_t Len;
|
||
Py_ssize_t Pos;
|
||
int BracketDepth;
|
||
int AtLineStart;
|
||
int ContinuationLine;
|
||
int BlankLine;
|
||
int *Indents;
|
||
int NIndents;
|
||
int IndentsCap;
|
||
Token *Tokens;
|
||
int NTokens;
|
||
int TokensCap;
|
||
int *LineStarts; /* 行起始字节偏移表 */
|
||
int NLineStarts;
|
||
int LineStartsCap;
|
||
int Error;
|
||
} Lexer;
|
||
|
||
/* ================= 解析器(Parser) ================= */
|
||
|
||
typedef struct {
|
||
const char *Src;
|
||
Py_ssize_t Len;
|
||
Token *Tokens;
|
||
int NTokens;
|
||
int Idx;
|
||
int *LineStarts;
|
||
int NLineStarts;
|
||
int Error; /* 语法错误标志(可回退) */
|
||
const char *ErrMsg;
|
||
int ErrLine;
|
||
int FStringExprEnd; /* f-string 表达式段结束位置(body 内偏移) */
|
||
} Parser;
|
||
|
||
/* vast.nodes 模块与节点类缓存(进程级惰性初始化) */
|
||
static PyObject *s_Nodes = NULL;
|
||
static PyObject *s_Classes = NULL; /* dict: 类名 -> 类对象 */
|
||
|
||
static PyObject *NodesModule(void) {
|
||
if (s_Nodes == NULL) {
|
||
s_Nodes = PyImport_ImportModule("lib.vast.Nodes");
|
||
}
|
||
return s_Nodes;
|
||
}
|
||
|
||
/* 获取节点类对象(borrowed 引用,内部缓存避免重复属性查找) */
|
||
static PyObject *ClassGet(Parser *P, const char *Name) {
|
||
PyObject *Mod = NodesModule();
|
||
if (Mod == NULL) {
|
||
return NULL;
|
||
}
|
||
if (s_Classes == NULL) {
|
||
s_Classes = PyDict_New();
|
||
if (s_Classes == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Key = PyUnicode_FromString(Name);
|
||
if (Key == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Cls = PyDict_GetItemWithError(s_Classes, Key); /* borrowed */
|
||
if (Cls == NULL && !PyErr_Occurred()) {
|
||
Cls = PyObject_GetAttrString(Mod, Name);
|
||
if (Cls == NULL) {
|
||
Py_DECREF(Key);
|
||
return NULL;
|
||
}
|
||
if (PyDict_SetItem(s_Classes, Key, Cls) < 0) {
|
||
Py_DECREF(Cls);
|
||
Py_DECREF(Key);
|
||
return NULL;
|
||
}
|
||
}
|
||
Py_DECREF(Key);
|
||
return Cls; /* borrowed */
|
||
}
|
||
|
||
/* 构造节点:按位置参数数组调用类(vast.nodes 的 __init__(*args, **kwargs)) */
|
||
static PyObject *NewNode(Parser *P, const char *Name, PyObject **Args, Py_ssize_t NArgs) {
|
||
PyObject *Cls = ClassGet(P, Name);
|
||
if (Cls == NULL) {
|
||
return NULL;
|
||
}
|
||
return PyObject_Vectorcall(Cls, Args, NArgs, NULL);
|
||
}
|
||
|
||
/* 设置整数属性;失败(无槽位)时清除异常 */
|
||
static void SetAttrLong(PyObject *Node, const char *Name, long V) {
|
||
PyObject *O = PyLong_FromLong(V);
|
||
if (O == NULL) {
|
||
PyErr_Clear();
|
||
return;
|
||
}
|
||
if (PyObject_SetAttrString(Node, Name, O) < 0) {
|
||
PyErr_Clear();
|
||
}
|
||
Py_DECREF(O);
|
||
}
|
||
|
||
/* 设置 4 个位置属性 */
|
||
static void NodePos(Parser *P, PyObject *Node, int Line, int Col, int EndLine, int EndCol) {
|
||
SetAttrLong(Node, "lineno", Line);
|
||
SetAttrLong(Node, "col_offset", Col);
|
||
SetAttrLong(Node, "end_lineno", EndLine);
|
||
SetAttrLong(Node, "end_col_offset", EndCol);
|
||
}
|
||
|
||
/* 仅设置 lineno/col_offset(f-string 内部字面量常量用) */
|
||
static void NodePosNoEnd(Parser *P, PyObject *Node, int Line, int Col) {
|
||
SetAttrLong(Node, "lineno", Line);
|
||
SetAttrLong(Node, "col_offset", Col);
|
||
}
|
||
|
||
/* 前一个 token(借用的 _Prev 语义) */
|
||
static Token *PrevTok(Parser *P) {
|
||
int I = P->Idx > 0 ? P->Idx - 1 : 0;
|
||
return &P->Tokens[I];
|
||
}
|
||
|
||
/* FixLoc:start 用给定 token,end 缺省取前一个 token(vast _FixLoc 语义) */
|
||
static void FixLocEnd(Parser *P, PyObject *Node, Token *Start, Token *End) {
|
||
if (End == NULL) {
|
||
End = PrevTok(P);
|
||
}
|
||
NodePos(P, Node, Start->Line, Start->Col, End->EndLine, End->EndCol);
|
||
}
|
||
|
||
static void FixLoc(Parser *P, PyObject *Node, Token *Start) {
|
||
FixLocEnd(P, Node, Start, NULL);
|
||
}
|
||
|
||
/* 节点类名(动态 type() 创建的类 tp_name 即类名) */
|
||
static const char *TypeName(PyObject *Node) {
|
||
return Py_TYPE(Node)->tp_name;
|
||
}
|
||
|
||
static int NodeIs(PyObject *Node, const char *Name) {
|
||
return strcmp(Py_TYPE(Node)->tp_name, Name) == 0;
|
||
}
|
||
|
||
/* ================= 字符分类 ================= */
|
||
|
||
static int IsNameStart(int C) {
|
||
return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') || C == '_' || C >= 0x80;
|
||
}
|
||
|
||
static int IsNameChar(int C) {
|
||
return IsNameStart(C) || (C >= '0' && C <= '9');
|
||
}
|
||
|
||
static int IsDigit(int C) {
|
||
return C >= '0' && C <= '9';
|
||
}
|
||
|
||
static int IsAlnum(int C) {
|
||
return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') || (C >= '0' && C <= '9');
|
||
}
|
||
|
||
static int IsStringPrefixChar(int C) {
|
||
return C == 'r' || C == 'R' || C == 'b' || C == 'B' || C == 'u' || C == 'U'
|
||
|| C == 'f' || C == 'F';
|
||
}
|
||
|
||
/* ================= 行起始表 ================= */
|
||
|
||
/* bisect_right(LineStarts, Off) - 1 → (行号, 字节列) */
|
||
static void PosInfoLS(const int *LineStarts, int N, int Off, int *Line, int *Col) {
|
||
int Lo = 0, Hi = N - 1, Ans = 0;
|
||
while (Lo <= Hi) {
|
||
int Mid = (Lo + Hi) / 2;
|
||
if (LineStarts[Mid] <= Off) {
|
||
Ans = Mid;
|
||
Lo = Mid + 1;
|
||
} else {
|
||
Hi = Mid - 1;
|
||
}
|
||
}
|
||
*Line = Ans + 1;
|
||
*Col = Off - LineStarts[Ans];
|
||
}
|
||
|
||
/* ================= Lexer 基础 ================= */
|
||
|
||
static void RegisterNewline(Lexer *L, int Pos) {
|
||
if (L->NLineStarts >= L->LineStartsCap) {
|
||
int NCap = L->LineStartsCap ? L->LineStartsCap * 2 : 32;
|
||
int *NS = (int *)PyMem_Realloc(L->LineStarts, (size_t)NCap * sizeof(int));
|
||
if (NS == NULL) {
|
||
L->Error = 1;
|
||
return;
|
||
}
|
||
L->LineStarts = NS;
|
||
L->LineStartsCap = NCap;
|
||
}
|
||
L->LineStarts[L->NLineStarts++] = Pos;
|
||
}
|
||
|
||
static void EmitToken(Lexer *L, TokenKind Kind, int StartOff, int EndOff) {
|
||
if (L->NTokens >= L->TokensCap) {
|
||
int NCap = L->TokensCap ? L->TokensCap * 2 : 128;
|
||
Token *NT = (Token *)PyMem_Realloc(L->Tokens, (size_t)NCap * sizeof(Token));
|
||
if (NT == NULL) {
|
||
L->Error = 1;
|
||
return;
|
||
}
|
||
L->Tokens = NT;
|
||
L->TokensCap = NCap;
|
||
}
|
||
Token *T = &L->Tokens[L->NTokens];
|
||
T->Kind = Kind;
|
||
T->Start = L->Src + StartOff;
|
||
T->End = L->Src + EndOff;
|
||
T->StartOff = StartOff;
|
||
T->EndOff = EndOff;
|
||
PosInfoLS(L->LineStarts, L->NLineStarts, StartOff, &T->Line, &T->Col);
|
||
PosInfoLS(L->LineStarts, L->NLineStarts, EndOff, &T->EndLine, &T->EndCol);
|
||
L->NTokens++;
|
||
}
|
||
|
||
/* 运算符最长匹配(与 vast Tokenizer._OPERATORS 一致) */
|
||
static int MatchOperator(const char *S, Py_ssize_t N) {
|
||
if (N <= 0) {
|
||
return 0;
|
||
}
|
||
char C = S[0];
|
||
switch (C) {
|
||
case '*':
|
||
if (N >= 3 && S[1] == '*' && S[2] == '=') return 3;
|
||
if (N >= 2 && S[1] == '*') return 2;
|
||
if (N >= 2 && S[1] == '=') return 2;
|
||
return 1;
|
||
case '/':
|
||
if (N >= 3 && S[1] == '/' && S[2] == '=') return 3;
|
||
if (N >= 2 && S[1] == '/') return 2;
|
||
if (N >= 2 && S[1] == '=') return 2;
|
||
return 1;
|
||
case '<':
|
||
if (N >= 3 && S[1] == '<' && S[2] == '=') return 3;
|
||
if (N >= 2 && S[1] == '<') return 2;
|
||
if (N >= 2 && S[1] == '=') return 2;
|
||
return 1;
|
||
case '>':
|
||
if (N >= 3 && S[1] == '>' && S[2] == '=') return 3;
|
||
if (N >= 2 && S[1] == '>') return 2;
|
||
if (N >= 2 && S[1] == '=') return 2;
|
||
return 1;
|
||
case '=':
|
||
return (N >= 2 && S[1] == '=') ? 2 : 1;
|
||
case '!':
|
||
return (N >= 2 && S[1] == '=') ? 2 : 1;
|
||
case ':':
|
||
return (N >= 2 && S[1] == '=') ? 2 : 1;
|
||
case '-':
|
||
if (N >= 2 && S[1] == '>') return 2;
|
||
if (N >= 2 && S[1] == '=') return 2;
|
||
return 1;
|
||
case '+':
|
||
return (N >= 2 && S[1] == '=') ? 2 : 1;
|
||
case '%':
|
||
return (N >= 2 && S[1] == '=') ? 2 : 1;
|
||
case '@':
|
||
return (N >= 2 && S[1] == '=') ? 2 : 1;
|
||
case '&':
|
||
return (N >= 2 && S[1] == '=') ? 2 : 1;
|
||
case '|':
|
||
return (N >= 2 && S[1] == '=') ? 2 : 1;
|
||
case '^':
|
||
return (N >= 2 && S[1] == '=') ? 2 : 1;
|
||
case '.':
|
||
return (N >= 3 && S[1] == '.' && S[2] == '.') ? 3 : 1;
|
||
default:
|
||
if (C == '(' || C == ')' || C == '[' || C == ']' || C == '{' || C == '}'
|
||
|| C == ',' || C == ';' || C == '~') {
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
static void EmitOp(Lexer *L) {
|
||
int Start = (int)L->Pos;
|
||
int Len = MatchOperator(L->Src + L->Pos, L->Len - L->Pos);
|
||
if (Len <= 0) {
|
||
Len = 1;
|
||
}
|
||
L->Pos += Len;
|
||
EmitToken(L, TK_OP, Start, (int)L->Pos);
|
||
L->AtLineStart = 0;
|
||
}
|
||
|
||
static void HandleNewline(Lexer *L) {
|
||
int NlStart = (int)L->Pos - 1;
|
||
if (NlStart > 0 && L->Src[NlStart] == '\n' && L->Src[NlStart - 1] == '\r') {
|
||
NlStart--;
|
||
}
|
||
if (L->BracketDepth > 0 || L->BlankLine
|
||
|| (L->AtLineStart && !L->ContinuationLine)) {
|
||
EmitToken(L, TK_NL, NlStart, (int)L->Pos);
|
||
} else {
|
||
EmitToken(L, TK_NEWLINE, NlStart, (int)L->Pos);
|
||
}
|
||
RegisterNewline(L, (int)L->Pos);
|
||
L->AtLineStart = 1;
|
||
L->ContinuationLine = 0;
|
||
L->BlankLine = 0;
|
||
}
|
||
|
||
static void HandleIndent(Lexer *L) {
|
||
int Start = (int)L->Pos;
|
||
int Col = 0;
|
||
while (L->Pos < L->Len) {
|
||
char Ch = L->Src[L->Pos];
|
||
if (Ch == ' ') {
|
||
Col++;
|
||
L->Pos++;
|
||
} else if (Ch == '\t') {
|
||
Col = (Col / 8 + 1) * 8;
|
||
L->Pos++;
|
||
} else if (Ch == '\f') {
|
||
L->Pos++;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
L->AtLineStart = 0;
|
||
if (L->Pos >= L->Len || L->Src[L->Pos] == '\r' || L->Src[L->Pos] == '\n'
|
||
|| L->Src[L->Pos] == '#') {
|
||
L->BlankLine = 1;
|
||
return;
|
||
}
|
||
int Cur = L->Indents[L->NIndents - 1];
|
||
if (Col > Cur) {
|
||
if (L->NIndents >= L->IndentsCap) {
|
||
int NCap = L->IndentsCap ? L->IndentsCap * 2 : 16;
|
||
int *NI = (int *)PyMem_Realloc(L->Indents, (size_t)NCap * sizeof(int));
|
||
if (NI == NULL) {
|
||
L->Error = 1;
|
||
return;
|
||
}
|
||
L->Indents = NI;
|
||
L->IndentsCap = NCap;
|
||
}
|
||
L->Indents[L->NIndents++] = Col;
|
||
EmitToken(L, TK_INDENT, Start, (int)L->Pos);
|
||
} else if (Col < Cur) {
|
||
while (L->NIndents > 0 && L->Indents[L->NIndents - 1] > Col) {
|
||
L->NIndents--;
|
||
EmitToken(L, TK_DEDENT, (int)L->Pos, (int)L->Pos);
|
||
}
|
||
}
|
||
}
|
||
|
||
static void ScanComment(Lexer *L) {
|
||
while (L->Pos < L->Len && L->Src[L->Pos] != '\r' && L->Src[L->Pos] != '\n') {
|
||
L->Pos++;
|
||
}
|
||
}
|
||
|
||
static void ScanContinuation(Lexer *L) {
|
||
if (L->Pos + 1 < L->Len
|
||
&& (L->Src[L->Pos + 1] == '\r' || L->Src[L->Pos + 1] == '\n')) {
|
||
L->Pos += 1;
|
||
if (L->Pos < L->Len && L->Src[L->Pos] == '\r') {
|
||
L->Pos += 1;
|
||
}
|
||
if (L->Pos < L->Len && L->Src[L->Pos] == '\n') {
|
||
L->Pos += 1;
|
||
}
|
||
RegisterNewline(L, (int)L->Pos);
|
||
L->AtLineStart = 1;
|
||
L->ContinuationLine = 1;
|
||
} else {
|
||
L->Pos += 1;
|
||
}
|
||
}
|
||
|
||
static void ScanName(Lexer *L) {
|
||
int Start = (int)L->Pos;
|
||
while (L->Pos < L->Len && IsNameChar((unsigned char)L->Src[L->Pos])) {
|
||
L->Pos++;
|
||
}
|
||
EmitToken(L, TK_NAME, Start, (int)L->Pos);
|
||
L->AtLineStart = 0;
|
||
}
|
||
|
||
static void ScanNumber(Lexer *L) {
|
||
int Start = (int)L->Pos;
|
||
if (L->Src[L->Pos] == '0' && L->Pos + 1 < L->Len) {
|
||
char Nxt = L->Src[L->Pos + 1];
|
||
if (Nxt == 'x' || Nxt == 'X' || Nxt == 'o' || Nxt == 'O'
|
||
|| Nxt == 'b' || Nxt == 'B') {
|
||
L->Pos += 2;
|
||
while (L->Pos < L->Len
|
||
&& (IsAlnum((unsigned char)L->Src[L->Pos]) || L->Src[L->Pos] == '_')) {
|
||
L->Pos++;
|
||
}
|
||
EmitToken(L, TK_NUMBER, Start, (int)L->Pos);
|
||
L->AtLineStart = 0;
|
||
return;
|
||
}
|
||
}
|
||
while (L->Pos < L->Len
|
||
&& (IsDigit((unsigned char)L->Src[L->Pos]) || L->Src[L->Pos] == '_')) {
|
||
L->Pos++;
|
||
}
|
||
if (L->Pos < L->Len && L->Src[L->Pos] == '.') {
|
||
L->Pos++;
|
||
while (L->Pos < L->Len
|
||
&& (IsDigit((unsigned char)L->Src[L->Pos]) || L->Src[L->Pos] == '_')) {
|
||
L->Pos++;
|
||
}
|
||
}
|
||
if (L->Pos < L->Len && (L->Src[L->Pos] == 'e' || L->Src[L->Pos] == 'E')) {
|
||
Py_ssize_t Save = L->Pos;
|
||
L->Pos++;
|
||
if (L->Pos < L->Len && (L->Src[L->Pos] == '+' || L->Src[L->Pos] == '-')) {
|
||
L->Pos++;
|
||
}
|
||
if (L->Pos < L->Len
|
||
&& (IsDigit((unsigned char)L->Src[L->Pos]) || L->Src[L->Pos] == '_')) {
|
||
while (L->Pos < L->Len
|
||
&& (IsDigit((unsigned char)L->Src[L->Pos]) || L->Src[L->Pos] == '_')) {
|
||
L->Pos++;
|
||
}
|
||
} else {
|
||
L->Pos = Save;
|
||
}
|
||
}
|
||
if (L->Pos < L->Len && (L->Src[L->Pos] == 'j' || L->Src[L->Pos] == 'J')) {
|
||
L->Pos++;
|
||
}
|
||
EmitToken(L, TK_NUMBER, Start, (int)L->Pos);
|
||
L->AtLineStart = 0;
|
||
}
|
||
|
||
static void SkipInnerString(Lexer *L);
|
||
static void ScanFStringExpr(Lexer *L);
|
||
|
||
static void ScanStringBody(Lexer *L, char Quote, int Triple, int IsFString) {
|
||
while (L->Pos < L->Len) {
|
||
char Ch = L->Src[L->Pos];
|
||
if (Ch == '\\') {
|
||
if (L->Pos + 1 < L->Len
|
||
&& (L->Src[L->Pos + 1] == '{' || L->Src[L->Pos + 1] == '}')) {
|
||
L->Pos += 1;
|
||
} else {
|
||
L->Pos += 2;
|
||
}
|
||
continue;
|
||
}
|
||
if (Ch == '\n') {
|
||
L->Pos++;
|
||
RegisterNewline(L, (int)L->Pos);
|
||
continue;
|
||
}
|
||
if (IsFString && Ch == '{') {
|
||
if (L->Pos + 1 < L->Len && L->Src[L->Pos + 1] == '{') {
|
||
L->Pos += 2;
|
||
continue;
|
||
}
|
||
ScanFStringExpr(L);
|
||
continue;
|
||
}
|
||
if (IsFString && Ch == '}') {
|
||
if (L->Pos + 1 < L->Len && L->Src[L->Pos + 1] == '}') {
|
||
L->Pos += 2;
|
||
continue;
|
||
}
|
||
L->Pos += 1;
|
||
continue;
|
||
}
|
||
if (Ch == Quote) {
|
||
if (Triple) {
|
||
if (L->Pos + 2 < L->Len && L->Src[L->Pos] == Quote
|
||
&& L->Src[L->Pos + 1] == Quote && L->Src[L->Pos + 2] == Quote) {
|
||
L->Pos += 3;
|
||
return;
|
||
}
|
||
L->Pos += 1;
|
||
continue;
|
||
} else {
|
||
L->Pos += 1;
|
||
return;
|
||
}
|
||
}
|
||
L->Pos += 1;
|
||
}
|
||
}
|
||
|
||
static void ScanFStringExpr(Lexer *L) {
|
||
L->Pos += 1; /* 跳过 { */
|
||
int Depth = 1;
|
||
while (L->Pos < L->Len) {
|
||
char Ch = L->Src[L->Pos];
|
||
if (Ch == '\\') {
|
||
L->Pos += 2;
|
||
continue;
|
||
}
|
||
if (Ch == '\n') {
|
||
L->Pos++;
|
||
RegisterNewline(L, (int)L->Pos);
|
||
continue;
|
||
}
|
||
if (Ch == '\'' || Ch == '"') {
|
||
SkipInnerString(L);
|
||
continue;
|
||
}
|
||
if (Ch == '(' || Ch == '[' || Ch == '{') {
|
||
Depth++;
|
||
L->Pos++;
|
||
continue;
|
||
}
|
||
if (Ch == ')' || Ch == ']') {
|
||
Depth--;
|
||
L->Pos++;
|
||
continue;
|
||
}
|
||
if (Ch == '}') {
|
||
if (Depth == 1) {
|
||
L->Pos++;
|
||
return;
|
||
}
|
||
Depth--;
|
||
L->Pos++;
|
||
continue;
|
||
}
|
||
L->Pos++;
|
||
}
|
||
}
|
||
|
||
static void SkipInnerString(Lexer *L) {
|
||
Py_ssize_t Save = L->Pos;
|
||
while (L->Pos < L->Len && IsStringPrefixChar((unsigned char)L->Src[L->Pos])) {
|
||
L->Pos++;
|
||
}
|
||
if (L->Pos >= L->Len || (L->Src[L->Pos] != '\'' && L->Src[L->Pos] != '"')) {
|
||
L->Pos = Save;
|
||
L->Pos += 1;
|
||
return;
|
||
}
|
||
char InnerQuote = L->Src[L->Pos];
|
||
int Triple = (L->Pos + 2 < L->Len && L->Src[L->Pos] == InnerQuote
|
||
&& L->Src[L->Pos + 1] == InnerQuote && L->Src[L->Pos + 2] == InnerQuote);
|
||
if (Triple) {
|
||
L->Pos += 3;
|
||
} else {
|
||
L->Pos += 1;
|
||
}
|
||
ScanStringBody(L, InnerQuote, Triple, 0);
|
||
}
|
||
|
||
static int TryScanString(Lexer *L) {
|
||
Py_ssize_t Start = L->Pos;
|
||
while (L->Pos < L->Len && IsStringPrefixChar((unsigned char)L->Src[L->Pos])) {
|
||
L->Pos++;
|
||
}
|
||
if (L->Pos >= L->Len || (L->Src[L->Pos] != '\'' && L->Src[L->Pos] != '"')) {
|
||
L->Pos = Start;
|
||
return 0;
|
||
}
|
||
int IsFString = 0;
|
||
for (Py_ssize_t K = Start; K < L->Pos; K++) {
|
||
char C = L->Src[K];
|
||
if (C == 'f' || C == 'F') {
|
||
IsFString = 1;
|
||
}
|
||
}
|
||
char Quote = L->Src[L->Pos];
|
||
int Triple = (L->Pos + 2 < L->Len && L->Src[L->Pos] == Quote
|
||
&& L->Src[L->Pos + 1] == Quote && L->Src[L->Pos + 2] == Quote);
|
||
if (Triple) {
|
||
L->Pos += 3;
|
||
} else {
|
||
L->Pos += 1;
|
||
}
|
||
ScanStringBody(L, Quote, Triple, IsFString);
|
||
EmitToken(L, IsFString ? TK_FSTRING : TK_STRING, (int)Start, (int)L->Pos);
|
||
L->AtLineStart = 0;
|
||
return 1;
|
||
}
|
||
|
||
static void FinishFile(Lexer *L) {
|
||
if (L->NTokens > 0) {
|
||
TokenKind K = L->Tokens[L->NTokens - 1].Kind;
|
||
if (K != TK_NEWLINE && K != TK_DEDENT && K != TK_INDENT) {
|
||
EmitToken(L, TK_NEWLINE, (int)L->Pos, (int)L->Pos);
|
||
}
|
||
}
|
||
while (L->NIndents > 1) {
|
||
L->NIndents--;
|
||
EmitToken(L, TK_DEDENT, (int)L->Pos, (int)L->Pos);
|
||
}
|
||
EmitToken(L, TK_ENDMARKER, (int)L->Pos, (int)L->Pos);
|
||
}
|
||
|
||
/* 词法分析主循环(对齐 vast Tokenizer.Tokenize) */
|
||
static void TokenizeMainLoop(Lexer *L) {
|
||
while (L->Pos < L->Len) {
|
||
unsigned char Ch = (unsigned char)L->Src[L->Pos];
|
||
if (L->AtLineStart && L->BracketDepth == 0 && !L->ContinuationLine
|
||
&& Ch != '\r' && Ch != '\n') {
|
||
HandleIndent(L);
|
||
if (L->Pos >= L->Len) {
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
if (Ch == ' ' || Ch == '\t' || Ch == '\f') {
|
||
L->Pos++;
|
||
continue;
|
||
}
|
||
if (Ch == '\r') {
|
||
L->Pos++;
|
||
if (L->Pos < L->Len && L->Src[L->Pos] == '\n') {
|
||
L->Pos++;
|
||
}
|
||
HandleNewline(L);
|
||
continue;
|
||
}
|
||
if (Ch == '\n') {
|
||
L->Pos++;
|
||
HandleNewline(L);
|
||
continue;
|
||
}
|
||
if (Ch == '#') {
|
||
ScanComment(L);
|
||
continue;
|
||
}
|
||
if (Ch == '\\') {
|
||
ScanContinuation(L);
|
||
continue;
|
||
}
|
||
if (Ch == '(' || Ch == '[' || Ch == '{') {
|
||
L->BracketDepth++;
|
||
EmitOp(L);
|
||
continue;
|
||
}
|
||
if (Ch == ')' || Ch == ']' || Ch == '}') {
|
||
if (L->BracketDepth > 0) {
|
||
L->BracketDepth--;
|
||
}
|
||
EmitOp(L);
|
||
continue;
|
||
}
|
||
if (Ch == '\'' || Ch == '"' || IsNameStart(Ch)) {
|
||
if (TryScanString(L)) {
|
||
continue;
|
||
}
|
||
if (IsDigit(Ch)) {
|
||
ScanNumber(L);
|
||
continue;
|
||
}
|
||
if (IsNameStart(Ch)) {
|
||
ScanName(L);
|
||
continue;
|
||
}
|
||
}
|
||
if (IsDigit(Ch) || (Ch == '.' && L->Pos + 1 < L->Len
|
||
&& IsDigit((unsigned char)L->Src[L->Pos + 1]))) {
|
||
ScanNumber(L);
|
||
continue;
|
||
}
|
||
EmitOp(L);
|
||
}
|
||
}
|
||
|
||
/* 对任意文本执行完整 tokenize。
|
||
* OutLineStarts/OutNLineStarts 可为 NULL(子表达式不需要)。
|
||
* 返回 1 成功,0 失败(内存不足)。 */
|
||
static int TokenizeText(const char *Src, Py_ssize_t Len,
|
||
Token **OutTokens, int *OutN,
|
||
int **OutLineStarts, int *OutNLineStarts) {
|
||
Lexer L;
|
||
memset(&L, 0, sizeof(L));
|
||
L.Src = Src;
|
||
L.Len = Len;
|
||
L.Pos = 0;
|
||
L.AtLineStart = 1;
|
||
L.Indents = (int *)PyMem_Malloc(sizeof(int));
|
||
if (L.Indents == NULL) {
|
||
return 0;
|
||
}
|
||
L.Indents[0] = 0;
|
||
L.NIndents = 1;
|
||
L.IndentsCap = 1;
|
||
RegisterNewline(&L, 0);
|
||
TokenizeMainLoop(&L);
|
||
if (!L.Error) {
|
||
FinishFile(&L);
|
||
}
|
||
*OutTokens = L.Tokens;
|
||
*OutN = L.NTokens;
|
||
if (OutLineStarts) {
|
||
*OutLineStarts = L.LineStarts;
|
||
*OutNLineStarts = L.NLineStarts;
|
||
}
|
||
PyMem_Free(L.Indents);
|
||
if (OutLineStarts == NULL) {
|
||
PyMem_Free(L.LineStarts);
|
||
}
|
||
return !L.Error;
|
||
}
|
||
|
||
/* ================= Parser 游标辅助 ================= */
|
||
|
||
static Token *PeekTok(Parser *P, int Off) {
|
||
int I = P->Idx + Off;
|
||
if (I >= P->NTokens) {
|
||
I = P->NTokens - 1;
|
||
}
|
||
if (I < 0) {
|
||
I = 0;
|
||
}
|
||
return &P->Tokens[I];
|
||
}
|
||
|
||
static Token *NextTok(Parser *P) {
|
||
Token *T = &P->Tokens[P->Idx];
|
||
if (P->Idx < P->NTokens - 1) {
|
||
P->Idx++;
|
||
}
|
||
return T;
|
||
}
|
||
|
||
static int TokIsOp(Token *T, const char *S) {
|
||
if (T->Kind != TK_OP) {
|
||
return 0;
|
||
}
|
||
Py_ssize_t L = (Py_ssize_t)strlen(S);
|
||
return (T->End - T->Start == L) && memcmp(T->Start, S, (size_t)L) == 0;
|
||
}
|
||
|
||
static int TokIsName(Token *T, const char *S) {
|
||
if (T->Kind != TK_NAME) {
|
||
return 0;
|
||
}
|
||
Py_ssize_t L = (Py_ssize_t)strlen(S);
|
||
return (T->End - T->Start == L) && memcmp(T->Start, S, (size_t)L) == 0;
|
||
}
|
||
|
||
static int AtOp(Parser *P, const char *S) {
|
||
return TokIsOp(PeekTok(P, 0), S);
|
||
}
|
||
|
||
static int AtName(Parser *P, const char *S) {
|
||
return TokIsName(PeekTok(P, 0), S);
|
||
}
|
||
|
||
static void SkipNL(Parser *P) {
|
||
while (PeekTok(P, 0)->Kind == TK_NL) {
|
||
NextTok(P);
|
||
}
|
||
}
|
||
|
||
static void SkipNEWLINE(Parser *P) {
|
||
while (PeekTok(P, 0)->Kind == TK_NEWLINE || PeekTok(P, 0)->Kind == TK_NL) {
|
||
NextTok(P);
|
||
}
|
||
}
|
||
|
||
static void SyntaxErrorAt(Parser *P, Token *T, const char *Msg) {
|
||
P->Error = 1;
|
||
P->ErrMsg = Msg;
|
||
P->ErrLine = T ? T->Line : 0;
|
||
}
|
||
|
||
static Token *ExpectOp(Parser *P, const char *S) {
|
||
Token *T = NextTok(P);
|
||
if (!TokIsOp(T, S)) {
|
||
SyntaxErrorAt(P, T, "expected operator");
|
||
return NULL;
|
||
}
|
||
return T;
|
||
}
|
||
|
||
static Token *ExpectName(Parser *P, const char *Value) {
|
||
Token *T = NextTok(P);
|
||
if (T->Kind != TK_NAME || (Value != NULL && !TokIsName(T, Value))) {
|
||
SyntaxErrorAt(P, T, "expected name");
|
||
return NULL;
|
||
}
|
||
return T;
|
||
}
|
||
|
||
static int ExpectNEWLINE(Parser *P) {
|
||
Token *T = NextTok(P);
|
||
if (T->Kind != TK_NEWLINE) {
|
||
SyntaxErrorAt(P, T, "expected newline");
|
||
return 0;
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
/* ================= 节点构造辅助 ================= */
|
||
|
||
static PyObject *MakeCtx(Parser *P, const char *Name) {
|
||
PyObject *Cls = ClassGet(P, Name);
|
||
if (Cls == NULL) {
|
||
return NULL;
|
||
}
|
||
return PyObject_Vectorcall(Cls, NULL, 0, NULL);
|
||
}
|
||
|
||
static PyObject *MakeSingleton(Parser *P, const char *Name) {
|
||
PyObject *Cls = ClassGet(P, Name);
|
||
if (Cls == NULL) {
|
||
return NULL;
|
||
}
|
||
return PyObject_Vectorcall(Cls, NULL, 0, NULL);
|
||
}
|
||
|
||
static PyObject *NewList(void) {
|
||
return PyList_New(0);
|
||
}
|
||
|
||
static int ListAppend(PyObject *List, PyObject *Item) {
|
||
return PyList_Append(List, Item);
|
||
}
|
||
|
||
/* Name(id, ctx) 并设置位置 */
|
||
static PyObject *MakeNameNode(Parser *P, Token *T, const char *CtxName) {
|
||
PyObject *Id = PyUnicode_FromStringAndSize(T->Start, T->End - T->Start);
|
||
PyObject *Ctx = MakeCtx(P, CtxName);
|
||
if (Id == NULL || Ctx == NULL) {
|
||
Py_XDECREF(Id);
|
||
Py_XDECREF(Ctx);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Id, Ctx };
|
||
PyObject *Node = NewNode(P, "Name", Argv, 2);
|
||
Py_DECREF(Id);
|
||
Py_DECREF(Ctx);
|
||
if (Node != NULL) {
|
||
FixLocEnd(P, Node, T, NULL);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* Constant(value, kind=None) */
|
||
static PyObject *MakeConstant(Parser *P, PyObject *Value) {
|
||
PyObject *Argv[2] = { Value, Py_None };
|
||
return NewNode(P, "Constant", Argv, 2);
|
||
}
|
||
|
||
static PyObject *MakeConstantPos(Parser *P, PyObject *Value, Token *Start) {
|
||
PyObject *N = MakeConstant(P, Value);
|
||
if (N != NULL) {
|
||
FixLocEnd(P, N, Start, NULL);
|
||
}
|
||
return N;
|
||
}
|
||
|
||
/* keyword(arg, value):arg 为 NULL 表示 **kwargs(arg=None) */
|
||
static PyObject *MakeKeyword(Parser *P, PyObject *Arg, PyObject *Value, Token *Start) {
|
||
PyObject *Argv[2] = { Arg ? Arg : Py_None, Value };
|
||
PyObject *N = NewNode(P, "keyword", Argv, 2);
|
||
if (N != NULL) {
|
||
FixLoc(P, N, Start);
|
||
}
|
||
return N;
|
||
}
|
||
|
||
static PyObject *MakeStarred(Parser *P, PyObject *Value) {
|
||
PyObject *Load = MakeCtx(P, "Load");
|
||
if (Load == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Value, Load };
|
||
PyObject *N = NewNode(P, "Starred", Argv, 2);
|
||
Py_DECREF(Load);
|
||
return N;
|
||
}
|
||
|
||
/* Attribute(value, attr, Load) */
|
||
static PyObject *MakeAttrNode(Parser *P, PyObject *Value, Token *AttrTok, Token *Start) {
|
||
PyObject *Attr = PyUnicode_FromStringAndSize(AttrTok->Start, AttrTok->End - AttrTok->Start);
|
||
PyObject *Load = MakeCtx(P, "Load");
|
||
if (Attr == NULL || Load == NULL) {
|
||
Py_XDECREF(Attr);
|
||
Py_XDECREF(Load);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3] = { Value, Attr, Load };
|
||
PyObject *N = NewNode(P, "Attribute", Argv, 3);
|
||
Py_DECREF(Attr);
|
||
Py_DECREF(Load);
|
||
if (N != NULL) {
|
||
FixLoc(P, N, Start);
|
||
}
|
||
return N;
|
||
}
|
||
|
||
/* 替换节点 ctx 属性为指定上下文单例 */
|
||
static void ReplaceCtx(Parser *P, PyObject *Node, const char *CtxName) {
|
||
PyObject *Ctx = MakeCtx(P, CtxName);
|
||
if (Ctx == NULL) {
|
||
return;
|
||
}
|
||
if (PyObject_SetAttrString(Node, "ctx", Ctx) < 0) {
|
||
PyErr_Clear();
|
||
}
|
||
Py_DECREF(Ctx);
|
||
}
|
||
|
||
static void SetStoreContext(Parser *P, PyObject *Node);
|
||
static void SetDelContext(Parser *P, PyObject *Node);
|
||
|
||
static void SetStoreContext(Parser *P, PyObject *Node) {
|
||
const char *N = TypeName(Node);
|
||
if (strcmp(N, "Attribute") == 0 || strcmp(N, "Subscript") == 0) {
|
||
ReplaceCtx(P, Node, "Store");
|
||
} else if (strcmp(N, "Name") == 0) {
|
||
ReplaceCtx(P, Node, "Store");
|
||
} else if (strcmp(N, "Tuple") == 0 || strcmp(N, "List") == 0) {
|
||
ReplaceCtx(P, Node, "Store");
|
||
PyObject *Elts = PyObject_GetAttrString(Node, "elts");
|
||
if (Elts != NULL) {
|
||
Py_ssize_t NElts = PyList_GET_SIZE(Elts);
|
||
for (Py_ssize_t I = 0; I < NElts; I++) {
|
||
SetStoreContext(P, PyList_GET_ITEM(Elts, I));
|
||
}
|
||
Py_DECREF(Elts);
|
||
} else {
|
||
PyErr_Clear();
|
||
}
|
||
} else if (strcmp(N, "Starred") == 0) {
|
||
ReplaceCtx(P, Node, "Store");
|
||
PyObject *V = PyObject_GetAttrString(Node, "value");
|
||
if (V != NULL) {
|
||
SetStoreContext(P, V);
|
||
Py_DECREF(V);
|
||
} else {
|
||
PyErr_Clear();
|
||
}
|
||
}
|
||
}
|
||
|
||
static void SetDelContext(Parser *P, PyObject *Node) {
|
||
const char *N = TypeName(Node);
|
||
if (strcmp(N, "Name") == 0 || strcmp(N, "Attribute") == 0
|
||
|| strcmp(N, "Subscript") == 0) {
|
||
ReplaceCtx(P, Node, "Del");
|
||
} else if (strcmp(N, "Tuple") == 0 || strcmp(N, "List") == 0) {
|
||
ReplaceCtx(P, Node, "Del");
|
||
PyObject *Elts = PyObject_GetAttrString(Node, "elts");
|
||
if (Elts != NULL) {
|
||
Py_ssize_t NElts = PyList_GET_SIZE(Elts);
|
||
for (Py_ssize_t I = 0; I < NElts; I++) {
|
||
SetDelContext(P, PyList_GET_ITEM(Elts, I));
|
||
}
|
||
Py_DECREF(Elts);
|
||
} else {
|
||
PyErr_Clear();
|
||
}
|
||
}
|
||
}
|
||
|
||
static int IsNameOrAttrOrSub(PyObject *Node) {
|
||
const char *N = TypeName(Node);
|
||
return strcmp(N, "Name") == 0 || strcmp(N, "Attribute") == 0
|
||
|| strcmp(N, "Subscript") == 0;
|
||
}
|
||
|
||
static int NodeIsConstant(PyObject *Node) {
|
||
return NodeIs(Node, "Constant");
|
||
}
|
||
|
||
/* ================= 数字 / 字符串字面量 ================= */
|
||
|
||
/* 解析数字 token 为 Python 数值对象(对齐 vast _ParseNumber) */
|
||
static PyObject *ParseNumberValue(Parser *P, Token *T) {
|
||
Py_ssize_t Len = T->End - T->Start;
|
||
char *Buf = (char *)PyMem_Malloc((size_t)Len + 1);
|
||
if (Buf == NULL) {
|
||
return NULL;
|
||
}
|
||
Py_ssize_t N = 0;
|
||
for (Py_ssize_t I = 0; I < Len; I++) {
|
||
if (T->Start[I] != '_') {
|
||
Buf[N++] = T->Start[I];
|
||
}
|
||
}
|
||
Buf[N] = '\0';
|
||
PyObject *Result = NULL;
|
||
if (N > 0 && (Buf[N - 1] == 'j' || Buf[N - 1] == 'J')) {
|
||
/* 复数:去掉 j,实部按 float 解析 */
|
||
Buf[N - 1] = '\0';
|
||
PyObject *RealStr = PyUnicode_FromStringAndSize(Buf, (Py_ssize_t)strlen(Buf));
|
||
if (RealStr != NULL) {
|
||
PyObject *Real = PyFloat_FromString(RealStr);
|
||
Py_DECREF(RealStr);
|
||
if (Real != NULL) {
|
||
Result = PyComplex_FromDoubles(PyFloat_AS_DOUBLE(Real), 0.0);
|
||
Py_DECREF(Real);
|
||
}
|
||
}
|
||
} else if (N >= 2 && Buf[0] == '0'
|
||
&& (Buf[1] == 'x' || Buf[1] == 'X' || Buf[1] == 'o'
|
||
|| Buf[1] == 'O' || Buf[1] == 'b' || Buf[1] == 'B')) {
|
||
Result = PyLong_FromString(Buf, NULL, 0);
|
||
if (Result == NULL) {
|
||
PyErr_Clear();
|
||
}
|
||
} else {
|
||
int IsFloat = 0;
|
||
for (Py_ssize_t I = 0; I < N; I++) {
|
||
if (Buf[I] == '.' || Buf[I] == 'e' || Buf[I] == 'E') {
|
||
IsFloat = 1;
|
||
break;
|
||
}
|
||
}
|
||
if (IsFloat) {
|
||
PyObject *S = PyUnicode_FromStringAndSize(Buf, N);
|
||
if (S != NULL) {
|
||
Result = PyFloat_FromString(S);
|
||
Py_DECREF(S);
|
||
}
|
||
if (Result == NULL) {
|
||
PyErr_Clear();
|
||
}
|
||
} else {
|
||
Result = PyLong_FromString(Buf, NULL, 10);
|
||
if (Result == NULL) {
|
||
PyErr_Clear();
|
||
}
|
||
}
|
||
}
|
||
if (Result == NULL) {
|
||
/* 无法解析:保留原字符串(对齐 vast 的 except ValueError 分支) */
|
||
Result = PyUnicode_FromStringAndSize(T->Start, Len);
|
||
}
|
||
PyMem_Free(Buf);
|
||
return Result;
|
||
}
|
||
|
||
/* UTF-8 解码一个字符到 UCS4,返回字节数 */
|
||
static int UTF8CharDecode(const char *S, Py_ssize_t N, Py_UCS4 *Out) {
|
||
unsigned char C = (unsigned char)S[0];
|
||
if (C < 0x80) {
|
||
*Out = C;
|
||
return 1;
|
||
}
|
||
if (C < 0xC0 || N < 2) {
|
||
*Out = C;
|
||
return 1;
|
||
}
|
||
if (C < 0xE0) {
|
||
*Out = ((C & 0x1F) << 6) | ((unsigned char)S[1] & 0x3F);
|
||
return 2;
|
||
}
|
||
if (C < 0xF0 && N >= 3) {
|
||
*Out = ((C & 0x0F) << 12) | (((unsigned char)S[1] & 0x3F) << 6)
|
||
| ((unsigned char)S[2] & 0x3F);
|
||
return 3;
|
||
}
|
||
if (N >= 4) {
|
||
*Out = ((C & 0x07) << 18) | (((unsigned char)S[1] & 0x3F) << 12)
|
||
| (((unsigned char)S[2] & 0x3F) << 6) | ((unsigned char)S[3] & 0x3F);
|
||
return 4;
|
||
}
|
||
*Out = C;
|
||
return 1;
|
||
}
|
||
|
||
static int HexVal(char C) {
|
||
if (C >= '0' && C <= '9') return C - '0';
|
||
if (C >= 'a' && C <= 'f') return C - 'a' + 10;
|
||
if (C >= 'A' && C <= 'F') return C - 'A' + 10;
|
||
return 0;
|
||
}
|
||
|
||
/* 解码字符串转义序列(对齐 vast _DecodeEscapes) */
|
||
static PyObject *DecodeEscapes(Parser *P, const char *Body, Py_ssize_t Len, int IsRaw) {
|
||
if (IsRaw) {
|
||
return PyUnicode_DecodeUTF8(Body, Len, NULL);
|
||
}
|
||
Py_UCS4 *Buf = (Py_UCS4 *)PyMem_Malloc((size_t)(Len * 4 + 4) * sizeof(Py_UCS4));
|
||
if (Buf == NULL) {
|
||
return NULL;
|
||
}
|
||
Py_ssize_t NBuf = 0;
|
||
Py_ssize_t I = 0;
|
||
while (I < Len) {
|
||
unsigned char Ch = (unsigned char)Body[I];
|
||
if (Ch != '\\') {
|
||
Py_UCS4 Cp;
|
||
int NB = UTF8CharDecode(Body + I, Len - I, &Cp);
|
||
Buf[NBuf++] = Cp;
|
||
I += NB;
|
||
continue;
|
||
}
|
||
I++;
|
||
if (I >= Len) {
|
||
Buf[NBuf++] = '\\';
|
||
break;
|
||
}
|
||
char Esc = Body[I];
|
||
switch (Esc) {
|
||
case '\\': Buf[NBuf++] = '\\'; I++; break;
|
||
case '\'': Buf[NBuf++] = '\''; I++; break;
|
||
case '"': Buf[NBuf++] = '"'; I++; break;
|
||
case 'n': Buf[NBuf++] = '\n'; I++; break;
|
||
case 't': Buf[NBuf++] = '\t'; I++; break;
|
||
case 'r': Buf[NBuf++] = '\r'; I++; break;
|
||
case 'b': Buf[NBuf++] = '\b'; I++; break;
|
||
case 'f': Buf[NBuf++] = '\f'; I++; break;
|
||
case 'v': Buf[NBuf++] = '\v'; I++; break;
|
||
case 'a': Buf[NBuf++] = '\a'; I++; break;
|
||
case 'x': {
|
||
int V = HexVal(I + 1 < Len ? Body[I + 1] : '0') * 16
|
||
+ HexVal(I + 2 < Len ? Body[I + 2] : '0');
|
||
Buf[NBuf++] = V;
|
||
I += 3;
|
||
break;
|
||
}
|
||
case 'u': {
|
||
int V = 0;
|
||
for (int K = 1; K <= 4; K++) {
|
||
V = V * 16 + HexVal(I + K < Len ? Body[I + K] : '0');
|
||
}
|
||
Buf[NBuf++] = V;
|
||
I += 5;
|
||
break;
|
||
}
|
||
case 'U': {
|
||
int V = 0;
|
||
for (int K = 1; K <= 8; K++) {
|
||
V = V * 16 + HexVal(I + K < Len ? Body[I + K] : '0');
|
||
}
|
||
Buf[NBuf++] = V;
|
||
I += 9;
|
||
break;
|
||
}
|
||
default:
|
||
if (Esc >= '0' && Esc <= '7') {
|
||
int J = 0;
|
||
int V = 0;
|
||
while (J < 3 && I + J < Len && Body[I + J] >= '0' && Body[I + J] <= '7') {
|
||
V = V * 8 + (Body[I + J] - '0');
|
||
J++;
|
||
}
|
||
Buf[NBuf++] = V;
|
||
I += J;
|
||
} else {
|
||
Buf[NBuf++] = '\\';
|
||
Buf[NBuf++] = (Py_UCS4)(unsigned char)Esc;
|
||
I++;
|
||
}
|
||
}
|
||
}
|
||
PyObject *R = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, Buf, NBuf);
|
||
PyMem_Free(Buf);
|
||
return R;
|
||
}
|
||
|
||
/* 解码 bytes 字面量(对齐 vast _DecodeBytes) */
|
||
static PyObject *DecodeBytes(Parser *P, const char *Body, Py_ssize_t Len, int IsRaw) {
|
||
if (IsRaw) {
|
||
return PyBytes_FromStringAndSize(Body, Len);
|
||
}
|
||
char *Buf = (char *)PyMem_Malloc((size_t)(Len * 4 + 4));
|
||
if (Buf == NULL) {
|
||
return NULL;
|
||
}
|
||
Py_ssize_t NBuf = 0;
|
||
Py_ssize_t I = 0;
|
||
while (I < Len) {
|
||
unsigned char Ch = (unsigned char)Body[I];
|
||
if (Ch != '\\') {
|
||
Buf[NBuf++] = Ch;
|
||
I++;
|
||
continue;
|
||
}
|
||
I++;
|
||
if (I >= Len) {
|
||
Buf[NBuf++] = '\\';
|
||
break;
|
||
}
|
||
char Esc = Body[I];
|
||
switch (Esc) {
|
||
case '\\': Buf[NBuf++] = '\\'; I++; break;
|
||
case '\'': Buf[NBuf++] = '\''; I++; break;
|
||
case '"': Buf[NBuf++] = '"'; I++; break;
|
||
case 'n': Buf[NBuf++] = 10; I++; break;
|
||
case 't': Buf[NBuf++] = 9; I++; break;
|
||
case 'r': Buf[NBuf++] = 13; I++; break;
|
||
case 'b': Buf[NBuf++] = 8; I++; break;
|
||
case 'f': Buf[NBuf++] = 12; I++; break;
|
||
case 'v': Buf[NBuf++] = 11; I++; break;
|
||
case 'a': Buf[NBuf++] = 7; I++; break;
|
||
case 'x': {
|
||
int V = HexVal(I + 1 < Len ? Body[I + 1] : '0') * 16
|
||
+ HexVal(I + 2 < Len ? Body[I + 2] : '0');
|
||
Buf[NBuf++] = (char)V;
|
||
I += 3;
|
||
break;
|
||
}
|
||
case 'u': {
|
||
int V = 0;
|
||
for (int K = 1; K <= 4; K++) {
|
||
V = V * 16 + HexVal(I + K < Len ? Body[I + K] : '0');
|
||
}
|
||
Buf[NBuf++] = (char)V;
|
||
I += 5;
|
||
break;
|
||
}
|
||
case 'U': {
|
||
int V = 0;
|
||
for (int K = 1; K <= 8; K++) {
|
||
V = V * 16 + HexVal(I + K < Len ? Body[I + K] : '0');
|
||
}
|
||
Buf[NBuf++] = (char)V;
|
||
I += 9;
|
||
break;
|
||
}
|
||
default:
|
||
if (Esc >= '0' && Esc <= '7') {
|
||
int J = 0;
|
||
int V = 0;
|
||
while (J < 3 && I + J < Len && Body[I + J] >= '0' && Body[I + J] <= '7') {
|
||
V = V * 8 + (Body[I + J] - '0');
|
||
J++;
|
||
}
|
||
Buf[NBuf++] = (char)V;
|
||
I += J;
|
||
} else {
|
||
Buf[NBuf++] = '\\';
|
||
Buf[NBuf++] = (unsigned char)Esc;
|
||
I++;
|
||
}
|
||
}
|
||
}
|
||
PyObject *R = PyBytes_FromStringAndSize(Buf, NBuf);
|
||
PyMem_Free(Buf);
|
||
return R;
|
||
}
|
||
|
||
/* 解码字符串 token 原始文本为实际值(str 或 bytes) */
|
||
static PyObject *DecodeString(Parser *P, Token *T) {
|
||
const char *Raw = T->Start;
|
||
Py_ssize_t Len = T->End - T->Start;
|
||
Py_ssize_t I = 0;
|
||
while (I < Len && IsStringPrefixChar((unsigned char)Raw[I])) {
|
||
I++;
|
||
}
|
||
char Quote = Raw[I];
|
||
int Triple = (I + 2 < Len && Raw[I] == Quote && Raw[I + 1] == Quote
|
||
&& Raw[I + 2] == Quote);
|
||
Py_ssize_t BodyStart = I + (Triple ? 3 : 1);
|
||
Py_ssize_t BodyEnd = Len - (Triple ? 3 : 1);
|
||
int IsRaw = 0;
|
||
int IsBytes = 0;
|
||
for (Py_ssize_t K = 0; K < I; K++) {
|
||
char C = Raw[K];
|
||
if (C == 'r' || C == 'R') IsRaw = 1;
|
||
if (C == 'b' || C == 'B') IsBytes = 1;
|
||
}
|
||
if (IsBytes) {
|
||
return DecodeBytes(P, Raw + BodyStart, BodyEnd - BodyStart, IsRaw);
|
||
}
|
||
return DecodeEscapes(P, Raw + BodyStart, BodyEnd - BodyStart, IsRaw);
|
||
}
|
||
|
||
/* 拼接字符串字面量值(对齐 vast _JoinConstParts) */
|
||
static PyObject *JoinConstParts(PyObject *Parts) {
|
||
Py_ssize_t N = PyList_GET_SIZE(Parts);
|
||
if (N == 0) {
|
||
return PyUnicode_FromString("");
|
||
}
|
||
PyObject *First = PyList_GET_ITEM(Parts, 0);
|
||
if (PyBytes_Check(First)) {
|
||
PyObject *Acc = PyBytes_FromStringAndSize(NULL, 0);
|
||
for (Py_ssize_t I = 0; I < N; I++) {
|
||
PyObject *Part = PyList_GET_ITEM(Parts, I);
|
||
PyObject *Bytes = PyBytes_Check(Part) ? Part
|
||
: PyUnicode_AsUTF8String(Part);
|
||
if (Bytes == NULL) {
|
||
Py_DECREF(Acc);
|
||
return NULL;
|
||
}
|
||
PyObject *NewAcc = PySequence_Concat(Acc, Bytes);
|
||
if (Bytes != Part) {
|
||
Py_DECREF(Bytes);
|
||
}
|
||
Py_DECREF(Acc);
|
||
if (NewAcc == NULL) {
|
||
return NULL;
|
||
}
|
||
Acc = NewAcc;
|
||
}
|
||
return Acc;
|
||
}
|
||
PyObject *Sep = PyUnicode_FromString("");
|
||
if (Sep == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Joined = PyUnicode_Join(Sep, Parts);
|
||
Py_DECREF(Sep);
|
||
return Joined;
|
||
}
|
||
|
||
/* ================= 表达式解析 ================= */
|
||
|
||
static PyObject *ParseExpr(Parser *P);
|
||
static PyObject *ParseConditional(Parser *P);
|
||
static PyObject *ParseDisjunction(Parser *P);
|
||
static PyObject *ParseConjunction(Parser *P);
|
||
static PyObject *ParseInversion(Parser *P);
|
||
static PyObject *ParseComparison(Parser *P);
|
||
static PyObject *ParseBitOr(Parser *P);
|
||
static PyObject *ParseBitXor(Parser *P);
|
||
static PyObject *ParseBitAnd(Parser *P);
|
||
static PyObject *ParseShift(Parser *P);
|
||
static PyObject *ParseArith(Parser *P);
|
||
static PyObject *ParseTerm(Parser *P);
|
||
static PyObject *ParseFactor(Parser *P);
|
||
static PyObject *ParsePower(Parser *P);
|
||
static PyObject *ParseAwaitPrimary(Parser *P);
|
||
static PyObject *ParsePrimary(Parser *P);
|
||
static PyObject *ParseAtom(Parser *P);
|
||
static PyObject *ParseNumber(Parser *P);
|
||
static PyObject *ParseStringConcat(Parser *P);
|
||
static PyObject *ParseParen(Parser *P);
|
||
static PyObject *ParseList(Parser *P);
|
||
static PyObject *ParseDictSet(Parser *P);
|
||
static PyObject *ParseYield(Parser *P);
|
||
static PyObject *ParseLambda(Parser *P);
|
||
static PyObject *ParseArguments(Parser *P, int SkipOpen, int AllowLambda);
|
||
static PyObject *ParseArg(Parser *P, int AllowAnnotation);
|
||
static PyObject *ParseTarget(Parser *P);
|
||
static PyObject *ParseComprehensionTarget(Parser *P);
|
||
static PyObject *ParseComprehensionGenerators(Parser *P);
|
||
|
||
/* ============ 字符串拼接与 f-string ============ */
|
||
|
||
static PyObject *ParseFStringToken(Parser *P, Token *Tok);
|
||
static PyObject *ParseFStringBodyEx(Parser *P, const char *Raw, int RawLen,
|
||
Token *OuterTok, int BaseOffset);
|
||
static PyObject *ParseFStringValue(Parser *P, const char *Raw, int BodyStart,
|
||
int Start, int BodyEnd, Token *OuterTok, int RelBase);
|
||
static PyObject *ParseSubExpression(Parser *P, const char *Text, Py_ssize_t TextLen,
|
||
int AbsBase);
|
||
static int SkipInnerLiteral(const char *Raw, int BodyStart, int Start, int BodyEnd);
|
||
|
||
/* f-string 内部字面量常量(仅 lineno/col_offset,对齐 vast) */
|
||
static PyObject *MakeFStrConstant(Parser *P, PyObject *Value, Token *OuterTok) {
|
||
PyObject *N = MakeConstant(P, Value);
|
||
if (N != NULL) {
|
||
NodePosNoEnd(P, N, OuterTok->Line, OuterTok->Col);
|
||
}
|
||
return N;
|
||
}
|
||
|
||
static PyObject *ParseStringConcat(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Parts = NewList(); /* JoinedStr 的 values */
|
||
PyObject *ConstParts = NewList(); /* 普通字符串字面量值 */
|
||
int HasFString = 0;
|
||
if (Parts == NULL || ConstParts == NULL) {
|
||
Py_XDECREF(Parts);
|
||
Py_XDECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
for (;;) {
|
||
SkipNL(P);
|
||
Token *Tok = PeekTok(P, 0);
|
||
if (Tok->Kind == TK_STRING) {
|
||
NextTok(P);
|
||
PyObject *Val = DecodeString(P, Tok);
|
||
if (Val == NULL) {
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
PyList_Append(ConstParts, Val);
|
||
Py_DECREF(Val);
|
||
} else if (Tok->Kind == TK_FSTRING) {
|
||
NextTok(P);
|
||
PyObject *Joined = ParseFStringToken(P, Tok);
|
||
if (Joined == NULL) {
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
HasFString = 1;
|
||
if (PyList_GET_SIZE(ConstParts) > 0) {
|
||
PyObject *JoinedStr = JoinConstParts(ConstParts);
|
||
if (JoinedStr == NULL) {
|
||
Py_DECREF(Joined);
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
PyObject *C = MakeFStrConstant(P, JoinedStr, Start);
|
||
Py_DECREF(JoinedStr);
|
||
if (C == NULL) {
|
||
Py_DECREF(Joined);
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Parts, C);
|
||
Py_DECREF(C);
|
||
PyList_SetSlice(ConstParts, 0, PyList_GET_SIZE(ConstParts), NULL);
|
||
}
|
||
PyObject *JVals = PyObject_GetAttrString(Joined, "values");
|
||
if (JVals == NULL) {
|
||
Py_DECREF(Joined);
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
/* 相邻 Constant 合并(f-string 字面量 + 后续常量段) */
|
||
if (PyList_GET_SIZE(Parts) > 0 && NodeIsConstant(PyList_GET_ITEM(Parts, PyList_GET_SIZE(Parts) - 1))
|
||
&& PyList_GET_SIZE(JVals) > 0 && NodeIsConstant(PyList_GET_ITEM(JVals, 0))) {
|
||
PyObject *Last = PyList_GET_ITEM(Parts, PyList_GET_SIZE(Parts) - 1);
|
||
PyObject *LastVal = PyObject_GetAttrString(Last, "value");
|
||
PyObject *FirstVal = PyObject_GetAttrString(PyList_GET_ITEM(JVals, 0), "value");
|
||
if (LastVal == NULL || FirstVal == NULL) {
|
||
Py_XDECREF(LastVal);
|
||
Py_XDECREF(FirstVal);
|
||
Py_DECREF(JVals);
|
||
Py_DECREF(Joined);
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
PyObject *S1 = PyObject_Str(LastVal);
|
||
PyObject *S2 = PyObject_Str(FirstVal);
|
||
Py_DECREF(LastVal);
|
||
Py_DECREF(FirstVal);
|
||
PyObject *Merged = NULL;
|
||
if (S1 != NULL && S2 != NULL) {
|
||
Merged = PyUnicode_Concat(S1, S2);
|
||
}
|
||
Py_XDECREF(S1);
|
||
Py_XDECREF(S2);
|
||
if (Merged == NULL) {
|
||
Py_DECREF(JVals);
|
||
Py_DECREF(Joined);
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
PyObject *MergedConst = MakeFStrConstant(P, Merged, Start);
|
||
Py_DECREF(Merged);
|
||
if (MergedConst == NULL) {
|
||
Py_DECREF(JVals);
|
||
Py_DECREF(Joined);
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
PyList_SetItem(Parts, PyList_GET_SIZE(Parts) - 1, MergedConst); /* 偷取 */
|
||
PyObject *Val;
|
||
for (Py_ssize_t I = 1; I < PyList_GET_SIZE(JVals); I++) {
|
||
Val = PyList_GET_ITEM(JVals, I);
|
||
PyList_Append(Parts, Val);
|
||
}
|
||
} else {
|
||
PyObject *Val;
|
||
for (Py_ssize_t I = 0; I < PyList_GET_SIZE(JVals); I++) {
|
||
Val = PyList_GET_ITEM(JVals, I);
|
||
PyList_Append(Parts, Val);
|
||
}
|
||
}
|
||
Py_DECREF(JVals);
|
||
Py_DECREF(Joined);
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
if (!HasFString) {
|
||
PyObject *Val = JoinConstParts(ConstParts);
|
||
Py_DECREF(ConstParts);
|
||
if (Val == NULL) {
|
||
Py_DECREF(Parts);
|
||
return NULL;
|
||
}
|
||
PyObject *Node = MakeConstantPos(P, Val, Start);
|
||
Py_DECREF(Val);
|
||
Py_DECREF(Parts);
|
||
return Node;
|
||
}
|
||
if (PyList_GET_SIZE(ConstParts) > 0) {
|
||
if (PyList_GET_SIZE(Parts) > 0
|
||
&& NodeIsConstant(PyList_GET_ITEM(Parts, PyList_GET_SIZE(Parts) - 1))) {
|
||
PyObject *Last = PyList_GET_ITEM(Parts, PyList_GET_SIZE(Parts) - 1);
|
||
PyObject *LastVal = PyObject_GetAttrString(Last, "value");
|
||
PyObject *TailVal = JoinConstParts(ConstParts);
|
||
if (LastVal == NULL || TailVal == NULL) {
|
||
Py_XDECREF(LastVal);
|
||
Py_XDECREF(TailVal);
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
PyObject *S1 = PyObject_Str(LastVal);
|
||
PyObject *S2 = PyObject_Str(TailVal);
|
||
Py_DECREF(LastVal);
|
||
Py_DECREF(TailVal);
|
||
PyObject *Merged = NULL;
|
||
if (S1 != NULL && S2 != NULL) {
|
||
Merged = PyUnicode_Concat(S1, S2);
|
||
}
|
||
Py_XDECREF(S1);
|
||
Py_XDECREF(S2);
|
||
if (Merged == NULL) {
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
PyObject *MergedConst = MakeFStrConstant(P, Merged, Start);
|
||
Py_DECREF(Merged);
|
||
if (MergedConst == NULL) {
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
PyList_SetItem(Parts, PyList_GET_SIZE(Parts) - 1, MergedConst); /* 偷取 */
|
||
} else {
|
||
PyObject *TailVal = JoinConstParts(ConstParts);
|
||
if (TailVal == NULL) {
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
PyObject *C = MakeFStrConstant(P, TailVal, Start);
|
||
Py_DECREF(TailVal);
|
||
if (C == NULL) {
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(ConstParts);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Parts, C);
|
||
Py_DECREF(C);
|
||
}
|
||
}
|
||
Py_DECREF(ConstParts);
|
||
PyObject *Argv[1] = { Parts };
|
||
PyObject *Node = NewNode(P, "JoinedStr", Argv, 1);
|
||
Py_DECREF(Parts);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 解析 FSTRING token 为 JoinedStr */
|
||
static PyObject *ParseFStringToken(Parser *P, Token *Tok) {
|
||
PyObject *Values = ParseFStringBodyEx(P, Tok->Start, (int)(Tok->End - Tok->Start),
|
||
Tok, 0);
|
||
if (Values == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[1] = { Values };
|
||
PyObject *Node = NewNode(P, "JoinedStr", Argv, 1);
|
||
Py_DECREF(Values);
|
||
if (Node != NULL) {
|
||
NodePos(P, Node, Tok->Line, Tok->Col, Tok->EndLine, Tok->EndCol);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 基于原始文本的 f-string body 解析(完整实现)。
|
||
* 返回 values 列表;BaseOffset 用于嵌套(本实现仅顶层使用)。 */
|
||
static PyObject *ParseFStringBodyEx(Parser *P, const char *Raw, int RawLen,
|
||
Token *OuterTok, int BaseOffset);
|
||
|
||
/* 字面文本暂存(字节缓冲) */
|
||
typedef struct {
|
||
char *Buf;
|
||
Py_ssize_t Len;
|
||
Py_ssize_t Cap;
|
||
} LitBuf;
|
||
|
||
static int LitAppend(LitBuf *Lb, const char *S, Py_ssize_t N) {
|
||
if (Lb->Len + N > Lb->Cap) {
|
||
Py_ssize_t NCap = Lb->Cap ? Lb->Cap * 2 : 64;
|
||
while (NCap < Lb->Len + N) {
|
||
NCap *= 2;
|
||
}
|
||
char *NB = (char *)PyMem_Realloc(Lb->Buf, (size_t)NCap);
|
||
if (NB == NULL) {
|
||
return 0;
|
||
}
|
||
Lb->Buf = NB;
|
||
Lb->Cap = NCap;
|
||
}
|
||
memcpy(Lb->Buf + Lb->Len, S, (size_t)N);
|
||
Lb->Len += N;
|
||
return 1;
|
||
}
|
||
|
||
static PyObject *ParseFStringBodyEx(Parser *P, const char *Raw, int RawLen,
|
||
Token *OuterTok, int BaseOffset) {
|
||
(void)BaseOffset;
|
||
int I = 0;
|
||
while (I < RawLen && IsStringPrefixChar((unsigned char)Raw[I])) {
|
||
I++;
|
||
}
|
||
char Quote = Raw[I];
|
||
int Triple = (I + 2 < RawLen && Raw[I] == Quote && Raw[I + 1] == Quote
|
||
&& Raw[I + 2] == Quote);
|
||
int IsRaw = 0;
|
||
for (int K = 0; K < I; K++) {
|
||
if (Raw[K] == 'r' || Raw[K] == 'R') IsRaw = 1;
|
||
}
|
||
int BodyStart = I + (Triple ? 3 : 1);
|
||
int BodyEnd = RawLen - (Triple ? 3 : 1);
|
||
PyObject *Values = NewList();
|
||
if (Values == NULL) {
|
||
return NULL;
|
||
}
|
||
LitBuf Lb;
|
||
memset(&Lb, 0, sizeof(Lb));
|
||
int J = 0;
|
||
int RelBase = BodyStart;
|
||
while (J < BodyEnd - BodyStart) {
|
||
char Ch = Raw[BodyStart + J];
|
||
if (Ch == '{') {
|
||
if (J + 1 < BodyEnd - BodyStart && Raw[BodyStart + J + 1] == '{') {
|
||
if (!LitAppend(&Lb, "{", 1)) {
|
||
Py_DECREF(Values);
|
||
PyMem_Free(Lb.Buf);
|
||
return NULL;
|
||
}
|
||
J += 2;
|
||
continue;
|
||
}
|
||
if (Lb.Len > 0) {
|
||
PyObject *Str = DecodeEscapes(P, Lb.Buf, Lb.Len, IsRaw);
|
||
Lb.Len = 0;
|
||
if (Str == NULL) {
|
||
Py_DECREF(Values);
|
||
PyMem_Free(Lb.Buf);
|
||
return NULL;
|
||
}
|
||
PyObject *C = MakeFStrConstant(P, Str, OuterTok);
|
||
Py_DECREF(Str);
|
||
if (C == NULL) {
|
||
Py_DECREF(Values);
|
||
PyMem_Free(Lb.Buf);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Values, C);
|
||
Py_DECREF(C);
|
||
}
|
||
PyObject *Fv = ParseFStringValue(P, Raw, BodyStart, J, BodyEnd, OuterTok, RelBase);
|
||
if (Fv == NULL) {
|
||
Py_DECREF(Values);
|
||
PyMem_Free(Lb.Buf);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Values, Fv);
|
||
Py_DECREF(Fv);
|
||
J = P->FStringExprEnd;
|
||
continue;
|
||
} else if (Ch == '}') {
|
||
if (J + 1 < BodyEnd - BodyStart && Raw[BodyStart + J + 1] == '}') {
|
||
if (!LitAppend(&Lb, "}", 1)) {
|
||
Py_DECREF(Values);
|
||
PyMem_Free(Lb.Buf);
|
||
return NULL;
|
||
}
|
||
J += 2;
|
||
continue;
|
||
}
|
||
/* 单独的 } 宽松处理为字面量 */
|
||
if (!LitAppend(&Lb, "}", 1)) {
|
||
Py_DECREF(Values);
|
||
PyMem_Free(Lb.Buf);
|
||
return NULL;
|
||
}
|
||
J += 1;
|
||
continue;
|
||
} else {
|
||
Py_UCS4 Cp;
|
||
int NB = UTF8CharDecode(Raw + BodyStart + J, BodyEnd - BodyStart - J, &Cp);
|
||
char Tmp[4];
|
||
int TN;
|
||
if (Cp < 0x80) {
|
||
Tmp[0] = (char)Cp;
|
||
TN = 1;
|
||
} else if (Cp < 0x800) {
|
||
Tmp[0] = (char)(0xC0 | (Cp >> 6));
|
||
Tmp[1] = (char)(0x80 | (Cp & 0x3F));
|
||
TN = 2;
|
||
} else if (Cp < 0x10000) {
|
||
Tmp[0] = (char)(0xE0 | (Cp >> 12));
|
||
Tmp[1] = (char)(0x80 | ((Cp >> 6) & 0x3F));
|
||
Tmp[2] = (char)(0x80 | (Cp & 0x3F));
|
||
TN = 3;
|
||
} else {
|
||
Tmp[0] = (char)(0xF0 | (Cp >> 18));
|
||
Tmp[1] = (char)(0x80 | ((Cp >> 12) & 0x3F));
|
||
Tmp[2] = (char)(0x80 | ((Cp >> 6) & 0x3F));
|
||
Tmp[3] = (char)(0x80 | (Cp & 0x3F));
|
||
TN = 4;
|
||
}
|
||
if (!LitAppend(&Lb, Tmp, TN)) {
|
||
Py_DECREF(Values);
|
||
PyMem_Free(Lb.Buf);
|
||
return NULL;
|
||
}
|
||
J += NB;
|
||
continue;
|
||
}
|
||
}
|
||
if (Lb.Len > 0) {
|
||
PyObject *Str = DecodeEscapes(P, Lb.Buf, Lb.Len, IsRaw);
|
||
if (Str == NULL) {
|
||
Py_DECREF(Values);
|
||
PyMem_Free(Lb.Buf);
|
||
return NULL;
|
||
}
|
||
PyObject *C = MakeFStrConstant(P, Str, OuterTok);
|
||
Py_DECREF(Str);
|
||
if (C == NULL) {
|
||
Py_DECREF(Values);
|
||
PyMem_Free(Lb.Buf);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Values, C);
|
||
Py_DECREF(C);
|
||
}
|
||
PyMem_Free(Lb.Buf);
|
||
return Values;
|
||
}
|
||
|
||
/* 解析单个 {expr[!conv][:spec]} 段,返回 FormattedValue;结束位置存入 P->FStringExprEnd */
|
||
static PyObject *ParseFStringValue(Parser *P, const char *Raw, int BodyStart,
|
||
int Start, int BodyEnd, Token *OuterTok, int RelBase) {
|
||
int J = Start + 1; /* 跳过 { */
|
||
int Depth = 1;
|
||
int ExprStart = J;
|
||
int ExprEnd = J;
|
||
char StopChar = '}';
|
||
while (J < BodyEnd) {
|
||
char Ch = Raw[BodyStart + J];
|
||
if (Ch == '\\') {
|
||
J += 2;
|
||
continue;
|
||
}
|
||
if (Ch == '\'' || Ch == '"') {
|
||
J = SkipInnerLiteral(Raw, BodyStart, J, BodyEnd);
|
||
continue;
|
||
}
|
||
if (Ch == '(' || Ch == '[' || Ch == '{') {
|
||
Depth++;
|
||
J++;
|
||
continue;
|
||
}
|
||
if (Ch == ')' || Ch == ']' || Ch == '}') {
|
||
if (Depth == 1) {
|
||
ExprEnd = J;
|
||
J++;
|
||
break;
|
||
}
|
||
Depth--;
|
||
J++;
|
||
continue;
|
||
}
|
||
if (Depth == 1 && (Ch == '!' || Ch == ':')) {
|
||
ExprEnd = J;
|
||
StopChar = Ch;
|
||
break;
|
||
}
|
||
J++;
|
||
}
|
||
P->FStringExprEnd = J;
|
||
int Conversion = -1;
|
||
PyObject *FormatSpec = NULL;
|
||
int K = J;
|
||
if (StopChar == '!') {
|
||
K++;
|
||
if (K < BodyEnd && (Raw[BodyStart + K] == 'r' || Raw[BodyStart + K] == 's'
|
||
|| Raw[BodyStart + K] == 'a')) {
|
||
Conversion = (unsigned char)Raw[BodyStart + K];
|
||
K++;
|
||
}
|
||
if (K < BodyEnd && Raw[BodyStart + K] == ':') {
|
||
StopChar = ':';
|
||
} else {
|
||
if (K < BodyEnd && Raw[BodyStart + K] == '}') {
|
||
K++;
|
||
}
|
||
P->FStringExprEnd = K;
|
||
}
|
||
}
|
||
if (StopChar == ':') {
|
||
K++;
|
||
int SpecStart = K;
|
||
int Depth2 = 1;
|
||
while (K < BodyEnd) {
|
||
char C2 = Raw[BodyStart + K];
|
||
if (C2 == '{') {
|
||
Depth2++;
|
||
K++;
|
||
} else if (C2 == '}') {
|
||
Depth2--;
|
||
if (Depth2 == 0) {
|
||
break;
|
||
}
|
||
K++;
|
||
} else {
|
||
K++;
|
||
}
|
||
}
|
||
int HasNested = 0;
|
||
for (int I2 = SpecStart; I2 < K; I2++) {
|
||
if (Raw[BodyStart + I2] == '{') {
|
||
HasNested = 1;
|
||
break;
|
||
}
|
||
}
|
||
if (HasNested) {
|
||
/* 嵌套表达式:构造内层 f-string 文本并递归解析 */
|
||
Py_ssize_t SpecLen = K - SpecStart;
|
||
char *Inner = (char *)PyMem_Malloc((size_t)(SpecLen * 2 + 4));
|
||
if (Inner == NULL) {
|
||
return NULL;
|
||
}
|
||
Py_ssize_t NI = 0;
|
||
Inner[NI++] = 'f';
|
||
Inner[NI++] = '"';
|
||
for (int I2 = SpecStart; I2 < K; I2++) {
|
||
char C2 = Raw[BodyStart + I2];
|
||
if (C2 == '"') {
|
||
Inner[NI++] = '\\';
|
||
}
|
||
Inner[NI++] = C2;
|
||
}
|
||
Inner[NI++] = '"';
|
||
Token InnerTok;
|
||
InnerTok.Kind = TK_FSTRING;
|
||
InnerTok.Start = Inner;
|
||
InnerTok.End = Inner + NI;
|
||
InnerTok.Line = OuterTok->Line;
|
||
InnerTok.Col = OuterTok->Col;
|
||
InnerTok.EndLine = OuterTok->EndLine;
|
||
InnerTok.EndCol = OuterTok->EndCol;
|
||
InnerTok.StartOff = OuterTok->StartOff;
|
||
InnerTok.EndOff = OuterTok->EndOff;
|
||
FormatSpec = ParseFStringToken(P, &InnerTok);
|
||
PyMem_Free(Inner);
|
||
if (FormatSpec == NULL) {
|
||
return NULL;
|
||
}
|
||
} else {
|
||
PyObject *SpecStr = PyUnicode_FromStringAndSize(Raw + BodyStart + SpecStart,
|
||
K - SpecStart);
|
||
if (SpecStr == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *C = MakeFStrConstant(P, SpecStr, OuterTok);
|
||
Py_DECREF(SpecStr);
|
||
if (C == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *JVals = NewList();
|
||
if (JVals == NULL) {
|
||
Py_DECREF(C);
|
||
return NULL;
|
||
}
|
||
PyList_Append(JVals, C);
|
||
Py_DECREF(C);
|
||
PyObject *Argv[1] = { JVals };
|
||
FormatSpec = NewNode(P, "JoinedStr", Argv, 1);
|
||
Py_DECREF(JVals);
|
||
if (FormatSpec == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
if (K < BodyEnd && Raw[BodyStart + K] == '}') {
|
||
K++;
|
||
}
|
||
P->FStringExprEnd = K;
|
||
}
|
||
/* 解析子表达式并重定位 */
|
||
PyObject *ExprNode = ParseSubExpression(P, Raw + BodyStart + ExprStart,
|
||
ExprEnd - ExprStart,
|
||
OuterTok->StartOff + RelBase + ExprStart);
|
||
if (ExprNode == NULL) {
|
||
Py_XDECREF(FormatSpec);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3];
|
||
Argv[0] = ExprNode;
|
||
Argv[1] = PyLong_FromLong(Conversion);
|
||
Argv[2] = FormatSpec ? FormatSpec : Py_None;
|
||
PyObject *Fv = NewNode(P, "FormattedValue", Argv, 3);
|
||
Py_XDECREF(Argv[1]);
|
||
Py_XDECREF(FormatSpec);
|
||
Py_DECREF(ExprNode);
|
||
if (Fv == NULL) {
|
||
return NULL;
|
||
}
|
||
NodePos(P, Fv, OuterTok->Line, OuterTok->Col, OuterTok->EndLine, OuterTok->EndCol);
|
||
return Fv;
|
||
}
|
||
|
||
/* 跳过 f-string 表达式内部的字符串字面量 */
|
||
static int SkipInnerLiteral(const char *Raw, int BodyStart, int Start, int BodyEnd) {
|
||
int J = Start;
|
||
while (J < BodyEnd && IsStringPrefixChar((unsigned char)Raw[BodyStart + J])) {
|
||
J++;
|
||
}
|
||
if (J >= BodyEnd || (Raw[BodyStart + J] != '\'' && Raw[BodyStart + J] != '"')) {
|
||
return Start + 1;
|
||
}
|
||
char Quote = Raw[BodyStart + J];
|
||
int Triple = (J + 2 < BodyEnd && Raw[BodyStart + J] == Quote
|
||
&& Raw[BodyStart + J + 1] == Quote && Raw[BodyStart + J + 2] == Quote);
|
||
J += Triple ? 3 : 1;
|
||
while (J < BodyEnd) {
|
||
char Ch = Raw[BodyStart + J];
|
||
if (Ch == '\\') {
|
||
J += 2;
|
||
continue;
|
||
}
|
||
if (Ch == Quote) {
|
||
if (Triple) {
|
||
if (J + 2 < BodyEnd && Raw[BodyStart + J] == Quote
|
||
&& Raw[BodyStart + J + 1] == Quote && Raw[BodyStart + J + 2] == Quote) {
|
||
J += 3;
|
||
return J;
|
||
}
|
||
J += 1;
|
||
} else {
|
||
J += 1;
|
||
return J;
|
||
}
|
||
}
|
||
J++;
|
||
}
|
||
return J;
|
||
}
|
||
|
||
/* 解析 f-string 子表达式文本(重新 tokenize 并重定位到绝对偏移) */
|
||
static PyObject *ParseSubExpression(Parser *P, const char *Text, Py_ssize_t TextLen,
|
||
int AbsBase) {
|
||
Token *SubToks = NULL;
|
||
int NSub = 0;
|
||
if (!TokenizeText(Text, TextLen, &SubToks, &NSub, NULL, NULL)) {
|
||
return NULL;
|
||
}
|
||
for (int I = 0; I < NSub; I++) {
|
||
Token *T = &SubToks[I];
|
||
T->StartOff += AbsBase;
|
||
T->EndOff += AbsBase;
|
||
PosInfoLS(P->LineStarts, P->NLineStarts, T->StartOff, &T->Line, &T->Col);
|
||
PosInfoLS(P->LineStarts, P->NLineStarts, T->EndOff, &T->EndLine, &T->EndCol);
|
||
}
|
||
int SavedIdx = P->Idx;
|
||
Token *SavedTokens = P->Tokens;
|
||
int SavedNTokens = P->NTokens;
|
||
P->Tokens = SubToks;
|
||
P->NTokens = NSub;
|
||
P->Idx = 0;
|
||
PyObject *Expr = ParseExpr(P);
|
||
P->Tokens = SavedTokens;
|
||
P->NTokens = SavedNTokens;
|
||
P->Idx = SavedIdx;
|
||
PyMem_Free(SubToks);
|
||
return Expr;
|
||
}
|
||
|
||
/* ================= 表达式(优先级链) ================= */
|
||
|
||
/* 完整表达式:lambda 或条件表达式 */
|
||
static PyObject *ParseExpr(Parser *P) {
|
||
if (AtName(P, "lambda")) {
|
||
return ParseLambda(P);
|
||
}
|
||
return ParseConditional(P);
|
||
}
|
||
|
||
/* testlist_star_expr:表达式或逗号分隔元组 */
|
||
static PyObject *ParseExprList(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *First = ParseExpr(P);
|
||
if (First == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!AtOp(P, ",")) {
|
||
return First;
|
||
}
|
||
PyObject *Elts = NewList();
|
||
if (Elts == NULL) {
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, First);
|
||
while (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
PyObject *E = ParseExpr(P);
|
||
if (E == NULL) {
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, E);
|
||
Py_DECREF(E);
|
||
}
|
||
Py_DECREF(First);
|
||
PyObject *Load = MakeCtx(P, "Load");
|
||
if (Load == NULL) {
|
||
Py_DECREF(Elts);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Elts, Load };
|
||
PyObject *Node = NewNode(P, "Tuple", Argv, 2);
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Load);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 条件表达式:disjunction ('if' disjunction 'else' expression)? */
|
||
static PyObject *ParseConditional(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Body = ParseDisjunction(P);
|
||
if (Body == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!AtName(P, "if")) {
|
||
return Body;
|
||
}
|
||
NextTok(P);
|
||
PyObject *Test = ParseDisjunction(P);
|
||
if (Test == NULL) {
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
if (!AtName(P, "else")) {
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Test);
|
||
SyntaxErrorAt(P, PeekTok(P, 0), "expected 'else'");
|
||
return NULL;
|
||
}
|
||
NextTok(P);
|
||
PyObject *Orelse = ParseExpr(P);
|
||
if (Orelse == NULL) {
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Test);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3] = { Test, Body, Orelse };
|
||
PyObject *Node = NewNode(P, "IfExp", Argv, 3);
|
||
Py_DECREF(Test);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Orelse);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* disjunction:conjunction ('or' conjunction)* */
|
||
static PyObject *ParseDisjunction(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Values = NewList();
|
||
if (Values == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *First = ParseConjunction(P);
|
||
if (First == NULL) {
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Values, First);
|
||
Py_DECREF(First);
|
||
for (;;) {
|
||
SkipNL(P);
|
||
if (!AtName(P, "or")) {
|
||
break;
|
||
}
|
||
NextTok(P);
|
||
PyObject *V = ParseConjunction(P);
|
||
if (V == NULL) {
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Values, V);
|
||
Py_DECREF(V);
|
||
}
|
||
if (PyList_GET_SIZE(Values) == 1) {
|
||
PyObject *Only = PyList_GET_ITEM(Values, 0);
|
||
Py_INCREF(Only);
|
||
Py_DECREF(Values);
|
||
return Only;
|
||
}
|
||
PyObject *Op = MakeSingleton(P, "Or");
|
||
if (Op == NULL) {
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Op, Values };
|
||
PyObject *Node = NewNode(P, "BoolOp", Argv, 2);
|
||
Py_DECREF(Op);
|
||
Py_DECREF(Values);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* conjunction:inversion ('and' inversion)* */
|
||
static PyObject *ParseConjunction(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Values = NewList();
|
||
if (Values == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *First = ParseInversion(P);
|
||
if (First == NULL) {
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Values, First);
|
||
Py_DECREF(First);
|
||
for (;;) {
|
||
SkipNL(P);
|
||
if (!AtName(P, "and")) {
|
||
break;
|
||
}
|
||
NextTok(P);
|
||
PyObject *V = ParseInversion(P);
|
||
if (V == NULL) {
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Values, V);
|
||
Py_DECREF(V);
|
||
}
|
||
if (PyList_GET_SIZE(Values) == 1) {
|
||
PyObject *Only = PyList_GET_ITEM(Values, 0);
|
||
Py_INCREF(Only);
|
||
Py_DECREF(Values);
|
||
return Only;
|
||
}
|
||
PyObject *Op = MakeSingleton(P, "And");
|
||
if (Op == NULL) {
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Op, Values };
|
||
PyObject *Node = NewNode(P, "BoolOp", Argv, 2);
|
||
Py_DECREF(Op);
|
||
Py_DECREF(Values);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* inversion:'not' inversion | comparison */
|
||
static PyObject *ParseInversion(Parser *P) {
|
||
SkipNL(P);
|
||
if (AtName(P, "not")) {
|
||
Token *Start = NextTok(P);
|
||
PyObject *Operand = ParseInversion(P);
|
||
if (Operand == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Op = MakeSingleton(P, "Not");
|
||
if (Op == NULL) {
|
||
Py_DECREF(Operand);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Op, Operand };
|
||
PyObject *Node = NewNode(P, "UnaryOp", Argv, 2);
|
||
Py_DECREF(Op);
|
||
Py_DECREF(Operand);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
return ParseComparison(P);
|
||
}
|
||
|
||
/* 比较运算符映射 */
|
||
static const char *CompareOpName(const char *S) {
|
||
if (strcmp(S, "<") == 0) return "Lt";
|
||
if (strcmp(S, ">") == 0) return "Gt";
|
||
if (strcmp(S, "<=") == 0) return "LtE";
|
||
if (strcmp(S, ">=") == 0) return "GtE";
|
||
if (strcmp(S, "==") == 0) return "Eq";
|
||
if (strcmp(S, "!=") == 0) return "NotEq";
|
||
return NULL;
|
||
}
|
||
|
||
/* comparison:bit_or (cmpop bit_or)* */
|
||
static PyObject *ParseComparison(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Left = ParseBitOr(P);
|
||
if (Left == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Ops = NewList();
|
||
PyObject *Comparators = NewList();
|
||
if (Ops == NULL || Comparators == NULL) {
|
||
Py_XDECREF(Ops);
|
||
Py_XDECREF(Comparators);
|
||
Py_DECREF(Left);
|
||
return NULL;
|
||
}
|
||
for (;;) {
|
||
SkipNL(P);
|
||
Token *T = PeekTok(P, 0);
|
||
const char *OpName = NULL;
|
||
if (T->Kind == TK_OP) {
|
||
/* 通过 TokIsOp 精确匹配(避免非 NUL 结尾比较),并消费操作符 token */
|
||
if (TokIsOp(T, "<")) { OpName = "Lt"; NextTok(P); }
|
||
else if (TokIsOp(T, ">")) { OpName = "Gt"; NextTok(P); }
|
||
else if (TokIsOp(T, "<=")) { OpName = "LtE"; NextTok(P); }
|
||
else if (TokIsOp(T, ">=")) { OpName = "GtE"; NextTok(P); }
|
||
else if (TokIsOp(T, "==")) { OpName = "Eq"; NextTok(P); }
|
||
else if (TokIsOp(T, "!=")) { OpName = "NotEq"; NextTok(P); }
|
||
}
|
||
if (OpName == NULL && T->Kind == TK_NAME && TokIsName(T, "is")) {
|
||
NextTok(P);
|
||
if (PeekTok(P, 0)->Kind == TK_NAME && TokIsName(PeekTok(P, 0), "not")) {
|
||
NextTok(P);
|
||
OpName = "IsNot";
|
||
} else {
|
||
OpName = "Is";
|
||
}
|
||
} else if (OpName == NULL && T->Kind == TK_NAME && TokIsName(T, "in")) {
|
||
NextTok(P);
|
||
OpName = "In";
|
||
} else if (OpName == NULL && T->Kind == TK_NAME && TokIsName(T, "not")
|
||
&& PeekTok(P, 1)->Kind == TK_NAME && TokIsName(PeekTok(P, 1), "in")) {
|
||
NextTok(P);
|
||
NextTok(P);
|
||
OpName = "NotIn";
|
||
}
|
||
if (OpName == NULL) {
|
||
break;
|
||
}
|
||
PyObject *Op = MakeSingleton(P, OpName);
|
||
if (Op == NULL) {
|
||
Py_DECREF(Ops);
|
||
Py_DECREF(Comparators);
|
||
Py_DECREF(Left);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Ops, Op);
|
||
Py_DECREF(Op);
|
||
PyObject *C = ParseBitOr(P);
|
||
if (C == NULL) {
|
||
Py_DECREF(Ops);
|
||
Py_DECREF(Comparators);
|
||
Py_DECREF(Left);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Comparators, C);
|
||
Py_DECREF(C);
|
||
}
|
||
if (PyList_GET_SIZE(Ops) == 0) {
|
||
Py_DECREF(Ops);
|
||
Py_DECREF(Comparators);
|
||
return Left;
|
||
}
|
||
PyObject *Argv[3] = { Left, Ops, Comparators };
|
||
PyObject *Node = NewNode(P, "Compare", Argv, 3);
|
||
Py_DECREF(Left);
|
||
Py_DECREF(Ops);
|
||
Py_DECREF(Comparators);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 二元运算通用循环:left = Parse lower; while op: right = Parse lower; BinOp */
|
||
typedef PyObject *(*ParseFunc)(Parser *P);
|
||
|
||
static PyObject *ParseBinLoop(Parser *P, ParseFunc Lower, const char *Op1,
|
||
const char *Op2, const char *Node1, const char *Node2) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Left = Lower(P);
|
||
if (Left == NULL) {
|
||
return NULL;
|
||
}
|
||
for (;;) {
|
||
SkipNL(P);
|
||
const char *OpName = NULL;
|
||
if (Op1 != NULL && AtOp(P, Op1)) {
|
||
OpName = Node1;
|
||
NextTok(P);
|
||
} else if (Op2 != NULL && AtOp(P, Op2)) {
|
||
OpName = Node2;
|
||
NextTok(P);
|
||
} else {
|
||
break;
|
||
}
|
||
PyObject *Right = Lower(P);
|
||
if (Right == NULL) {
|
||
Py_DECREF(Left);
|
||
return NULL;
|
||
}
|
||
PyObject *Op = MakeSingleton(P, OpName);
|
||
if (Op == NULL) {
|
||
Py_DECREF(Left);
|
||
Py_DECREF(Right);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3] = { Left, Op, Right };
|
||
PyObject *Node = NewNode(P, "BinOp", Argv, 3);
|
||
Py_DECREF(Op);
|
||
Py_DECREF(Right);
|
||
Py_DECREF(Left);
|
||
if (Node == NULL) {
|
||
return NULL;
|
||
}
|
||
FixLoc(P, Node, Start);
|
||
Left = Node;
|
||
}
|
||
return Left;
|
||
}
|
||
|
||
static PyObject *ParseBitOr(Parser *P) {
|
||
return ParseBinLoop(P, ParseBitXor, "|", NULL, "BitOr", NULL);
|
||
}
|
||
|
||
static PyObject *ParseBitXor(Parser *P) {
|
||
return ParseBinLoop(P, ParseBitAnd, "^", NULL, "BitXor", NULL);
|
||
}
|
||
|
||
static PyObject *ParseBitAnd(Parser *P) {
|
||
return ParseBinLoop(P, ParseShift, "&", NULL, "BitAnd", NULL);
|
||
}
|
||
|
||
static PyObject *ParseShift(Parser *P) {
|
||
return ParseBinLoop(P, ParseArith, "<<", ">>", "LShift", "RShift");
|
||
}
|
||
|
||
static PyObject *ParseArith(Parser *P) {
|
||
return ParseBinLoop(P, ParseTerm, "+", "-", "Add", "Sub");
|
||
}
|
||
|
||
/* term:factor (*|/|//|%|@ factor)* */
|
||
static PyObject *ParseTerm(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Left = ParseFactor(P);
|
||
if (Left == NULL) {
|
||
return NULL;
|
||
}
|
||
for (;;) {
|
||
SkipNL(P);
|
||
Token *T = PeekTok(P, 0);
|
||
const char *OpName = NULL;
|
||
if (T->Kind == TK_OP) {
|
||
if (TokIsOp(T, "*")) OpName = "Mult";
|
||
else if (TokIsOp(T, "/")) OpName = "Div";
|
||
else if (TokIsOp(T, "//")) OpName = "FloorDiv";
|
||
else if (TokIsOp(T, "%")) OpName = "Mod";
|
||
else if (TokIsOp(T, "@")) OpName = "MatMult";
|
||
}
|
||
if (OpName == NULL) {
|
||
break;
|
||
}
|
||
NextTok(P);
|
||
PyObject *Right = ParseFactor(P);
|
||
if (Right == NULL) {
|
||
Py_DECREF(Left);
|
||
return NULL;
|
||
}
|
||
PyObject *Op = MakeSingleton(P, OpName);
|
||
if (Op == NULL) {
|
||
Py_DECREF(Left);
|
||
Py_DECREF(Right);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3] = { Left, Op, Right };
|
||
PyObject *Node = NewNode(P, "BinOp", Argv, 3);
|
||
Py_DECREF(Op);
|
||
Py_DECREF(Right);
|
||
Py_DECREF(Left);
|
||
if (Node == NULL) {
|
||
return NULL;
|
||
}
|
||
FixLoc(P, Node, Start);
|
||
Left = Node;
|
||
}
|
||
return Left;
|
||
}
|
||
|
||
/* factor:+|-|~ factor | power */
|
||
static PyObject *ParseFactor(Parser *P) {
|
||
Token *T = PeekTok(P, 0);
|
||
if (T->Kind == TK_OP && (TokIsOp(T, "+") || TokIsOp(T, "-") || TokIsOp(T, "~"))) {
|
||
Token *Start = NextTok(P);
|
||
PyObject *Operand = ParseFactor(P);
|
||
if (Operand == NULL) {
|
||
return NULL;
|
||
}
|
||
const char *OpName = TokIsOp(Start, "+") ? "UAdd"
|
||
: (TokIsOp(Start, "-") ? "USub" : "Invert");
|
||
PyObject *Op = MakeSingleton(P, OpName);
|
||
if (Op == NULL) {
|
||
Py_DECREF(Operand);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Op, Operand };
|
||
PyObject *Node = NewNode(P, "UnaryOp", Argv, 2);
|
||
Py_DECREF(Op);
|
||
Py_DECREF(Operand);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
return ParsePower(P);
|
||
}
|
||
|
||
/* power:await_primary ('**' factor)? */
|
||
static PyObject *ParsePower(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Base = ParseAwaitPrimary(P);
|
||
if (Base == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!AtOp(P, "**")) {
|
||
return Base;
|
||
}
|
||
NextTok(P);
|
||
PyObject *Exp = ParseFactor(P);
|
||
if (Exp == NULL) {
|
||
Py_DECREF(Base);
|
||
return NULL;
|
||
}
|
||
PyObject *Op = MakeSingleton(P, "Pow");
|
||
if (Op == NULL) {
|
||
Py_DECREF(Base);
|
||
Py_DECREF(Exp);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3] = { Base, Op, Exp };
|
||
PyObject *Node = NewNode(P, "BinOp", Argv, 3);
|
||
Py_DECREF(Op);
|
||
Py_DECREF(Exp);
|
||
Py_DECREF(Base);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* await_primary:'await' primary | primary */
|
||
static PyObject *ParseAwaitPrimary(Parser *P) {
|
||
if (AtName(P, "await")) {
|
||
Token *Start = NextTok(P);
|
||
PyObject *Value = ParsePrimary(P);
|
||
if (Value == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[1] = { Value };
|
||
PyObject *Node = NewNode(P, "Await", Argv, 1);
|
||
Py_DECREF(Value);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
return ParsePrimary(P);
|
||
}
|
||
|
||
/* 调用尾部:'(' [args] ')' */
|
||
static PyObject *ParseCallTail(Parser *P, PyObject *Func, Token *Start) {
|
||
if (!ExpectOp(P, "(")) {
|
||
return NULL;
|
||
}
|
||
PyObject *Args = NewList();
|
||
PyObject *Keywords = NewList();
|
||
if (Args == NULL || Keywords == NULL) {
|
||
Py_XDECREF(Args);
|
||
Py_XDECREF(Keywords);
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
if (!AtOp(P, ")")) {
|
||
for (;;) {
|
||
SkipNL(P);
|
||
if (AtOp(P, "**")) {
|
||
NextTok(P);
|
||
PyObject *Value = ParseExpr(P);
|
||
if (Value == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Keywords);
|
||
return NULL;
|
||
}
|
||
PyObject *Kw = MakeKeyword(P, NULL, Value, PrevTok(P));
|
||
Py_DECREF(Value);
|
||
if (Kw == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Keywords);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Keywords, Kw);
|
||
Py_DECREF(Kw);
|
||
} else {
|
||
if (AtOp(P, "*")) {
|
||
NextTok(P);
|
||
PyObject *Value = ParseExpr(P);
|
||
if (Value == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Keywords);
|
||
return NULL;
|
||
}
|
||
PyObject *Starred = MakeStarred(P, Value);
|
||
Py_DECREF(Value);
|
||
if (Starred == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Keywords);
|
||
return NULL;
|
||
}
|
||
FixLoc(P, Starred, PrevTok(P));
|
||
PyList_Append(Args, Starred);
|
||
Py_DECREF(Starred);
|
||
} else {
|
||
Token *T0 = PeekTok(P, 0);
|
||
Token *T1 = PeekTok(P, 1);
|
||
if (T0->Kind == TK_NAME && T1->Kind == TK_OP && TokIsOp(T1, "=")) {
|
||
Token *NameTok = NextTok(P);
|
||
NextTok(P); /* '=' */
|
||
PyObject *Value = ParseExpr(P);
|
||
if (Value == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Keywords);
|
||
return NULL;
|
||
}
|
||
PyObject *Arg = PyUnicode_FromStringAndSize(NameTok->Start,
|
||
NameTok->End - NameTok->Start);
|
||
PyObject *Kw = MakeKeyword(P, Arg, Value, NameTok);
|
||
Py_XDECREF(Arg);
|
||
Py_DECREF(Value);
|
||
if (Kw == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Keywords);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Keywords, Kw);
|
||
Py_DECREF(Kw);
|
||
} else {
|
||
if (PyList_GET_SIZE(Args) == 0 && PyList_GET_SIZE(Keywords) == 0) {
|
||
Token *GenStart = PeekTok(P, 0);
|
||
PyObject *GenElt = ParseExpr(P);
|
||
if (GenElt == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Keywords);
|
||
return NULL;
|
||
}
|
||
if (AtName(P, "for")) {
|
||
PyObject *GenGens = ParseComprehensionGenerators(P);
|
||
if (GenGens == NULL) {
|
||
Py_DECREF(GenElt);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Keywords);
|
||
return NULL;
|
||
}
|
||
PyObject *GArgv[2] = { GenElt, GenGens };
|
||
PyObject *Gen = NewNode(P, "GeneratorExp", GArgv, 2);
|
||
Py_DECREF(GenGens);
|
||
Py_DECREF(GenElt);
|
||
if (Gen == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Keywords);
|
||
return NULL;
|
||
}
|
||
FixLoc(P, Gen, GenStart);
|
||
PyList_Append(Args, Gen);
|
||
Py_DECREF(Gen);
|
||
} else {
|
||
PyList_Append(Args, GenElt);
|
||
Py_DECREF(GenElt);
|
||
}
|
||
} else {
|
||
PyObject *E = ParseExpr(P);
|
||
if (E == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Keywords);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Args, E);
|
||
Py_DECREF(E);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
SkipNL(P);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
if (AtOp(P, ")")) {
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (!ExpectOp(P, ")")) {
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Keywords);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3] = { Func, Args, Keywords };
|
||
PyObject *Node = NewNode(P, "Call", Argv, 3);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Keywords);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
static PyObject *ParseSliceList(Parser *P);
|
||
static PyObject *ParseSliceItem(Parser *P);
|
||
|
||
/* 下标尾部:'[' slice_list ']' */
|
||
static PyObject *ParseSubscriptTail(Parser *P, PyObject *Value, Token *Start) {
|
||
if (!ExpectOp(P, "[")) {
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
PyObject *SliceNode = ParseSliceList(P);
|
||
if (SliceNode == NULL) {
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
if (!ExpectOp(P, "]")) {
|
||
Py_DECREF(SliceNode);
|
||
return NULL;
|
||
}
|
||
PyObject *Load = MakeCtx(P, "Load");
|
||
if (Load == NULL) {
|
||
Py_DECREF(SliceNode);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3] = { Value, SliceNode, Load };
|
||
PyObject *Node = NewNode(P, "Subscript", Argv, 3);
|
||
Py_DECREF(SliceNode);
|
||
Py_DECREF(Load);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
static PyObject *ParseSliceList(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Elts = NewList();
|
||
if (Elts == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *First = ParseSliceItem(P);
|
||
if (First == NULL) {
|
||
Py_DECREF(Elts);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, First);
|
||
while (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
PyObject *E = ParseSliceItem(P);
|
||
if (E == NULL) {
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, E);
|
||
Py_DECREF(E);
|
||
}
|
||
if (PyList_GET_SIZE(Elts) == 1) {
|
||
Py_DECREF(Elts);
|
||
return First;
|
||
}
|
||
Py_DECREF(First);
|
||
PyObject *Load = MakeCtx(P, "Load");
|
||
if (Load == NULL) {
|
||
Py_DECREF(Elts);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Elts, Load };
|
||
PyObject *Node = NewNode(P, "Tuple", Argv, 2);
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Load);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
static PyObject *ParseSliceItem(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
if (AtOp(P, ":")) {
|
||
NextTok(P);
|
||
PyObject *Upper = NULL;
|
||
if (!AtOp(P, ":") && !AtOp(P, ",")) {
|
||
if (!AtOp(P, "]")) {
|
||
Upper = ParseExpr(P);
|
||
if (Upper == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
}
|
||
PyObject *Step = NULL;
|
||
if (AtOp(P, ":")) {
|
||
NextTok(P);
|
||
if (!AtOp(P, "]") && !AtOp(P, ",") && !AtOp(P, ":")) {
|
||
Step = ParseExpr(P);
|
||
if (Step == NULL) {
|
||
Py_XDECREF(Upper);
|
||
return NULL;
|
||
}
|
||
}
|
||
}
|
||
PyObject *Argv[3] = { Py_None, Upper ? Upper : Py_None, Step ? Step : Py_None };
|
||
PyObject *Node = NewNode(P, "Slice", Argv, 3);
|
||
Py_XDECREF(Upper);
|
||
Py_XDECREF(Step);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
PyObject *First = ParseExpr(P);
|
||
if (First == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!AtOp(P, ":")) {
|
||
return First;
|
||
}
|
||
NextTok(P);
|
||
PyObject *Lower = First;
|
||
PyObject *Upper = NULL;
|
||
PyObject *Step = NULL;
|
||
if (!AtOp(P, ":") && !AtOp(P, "]") && !AtOp(P, ",")) {
|
||
Upper = ParseExpr(P);
|
||
if (Upper == NULL) {
|
||
Py_DECREF(Lower);
|
||
return NULL;
|
||
}
|
||
}
|
||
if (AtOp(P, ":")) {
|
||
NextTok(P);
|
||
if (!AtOp(P, "]") && !AtOp(P, ",")) {
|
||
Step = ParseExpr(P);
|
||
if (Step == NULL) {
|
||
Py_DECREF(Lower);
|
||
Py_XDECREF(Upper);
|
||
return NULL;
|
||
}
|
||
}
|
||
}
|
||
PyObject *Argv[3] = { Lower, Upper ? Upper : Py_None, Step ? Step : Py_None };
|
||
PyObject *Node = NewNode(P, "Slice", Argv, 3);
|
||
Py_DECREF(Lower);
|
||
Py_XDECREF(Upper);
|
||
Py_XDECREF(Step);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 主表达式:原子 + trailer(属性/调用/下标) */
|
||
static PyObject *ParsePrimary(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Node = ParseAtom(P);
|
||
if (Node == NULL) {
|
||
return NULL;
|
||
}
|
||
for (;;) {
|
||
SkipNL(P);
|
||
Token *T = PeekTok(P, 0);
|
||
if (T->Kind == TK_OP && TokIsOp(T, ".")) {
|
||
NextTok(P);
|
||
Token *AttrTok = ExpectName(P, NULL);
|
||
if (AttrTok == NULL) {
|
||
Py_DECREF(Node);
|
||
return NULL;
|
||
}
|
||
PyObject *NewNode2 = MakeAttrNode(P, Node, AttrTok, Start);
|
||
Py_DECREF(Node);
|
||
if (NewNode2 == NULL) {
|
||
return NULL;
|
||
}
|
||
Node = NewNode2;
|
||
} else if (T->Kind == TK_OP && TokIsOp(T, "(")) {
|
||
PyObject *Call = ParseCallTail(P, Node, Start);
|
||
Py_DECREF(Node);
|
||
if (Call == NULL) {
|
||
return NULL;
|
||
}
|
||
Node = Call;
|
||
} else if (T->Kind == TK_OP && TokIsOp(T, "[")) {
|
||
PyObject *Sub = ParseSubscriptTail(P, Node, Start);
|
||
Py_DECREF(Node);
|
||
if (Sub == NULL) {
|
||
return NULL;
|
||
}
|
||
Node = Sub;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 数字常量 */
|
||
static PyObject *ParseNumber(Parser *P) {
|
||
Token *T = NextTok(P);
|
||
PyObject *Val = ParseNumberValue(P, T);
|
||
if (Val == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Node = MakeConstantPos(P, Val, T);
|
||
Py_DECREF(Val);
|
||
return Node;
|
||
}
|
||
|
||
/* 原子表达式 */
|
||
static PyObject *ParseAtom(Parser *P) {
|
||
SkipNL(P);
|
||
Token *T = PeekTok(P, 0);
|
||
if (T->Kind == TK_NUMBER) {
|
||
return ParseNumber(P);
|
||
}
|
||
if (T->Kind == TK_STRING || T->Kind == TK_FSTRING) {
|
||
return ParseStringConcat(P);
|
||
}
|
||
if (T->Kind == TK_NAME) {
|
||
if (TokIsName(T, "True") || TokIsName(T, "False") || TokIsName(T, "None")) {
|
||
NextTok(P);
|
||
PyObject *Val = TokIsName(T, "True") ? Py_True
|
||
: (TokIsName(T, "False") ? Py_False : Py_None);
|
||
PyObject *Node = MakeConstantPos(P, Val, T);
|
||
return Node;
|
||
}
|
||
NextTok(P); /* 必须消费名字 token,否则上层循环死循环(idx 不前) */
|
||
return MakeNameNode(P, T, "Load");
|
||
}
|
||
if (T->Kind == TK_OP) {
|
||
if (TokIsOp(T, "(")) {
|
||
return ParseParen(P);
|
||
}
|
||
if (TokIsOp(T, "[")) {
|
||
return ParseList(P);
|
||
}
|
||
if (TokIsOp(T, "{")) {
|
||
return ParseDictSet(P);
|
||
}
|
||
if (TokIsOp(T, "...")) {
|
||
NextTok(P);
|
||
return MakeConstantPos(P, Py_Ellipsis, T);
|
||
}
|
||
}
|
||
SyntaxErrorAt(P, T, "unexpected token");
|
||
return NULL;
|
||
}
|
||
|
||
/* 括号:空元组 / yield / walrus / 生成器表达式 / 元组 / 普通表达式 */
|
||
static PyObject *ParseParen(Parser *P) {
|
||
Token *Start = NextTok(P); /* '(' */
|
||
SkipNL(P);
|
||
if (AtOp(P, ")")) {
|
||
NextTok(P);
|
||
PyObject *Load = MakeCtx(P, "Load");
|
||
if (Load == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Empty = NewList();
|
||
if (Empty == NULL) {
|
||
Py_DECREF(Load);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Empty, Load };
|
||
PyObject *Node = NewNode(P, "Tuple", Argv, 2);
|
||
Py_DECREF(Empty);
|
||
Py_DECREF(Load);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
if (AtName(P, "yield")) {
|
||
PyObject *YieldNode = ParseYield(P);
|
||
if (YieldNode == NULL) {
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
if (!ExpectOp(P, ")")) {
|
||
Py_DECREF(YieldNode);
|
||
return NULL;
|
||
}
|
||
return YieldNode;
|
||
}
|
||
Token *T0 = PeekTok(P, 0);
|
||
Token *T1 = PeekTok(P, 1);
|
||
if (T0->Kind == TK_NAME && T1->Kind == TK_OP && TokIsOp(T1, ":=")) {
|
||
Token *NameTok = NextTok(P);
|
||
NextTok(P); /* ':=' */
|
||
PyObject *Value = ParseExpr(P);
|
||
if (Value == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Target = MakeNameNode(P, NameTok, "Store");
|
||
if (Target == NULL) {
|
||
Py_DECREF(Value);
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
if (!ExpectOp(P, ")")) {
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Value);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Target, Value };
|
||
PyObject *Node = NewNode(P, "NamedExpr", Argv, 2);
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Value);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
PyObject *First = ParseExpr(P);
|
||
if (First == NULL) {
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
if (AtName(P, "for")) {
|
||
PyObject *Generators = ParseComprehensionGenerators(P);
|
||
if (Generators == NULL) {
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
if (!ExpectOp(P, ")")) {
|
||
Py_DECREF(Generators);
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { First, Generators };
|
||
PyObject *Gen = NewNode(P, "GeneratorExp", Argv, 2);
|
||
Py_DECREF(Generators);
|
||
Py_DECREF(First);
|
||
if (Gen != NULL) {
|
||
FixLoc(P, Gen, Start);
|
||
}
|
||
return Gen;
|
||
}
|
||
if (AtOp(P, ",")) {
|
||
PyObject *Elts = NewList();
|
||
if (Elts == NULL) {
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, First);
|
||
while (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
if (AtOp(P, ")")) {
|
||
break;
|
||
}
|
||
PyObject *E = ParseExpr(P);
|
||
if (E == NULL) {
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, E);
|
||
Py_DECREF(E);
|
||
SkipNL(P);
|
||
}
|
||
if (!ExpectOp(P, ")")) {
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
Py_DECREF(First);
|
||
PyObject *Load = MakeCtx(P, "Load");
|
||
if (Load == NULL) {
|
||
Py_DECREF(Elts);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Elts, Load };
|
||
PyObject *Node = NewNode(P, "Tuple", Argv, 2);
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Load);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
if (!ExpectOp(P, ")")) {
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
return First;
|
||
}
|
||
|
||
/* 列表字面量 / 列表推导式 */
|
||
static PyObject *ParseList(Parser *P) {
|
||
Token *Start = NextTok(P); /* '[' */
|
||
SkipNL(P);
|
||
if (AtOp(P, "]")) {
|
||
NextTok(P);
|
||
PyObject *Load = MakeCtx(P, "Load");
|
||
if (Load == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Empty = NewList();
|
||
if (Empty == NULL) {
|
||
Py_DECREF(Load);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Empty, Load };
|
||
PyObject *Node = NewNode(P, "List", Argv, 2);
|
||
Py_DECREF(Empty);
|
||
Py_DECREF(Load);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
PyObject *First = ParseExpr(P);
|
||
if (First == NULL) {
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
if (AtName(P, "for")) {
|
||
PyObject *Generators = ParseComprehensionGenerators(P);
|
||
if (Generators == NULL) {
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
if (!ExpectOp(P, "]")) {
|
||
Py_DECREF(Generators);
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { First, Generators };
|
||
PyObject *Lc = NewNode(P, "ListComp", Argv, 2);
|
||
Py_DECREF(Generators);
|
||
Py_DECREF(First);
|
||
if (Lc != NULL) {
|
||
FixLoc(P, Lc, Start);
|
||
}
|
||
return Lc;
|
||
}
|
||
PyObject *Elts = NewList();
|
||
if (Elts == NULL) {
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, First);
|
||
while (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
if (AtOp(P, "]")) {
|
||
break;
|
||
}
|
||
PyObject *E = ParseExpr(P);
|
||
if (E == NULL) {
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, E);
|
||
Py_DECREF(E);
|
||
SkipNL(P);
|
||
}
|
||
if (!ExpectOp(P, "]")) {
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
Py_DECREF(First);
|
||
PyObject *Load = MakeCtx(P, "Load");
|
||
if (Load == NULL) {
|
||
Py_DECREF(Elts);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Elts, Load };
|
||
PyObject *Node = NewNode(P, "List", Argv, 2);
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Load);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 字典 / 集合字面量与推导式 */
|
||
static PyObject *ParseDictSet(Parser *P) {
|
||
Token *Start = NextTok(P); /* '{' */
|
||
SkipNL(P);
|
||
if (AtOp(P, "}")) {
|
||
NextTok(P);
|
||
PyObject *Keys = NewList();
|
||
PyObject *Values = NewList();
|
||
if (Keys == NULL || Values == NULL) {
|
||
Py_XDECREF(Keys);
|
||
Py_XDECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Keys, Values };
|
||
PyObject *Node = NewNode(P, "Dict", Argv, 2);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
PyObject *Keys = NewList();
|
||
PyObject *Values = NewList();
|
||
if (Keys == NULL || Values == NULL) {
|
||
Py_XDECREF(Keys);
|
||
Py_XDECREF(Values);
|
||
return NULL;
|
||
}
|
||
for (;;) {
|
||
SkipNL(P);
|
||
if (AtOp(P, "**")) {
|
||
NextTok(P);
|
||
PyObject *Val = ParseExpr(P);
|
||
if (Val == NULL) {
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Keys, Py_None);
|
||
PyList_Append(Values, Val);
|
||
Py_DECREF(Val);
|
||
} else {
|
||
PyObject *Key = ParseExpr(P);
|
||
if (Key == NULL) {
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
if (AtOp(P, ":")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
PyObject *Value = ParseExpr(P);
|
||
if (Value == NULL) {
|
||
Py_DECREF(Key);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Keys, Key);
|
||
PyList_Append(Values, Value);
|
||
Py_DECREF(Value);
|
||
Py_DECREF(Key);
|
||
} else {
|
||
/* 集合元素 */
|
||
PyObject *Elts = NewList();
|
||
if (Elts == NULL) {
|
||
Py_DECREF(Key);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, Key);
|
||
Py_DECREF(Key);
|
||
while (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
if (AtOp(P, "}")) {
|
||
break;
|
||
}
|
||
PyObject *E = ParseExpr(P);
|
||
if (E == NULL) {
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, E);
|
||
Py_DECREF(E);
|
||
SkipNL(P);
|
||
}
|
||
SkipNL(P);
|
||
if (AtName(P, "for")) {
|
||
PyObject *Generators = ParseComprehensionGenerators(P);
|
||
if (Generators == NULL) {
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
if (!ExpectOp(P, "}")) {
|
||
Py_DECREF(Generators);
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyObject *Elt0 = PyList_GET_ITEM(Elts, 0);
|
||
Py_INCREF(Elt0);
|
||
PyObject *Argv[2] = { Elt0, Generators };
|
||
PyObject *Sc = NewNode(P, "SetComp", Argv, 2);
|
||
Py_DECREF(Elt0);
|
||
Py_DECREF(Generators);
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
if (Sc != NULL) {
|
||
FixLoc(P, Sc, Start);
|
||
}
|
||
return Sc;
|
||
}
|
||
if (!ExpectOp(P, "}")) {
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[1] = { Elts };
|
||
PyObject *St = NewNode(P, "Set", Argv, 1);
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
if (St != NULL) {
|
||
FixLoc(P, St, Start);
|
||
}
|
||
return St;
|
||
}
|
||
}
|
||
SkipNL(P);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
if (AtOp(P, "}")) {
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
/* 字典推导式 */
|
||
SkipNL(P);
|
||
if (AtName(P, "for")) {
|
||
PyObject *Generators = ParseComprehensionGenerators(P);
|
||
if (Generators == NULL) {
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
if (!ExpectOp(P, "}")) {
|
||
Py_DECREF(Generators);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyObject *Key0 = PyList_GET_ITEM(Keys, 0);
|
||
PyObject *Val0 = PyList_GET_ITEM(Values, 0);
|
||
PyObject *KeyObj;
|
||
if (Key0 == Py_None) {
|
||
KeyObj = MakeConstant(P, Py_None);
|
||
if (KeyObj == NULL) {
|
||
Py_DECREF(Generators);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
} else {
|
||
KeyObj = Key0;
|
||
Py_INCREF(KeyObj);
|
||
}
|
||
Py_INCREF(Val0);
|
||
PyObject *Argv[3] = { KeyObj, Val0, Generators };
|
||
PyObject *Dc = NewNode(P, "DictComp", Argv, 3);
|
||
Py_DECREF(KeyObj);
|
||
Py_DECREF(Val0);
|
||
Py_DECREF(Generators);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
if (Dc != NULL) {
|
||
FixLoc(P, Dc, Start);
|
||
}
|
||
return Dc;
|
||
}
|
||
if (!ExpectOp(P, "}")) {
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Keys, Values };
|
||
PyObject *Node = NewNode(P, "Dict", Argv, 2);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Values);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 推导式生成器子句:for target in iter [if cond]* [async for ...] */
|
||
static PyObject *ParseComprehensionGenerators(Parser *P) {
|
||
PyObject *Generators = NewList();
|
||
if (Generators == NULL) {
|
||
return NULL;
|
||
}
|
||
for (;;) {
|
||
int IsAsync = 0;
|
||
if (AtName(P, "async") && PeekTok(P, 1)->Kind == TK_NAME
|
||
&& TokIsName(PeekTok(P, 1), "for")) {
|
||
NextTok(P);
|
||
IsAsync = 1;
|
||
}
|
||
if (!AtName(P, "for")) {
|
||
break;
|
||
}
|
||
Token *Start = NextTok(P);
|
||
PyObject *Target = ParseComprehensionTarget(P);
|
||
if (Target == NULL) {
|
||
Py_DECREF(Generators);
|
||
return NULL;
|
||
}
|
||
if (!ExpectName(P, "in")) {
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Generators);
|
||
return NULL;
|
||
}
|
||
PyObject *Iterable = ParseDisjunction(P);
|
||
if (Iterable == NULL) {
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Generators);
|
||
return NULL;
|
||
}
|
||
PyObject *Ifs = NewList();
|
||
if (Ifs == NULL) {
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Iterable);
|
||
Py_DECREF(Generators);
|
||
return NULL;
|
||
}
|
||
while (AtName(P, "if")) {
|
||
NextTok(P);
|
||
PyObject *Cond = ParseDisjunction(P);
|
||
if (Cond == NULL) {
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Iterable);
|
||
Py_DECREF(Ifs);
|
||
Py_DECREF(Generators);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Ifs, Cond);
|
||
Py_DECREF(Cond);
|
||
}
|
||
PyObject *IsAsyncObj = PyLong_FromLong(IsAsync);
|
||
PyObject *Argv[4] = { Target, Iterable, Ifs, IsAsyncObj };
|
||
PyObject *Comp = NewNode(P, "comprehension", Argv, 4);
|
||
Py_DECREF(IsAsyncObj);
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Iterable);
|
||
Py_DECREF(Ifs);
|
||
if (Comp == NULL) {
|
||
Py_DECREF(Generators);
|
||
return NULL;
|
||
}
|
||
/* comprehension 无位置属性,不调用 FixLoc */
|
||
(void)Start;
|
||
PyList_Append(Generators, Comp);
|
||
Py_DECREF(Comp);
|
||
if (AtName(P, "for") || (AtName(P, "async") && PeekTok(P, 1)->Kind == TK_NAME
|
||
&& TokIsName(PeekTok(P, 1), "for"))) {
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
return Generators;
|
||
}
|
||
|
||
/* 推导式 for 目标(支持裸元组解包) */
|
||
static PyObject *ParseComprehensionTarget(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *First = ParseTarget(P);
|
||
if (First == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!AtOp(P, ",")) {
|
||
return First;
|
||
}
|
||
PyObject *Elts = NewList();
|
||
if (Elts == NULL) {
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, First);
|
||
while (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
PyObject *E = ParseTarget(P);
|
||
if (E == NULL) {
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, E);
|
||
Py_DECREF(E);
|
||
}
|
||
Py_DECREF(First);
|
||
PyObject *Store = MakeCtx(P, "Store");
|
||
if (Store == NULL) {
|
||
Py_DECREF(Elts);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Elts, Store };
|
||
PyObject *Node = NewNode(P, "Tuple", Argv, 2);
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Store);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 赋值目标(Store 上下文) */
|
||
static PyObject *ParseTarget(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
if (AtOp(P, "(")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
PyObject *Elts = NewList();
|
||
if (Elts == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!AtOp(P, ")")) {
|
||
for (;;) {
|
||
PyObject *E = ParseTarget(P);
|
||
if (E == NULL) {
|
||
Py_DECREF(Elts);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, E);
|
||
Py_DECREF(E);
|
||
SkipNL(P);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
if (AtOp(P, ")")) {
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (!ExpectOp(P, ")")) {
|
||
Py_DECREF(Elts);
|
||
return NULL;
|
||
}
|
||
PyObject *Store = MakeCtx(P, "Store");
|
||
if (Store == NULL) {
|
||
Py_DECREF(Elts);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Elts, Store };
|
||
PyObject *Node = NewNode(P, "Tuple", Argv, 2);
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Store);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
if (AtOp(P, "[")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
PyObject *Elts = NewList();
|
||
if (Elts == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!AtOp(P, "]")) {
|
||
for (;;) {
|
||
PyObject *E = ParseTarget(P);
|
||
if (E == NULL) {
|
||
Py_DECREF(Elts);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, E);
|
||
Py_DECREF(E);
|
||
SkipNL(P);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
if (AtOp(P, "]")) {
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (!ExpectOp(P, "]")) {
|
||
Py_DECREF(Elts);
|
||
return NULL;
|
||
}
|
||
PyObject *Store = MakeCtx(P, "Store");
|
||
if (Store == NULL) {
|
||
Py_DECREF(Elts);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Elts, Store };
|
||
PyObject *Node = NewNode(P, "List", Argv, 2);
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Store);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
if (AtOp(P, "*")) {
|
||
NextTok(P);
|
||
PyObject *Value = ParseTarget(P);
|
||
if (Value == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Store = MakeCtx(P, "Store");
|
||
if (Store == NULL) {
|
||
Py_DECREF(Value);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Value, Store };
|
||
PyObject *Node = NewNode(P, "Starred", Argv, 2);
|
||
Py_DECREF(Value);
|
||
Py_DECREF(Store);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
Token *T = PeekTok(P, 0);
|
||
if (T->Kind == TK_NAME) {
|
||
NextTok(P); /* 必须消费名字 token */
|
||
return MakeNameNode(P, T, "Store");
|
||
}
|
||
/* 属性/下标目标:解析 Load 后改 Store */
|
||
PyObject *Node = ParsePrimary(P);
|
||
if (Node == NULL) {
|
||
return NULL;
|
||
}
|
||
SetStoreContext(P, Node);
|
||
return Node;
|
||
}
|
||
|
||
/* lambda */
|
||
static PyObject *ParseLambda(Parser *P) {
|
||
Token *Start = NextTok(P); /* 'lambda' */
|
||
PyObject *Args;
|
||
if (AtOp(P, ":")) {
|
||
PyObject *E1 = NewList();
|
||
PyObject *E2 = NewList();
|
||
if (E1 == NULL || E2 == NULL) {
|
||
Py_XDECREF(E1);
|
||
Py_XDECREF(E2);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[7];
|
||
Argv[0] = E1; /* posonlyargs */
|
||
Argv[1] = E2; /* args */
|
||
Argv[2] = Py_None; /* vararg */
|
||
Argv[3] = NewList(); /* kwonlyargs */
|
||
Argv[4] = NewList(); /* kw_defaults */
|
||
Argv[5] = Py_None; /* kwarg */
|
||
Argv[6] = NewList(); /* defaults */
|
||
if (Argv[3] == NULL || Argv[4] == NULL || Argv[6] == NULL) {
|
||
Py_XDECREF(E1);
|
||
Py_XDECREF(E2);
|
||
Py_XDECREF(Argv[3]);
|
||
Py_XDECREF(Argv[4]);
|
||
Py_XDECREF(Argv[6]);
|
||
return NULL;
|
||
}
|
||
Args = NewNode(P, "arguments", Argv, 7);
|
||
Py_DECREF(E1);
|
||
Py_DECREF(E2);
|
||
Py_DECREF(Argv[3]);
|
||
Py_DECREF(Argv[4]);
|
||
Py_DECREF(Argv[6]);
|
||
if (Args == NULL) {
|
||
return NULL;
|
||
}
|
||
} else {
|
||
Args = ParseArguments(P, 1, 1);
|
||
if (Args == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Args);
|
||
return NULL;
|
||
}
|
||
PyObject *Body = ParseExpr(P);
|
||
if (Body == NULL) {
|
||
Py_DECREF(Args);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Args, Body };
|
||
PyObject *Node = NewNode(P, "Lambda", Argv, 2);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Body);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* yield 表达式 */
|
||
static PyObject *ParseYield(Parser *P) {
|
||
Token *Start = NextTok(P); /* 'yield' */
|
||
if (AtName(P, "from")) {
|
||
NextTok(P);
|
||
PyObject *Value = ParseExpr(P);
|
||
if (Value == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[1] = { Value };
|
||
PyObject *Node = NewNode(P, "YieldFrom", Argv, 1);
|
||
Py_DECREF(Value);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
if (AtOp(P, ")")) {
|
||
PyObject *Node = NewNode(P, "Yield", (PyObject *[]){ Py_None }, 1);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
PyObject *Value = ParseExprList(P);
|
||
if (Value == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[1] = { Value };
|
||
PyObject *Node = NewNode(P, "Yield", Argv, 1);
|
||
Py_DECREF(Value);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 参数列表(lambda 与函数定义共用) */
|
||
static PyObject *ParseArguments(Parser *P, int SkipOpen, int AllowLambda) {
|
||
if (!SkipOpen) {
|
||
if (!ExpectOp(P, "(")) {
|
||
return NULL;
|
||
}
|
||
}
|
||
SkipNL(P);
|
||
PyObject *PosonlyArgs = NewList();
|
||
PyObject *Args = NewList();
|
||
PyObject *KwonlyArgs = NewList();
|
||
PyObject *KwDefaults = NewList();
|
||
PyObject *OrderedArgs = NewList();
|
||
PyObject *OrderedDefaults = NewList();
|
||
PyObject *Vararg = NULL;
|
||
PyObject *Kwarg = NULL;
|
||
if (PosonlyArgs == NULL || Args == NULL || KwonlyArgs == NULL
|
||
|| KwDefaults == NULL || OrderedArgs == NULL || OrderedDefaults == NULL) {
|
||
Py_XDECREF(PosonlyArgs);
|
||
Py_XDECREF(Args);
|
||
Py_XDECREF(KwonlyArgs);
|
||
Py_XDECREF(KwDefaults);
|
||
Py_XDECREF(OrderedArgs);
|
||
Py_XDECREF(OrderedDefaults);
|
||
return NULL;
|
||
}
|
||
int SeenStar = 0;
|
||
if (!AtOp(P, ")")) {
|
||
for (;;) {
|
||
SkipNL(P);
|
||
Token *T = PeekTok(P, 0);
|
||
if (TokIsOp(T, ")")) {
|
||
break;
|
||
}
|
||
if (TokIsOp(T, "*")) {
|
||
NextTok(P);
|
||
if (AtOp(P, ",")) {
|
||
SeenStar = 1;
|
||
NextTok(P);
|
||
if (AtOp(P, ")") || AtOp(P, ":")) {
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
Vararg = ParseArg(P, !AllowLambda);
|
||
if (Vararg == NULL) {
|
||
Py_DECREF(PosonlyArgs);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(KwonlyArgs);
|
||
Py_DECREF(KwDefaults);
|
||
Py_DECREF(OrderedArgs);
|
||
Py_DECREF(OrderedDefaults);
|
||
return NULL;
|
||
}
|
||
SeenStar = 1;
|
||
} else if (TokIsOp(T, "**")) {
|
||
NextTok(P);
|
||
Kwarg = ParseArg(P, !AllowLambda);
|
||
if (Kwarg == NULL) {
|
||
Py_DECREF(PosonlyArgs);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(KwonlyArgs);
|
||
Py_DECREF(KwDefaults);
|
||
Py_DECREF(OrderedArgs);
|
||
Py_DECREF(OrderedDefaults);
|
||
return NULL;
|
||
}
|
||
} else {
|
||
PyObject *A = ParseArg(P, !AllowLambda);
|
||
if (A == NULL) {
|
||
Py_DECREF(PosonlyArgs);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(KwonlyArgs);
|
||
Py_DECREF(KwDefaults);
|
||
Py_DECREF(OrderedArgs);
|
||
Py_DECREF(OrderedDefaults);
|
||
return NULL;
|
||
}
|
||
PyObject *Def = Py_None;
|
||
if (AtOp(P, "=")) {
|
||
NextTok(P);
|
||
Def = ParseExpr(P);
|
||
if (Def == NULL) {
|
||
Py_DECREF(A);
|
||
Py_DECREF(PosonlyArgs);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(KwonlyArgs);
|
||
Py_DECREF(KwDefaults);
|
||
Py_DECREF(OrderedArgs);
|
||
Py_DECREF(OrderedDefaults);
|
||
return NULL;
|
||
}
|
||
}
|
||
if (SeenStar) {
|
||
PyList_Append(KwonlyArgs, A);
|
||
PyList_Append(KwDefaults, Def);
|
||
} else {
|
||
PyList_Append(OrderedArgs, A);
|
||
PyList_Append(OrderedDefaults, Def);
|
||
}
|
||
Py_DECREF(A);
|
||
Py_XDECREF(Def != Py_None ? Def : NULL);
|
||
}
|
||
SkipNL(P);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
if (AtOp(P, ")")) {
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
Py_ssize_t NOrdered = PyList_GET_SIZE(OrderedArgs);
|
||
int LastNone = -1;
|
||
for (Py_ssize_t I = 0; I < NOrdered; I++) {
|
||
if (PyList_GET_ITEM(OrderedDefaults, I) == Py_None) {
|
||
LastNone = (int)I;
|
||
}
|
||
}
|
||
for (Py_ssize_t I = 0; I < NOrdered; I++) {
|
||
PyList_Append(Args, PyList_GET_ITEM(OrderedArgs, I));
|
||
}
|
||
PyObject *Defaults = NewList();
|
||
if (Defaults == NULL) {
|
||
Py_DECREF(PosonlyArgs);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(KwonlyArgs);
|
||
Py_DECREF(KwDefaults);
|
||
Py_DECREF(OrderedArgs);
|
||
Py_DECREF(OrderedDefaults);
|
||
Py_XDECREF(Vararg);
|
||
Py_XDECREF(Kwarg);
|
||
return NULL;
|
||
}
|
||
for (int I = LastNone + 1; I < (int)NOrdered; I++) {
|
||
PyObject *D = PyList_GET_ITEM(OrderedDefaults, I);
|
||
if (D != Py_None) {
|
||
PyList_Append(Defaults, D);
|
||
}
|
||
}
|
||
SkipNL(P);
|
||
if (!SkipOpen) {
|
||
if (!ExpectOp(P, ")")) {
|
||
Py_DECREF(PosonlyArgs);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(KwonlyArgs);
|
||
Py_DECREF(KwDefaults);
|
||
Py_DECREF(OrderedArgs);
|
||
Py_DECREF(OrderedDefaults);
|
||
Py_DECREF(Defaults);
|
||
Py_XDECREF(Vararg);
|
||
Py_XDECREF(Kwarg);
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Argv[7];
|
||
Argv[0] = PosonlyArgs;
|
||
Argv[1] = Args;
|
||
Argv[2] = Vararg ? Vararg : Py_None;
|
||
Argv[3] = KwonlyArgs;
|
||
Argv[4] = KwDefaults;
|
||
Argv[5] = Kwarg ? Kwarg : Py_None;
|
||
Argv[6] = Defaults;
|
||
PyObject *Node = NewNode(P, "arguments", Argv, 7);
|
||
Py_DECREF(PosonlyArgs);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(KwonlyArgs);
|
||
Py_DECREF(KwDefaults);
|
||
Py_DECREF(OrderedArgs);
|
||
Py_DECREF(OrderedDefaults);
|
||
Py_DECREF(Defaults);
|
||
Py_XDECREF(Vararg);
|
||
Py_XDECREF(Kwarg);
|
||
return Node;
|
||
}
|
||
|
||
/* 单个参数:name [':' annotation] */
|
||
static PyObject *ParseArg(Parser *P, int AllowAnnotation) {
|
||
Token *Start = ExpectName(P, NULL);
|
||
if (Start == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Annotation = NULL;
|
||
if (AllowAnnotation && AtOp(P, ":")) {
|
||
NextTok(P);
|
||
Annotation = ParseExpr(P);
|
||
if (Annotation == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Arg = PyUnicode_FromStringAndSize(Start->Start, Start->End - Start->Start);
|
||
if (Arg == NULL) {
|
||
Py_XDECREF(Annotation);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3] = { Arg, Annotation ? Annotation : Py_None, Py_None };
|
||
PyObject *Node = NewNode(P, "arg", Argv, 3);
|
||
Py_DECREF(Arg);
|
||
Py_XDECREF(Annotation);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* ================= 语句解析 ================= */
|
||
|
||
static PyObject *ParseStatement(Parser *P);
|
||
static PyObject *ParseSimpleStmt(Parser *P);
|
||
static PyObject *ParseSuite(Parser *P);
|
||
static PyObject *ParseIf(Parser *P);
|
||
static PyObject *ParseWhile(Parser *P);
|
||
static PyObject *ParseFor(Parser *P, int IsAsync);
|
||
static PyObject *ParseTry(Parser *P);
|
||
static PyObject *ParseWith(Parser *P, int IsAsync);
|
||
static PyObject *ParseMatch(Parser *P);
|
||
static PyObject *ParseFunctionDef(Parser *P, int IsAsync, PyObject *Decorators);
|
||
static PyObject *ParseClassDef(Parser *P, PyObject *Decorators);
|
||
static PyObject *ParseExprList(Parser *P);
|
||
static PyObject *ParseExternDef(Parser *P, int IsExport, PyObject *Decorators);
|
||
static PyObject *TryParseAnnAssign(Parser *P);
|
||
static PyObject *ParseExprStmt(Parser *P);
|
||
static PyObject *ParseImport(Parser *P);
|
||
static PyObject *ParseImportFrom(Parser *P);
|
||
static PyObject *ParseImportAlias(Parser *P);
|
||
static PyObject *ParseGlobal(Parser *P, const char *NodeName);
|
||
static PyObject *ParseDelete(Parser *P);
|
||
static PyObject *ParseAssert(Parser *P);
|
||
static PyObject *ParseDecorated(Parser *P);
|
||
static PyObject *ParseTypeParams(Parser *P);
|
||
static PyObject *ParseExceptHandler(Parser *P);
|
||
static PyObject *ParseTargetList(Parser *P);
|
||
|
||
/* 模块:语句序列 */
|
||
static PyObject *ParseModule(Parser *P) {
|
||
PyObject *Body = NewList();
|
||
if (Body == NULL) {
|
||
return NULL;
|
||
}
|
||
SkipNEWLINE(P);
|
||
while (PeekTok(P, 0)->Kind != TK_ENDMARKER) {
|
||
PyObject *Stmt = ParseStatement(P);
|
||
if (Stmt == NULL) {
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Body, Stmt);
|
||
Py_DECREF(Stmt);
|
||
while (AtOp(P, ";")) {
|
||
NextTok(P);
|
||
if (PeekTok(P, 0)->Kind == TK_NEWLINE) {
|
||
break;
|
||
}
|
||
PyObject *Extra = ParseStatement(P);
|
||
if (Extra == NULL) {
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Body, Extra);
|
||
Py_DECREF(Extra);
|
||
}
|
||
SkipNEWLINE(P);
|
||
}
|
||
PyObject *Ti = NewList();
|
||
if (Ti == NULL) {
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Body, Ti };
|
||
PyObject *Mod = NewNode(P, "Module", Argv, 2);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Ti);
|
||
return Mod;
|
||
}
|
||
|
||
/* 语句分派(对齐 vast Parser.ParseStatement) */
|
||
static PyObject *ParseStatement(Parser *P) {
|
||
Token *T = PeekTok(P, 0);
|
||
if (T->Kind == TK_NAME) {
|
||
if (TokIsName(T, "extern")) {
|
||
return ParseExternDef(P, 0, NULL);
|
||
}
|
||
if (TokIsName(T, "export")) {
|
||
return ParseExternDef(P, 1, NULL);
|
||
}
|
||
if ((TokIsName(T, "fn") || TokIsName(T, "fun") || TokIsName(T, "func")
|
||
|| TokIsName(T, "function"))
|
||
&& PeekTok(P, 1)->Kind == TK_NAME) {
|
||
return ParseFunctionDef(P, 0, NULL);
|
||
}
|
||
if (TokIsName(T, "async")) {
|
||
Token *N = PeekTok(P, 1);
|
||
if (N->Kind == TK_NAME && TokIsName(N, "def")) {
|
||
return ParseFunctionDef(P, 1, NULL);
|
||
}
|
||
if (N->Kind == TK_NAME && TokIsName(N, "for")) {
|
||
return ParseFor(P, 1);
|
||
}
|
||
if (N->Kind == TK_NAME && TokIsName(N, "with")) {
|
||
return ParseWith(P, 1);
|
||
}
|
||
}
|
||
if (TokIsName(T, "def")) {
|
||
return ParseFunctionDef(P, 0, NULL);
|
||
}
|
||
if (TokIsName(T, "class")) {
|
||
return ParseClassDef(P, NULL);
|
||
}
|
||
if (TokIsName(T, "if")) {
|
||
return ParseIf(P);
|
||
}
|
||
if (TokIsName(T, "while")) {
|
||
return ParseWhile(P);
|
||
}
|
||
if (TokIsName(T, "for")) {
|
||
return ParseFor(P, 0);
|
||
}
|
||
if (TokIsName(T, "try")) {
|
||
return ParseTry(P);
|
||
}
|
||
if (TokIsName(T, "with")) {
|
||
return ParseWith(P, 0);
|
||
}
|
||
if (TokIsName(T, "match")) {
|
||
int SaveIdx = P->Idx;
|
||
PyObject *M = ParseMatch(P);
|
||
if (M != NULL) {
|
||
return M;
|
||
}
|
||
if (PyErr_Occurred()) {
|
||
return NULL;
|
||
}
|
||
P->Idx = SaveIdx;
|
||
P->Error = 0;
|
||
/* 回退为表达式语句 */
|
||
}
|
||
if (TokIsName(T, "return")) {
|
||
Token *Start = NextTok(P);
|
||
PyObject *Value = NULL;
|
||
if (PeekTok(P, 0)->Kind != TK_NEWLINE && !AtOp(P, ";")) {
|
||
Value = ParseExprList(P);
|
||
if (Value == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Argv[1] = { Value ? Value : Py_None };
|
||
PyObject *Node = NewNode(P, "Return", Argv, 1);
|
||
Py_XDECREF(Value);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
if (TokIsName(T, "raise")) {
|
||
Token *Start = NextTok(P);
|
||
PyObject *Exc = NULL;
|
||
PyObject *Cause = NULL;
|
||
if (PeekTok(P, 0)->Kind != TK_NEWLINE && !AtOp(P, ";")) {
|
||
Exc = ParseExpr(P);
|
||
if (Exc == NULL) {
|
||
return NULL;
|
||
}
|
||
if (AtName(P, "from")) {
|
||
NextTok(P);
|
||
Cause = ParseExpr(P);
|
||
if (Cause == NULL) {
|
||
Py_DECREF(Exc);
|
||
return NULL;
|
||
}
|
||
}
|
||
}
|
||
PyObject *Argv[2] = { Exc ? Exc : Py_None, Cause ? Cause : Py_None };
|
||
PyObject *Node = NewNode(P, "Raise", Argv, 2);
|
||
Py_XDECREF(Exc);
|
||
Py_XDECREF(Cause);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
if (TokIsName(T, "import")) {
|
||
return ParseImport(P);
|
||
}
|
||
if (TokIsName(T, "from")) {
|
||
return ParseImportFrom(P);
|
||
}
|
||
if (TokIsName(T, "global")) {
|
||
return ParseGlobal(P, "Global");
|
||
}
|
||
if (TokIsName(T, "nonlocal")) {
|
||
return ParseGlobal(P, "Nonlocal");
|
||
}
|
||
if (TokIsName(T, "del")) {
|
||
return ParseDelete(P);
|
||
}
|
||
if (TokIsName(T, "assert")) {
|
||
return ParseAssert(P);
|
||
}
|
||
if (TokIsName(T, "pass")) {
|
||
Token *Start = NextTok(P);
|
||
PyObject *Node = NewNode(P, "Pass", NULL, 0);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
if (TokIsName(T, "break")) {
|
||
Token *Start = NextTok(P);
|
||
PyObject *Node = NewNode(P, "Break", NULL, 0);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
if (TokIsName(T, "continue")) {
|
||
Token *Start = NextTok(P);
|
||
PyObject *Node = NewNode(P, "Continue", NULL, 0);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
if (TokIsName(T, "yield")) {
|
||
return ParseExprStmt(P);
|
||
}
|
||
}
|
||
if (T->Kind == TK_OP && TokIsOp(T, "@")) {
|
||
return ParseDecorated(P);
|
||
}
|
||
return ParseSimpleStmt(P);
|
||
}
|
||
|
||
/* 简单语句:AnnAssign / Assign / AugAssign / Expr */
|
||
static PyObject *ParseSimpleStmt(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Ann = TryParseAnnAssign(P);
|
||
if (Ann != NULL) {
|
||
return Ann;
|
||
}
|
||
if (PyErr_Occurred()) {
|
||
return NULL;
|
||
}
|
||
PyObject *Expr = ParseExprList(P);
|
||
if (Expr == NULL) {
|
||
return NULL;
|
||
}
|
||
/* 赋值链 */
|
||
if (AtOp(P, "=")) {
|
||
PyObject *Targets = NewList();
|
||
if (Targets == NULL) {
|
||
Py_DECREF(Expr);
|
||
return NULL;
|
||
}
|
||
SetStoreContext(P, Expr);
|
||
PyList_Append(Targets, Expr);
|
||
for (;;) {
|
||
NextTok(P); /* '=' */
|
||
PyObject *Value = ParseExprList(P);
|
||
if (Value == NULL) {
|
||
Py_DECREF(Targets);
|
||
Py_DECREF(Expr);
|
||
return NULL;
|
||
}
|
||
if (AtOp(P, "=")) {
|
||
SetStoreContext(P, Value);
|
||
PyList_Append(Targets, Value);
|
||
Py_DECREF(Value);
|
||
continue;
|
||
}
|
||
Py_DECREF(Expr);
|
||
PyObject *Argv[3] = { Targets, Value, Py_None };
|
||
PyObject *Node = NewNode(P, "Assign", Argv, 3);
|
||
Py_DECREF(Targets);
|
||
Py_DECREF(Value);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
}
|
||
/* 增强赋值 */
|
||
static const struct { const char *Op; const char *NodeName; } AugOps[] = {
|
||
{"+=", "Add"}, {"-=", "Sub"}, {"*=", "Mult"}, {"/=", "Div"},
|
||
{"//=", "FloorDiv"}, {"%=", "Mod"}, {"**=", "Pow"}, {"<<=", "LShift"},
|
||
{">>=", "RShift"}, {"&=", "BitAnd"}, {"|=", "BitOr"}, {"^=", "BitXor"},
|
||
{"@=", "MatMult"},
|
||
};
|
||
for (Py_ssize_t I = 0; I < (Py_ssize_t)(sizeof(AugOps) / sizeof(AugOps[0])); I++) {
|
||
if (AtOp(P, AugOps[I].Op)) {
|
||
NextTok(P);
|
||
PyObject *Value = ParseExpr(P);
|
||
if (Value == NULL) {
|
||
Py_DECREF(Expr);
|
||
return NULL;
|
||
}
|
||
SetStoreContext(P, Expr);
|
||
PyObject *Op = MakeSingleton(P, AugOps[I].NodeName);
|
||
if (Op == NULL) {
|
||
Py_DECREF(Expr);
|
||
Py_DECREF(Value);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3] = { Expr, Op, Value };
|
||
PyObject *Node = NewNode(P, "AugAssign", Argv, 3);
|
||
Py_DECREF(Op);
|
||
Py_DECREF(Value);
|
||
Py_DECREF(Expr);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
}
|
||
PyObject *Argv[1] = { Expr };
|
||
PyObject *Node = NewNode(P, "Expr", Argv, 1);
|
||
Py_DECREF(Expr);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 尝试解析带注解赋值(对齐 vast _TryParseAnnAssign) */
|
||
static PyObject *TryParseAnnAssign(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
Token *T0 = PeekTok(P, 0);
|
||
Token *T1 = PeekTok(P, 1);
|
||
if (T0->Kind == TK_NAME && T1->Kind == TK_OP && TokIsOp(T1, ":")) {
|
||
Token *NameTok = NextTok(P);
|
||
NextTok(P); /* ':' */
|
||
PyObject *Annotation = ParseExpr(P);
|
||
if (Annotation == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Value = NULL;
|
||
if (AtOp(P, "=")) {
|
||
NextTok(P);
|
||
Value = ParseExpr(P);
|
||
if (Value == NULL) {
|
||
Py_DECREF(Annotation);
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Target = MakeNameNode(P, NameTok, "Store");
|
||
if (Target == NULL) {
|
||
Py_DECREF(Annotation);
|
||
Py_XDECREF(Value);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[4] = { Target, Annotation, Value ? Value : Py_None, PyLong_FromLong(1) };
|
||
PyObject *Node = NewNode(P, "AnnAssign", Argv, 4);
|
||
Py_DECREF(Argv[3]);
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Annotation);
|
||
Py_XDECREF(Value);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
if (T0->Kind == TK_NAME
|
||
|| (T0->Kind == TK_OP && (TokIsOp(T0, "(") || TokIsOp(T0, "[")))) {
|
||
int SaveIdx = P->Idx;
|
||
int SaveError = P->Error;
|
||
PyObject *Expr = ParseExpr(P);
|
||
if (Expr == NULL) {
|
||
if (PyErr_Occurred()) {
|
||
return NULL;
|
||
}
|
||
P->Idx = SaveIdx;
|
||
P->Error = SaveError;
|
||
return NULL;
|
||
}
|
||
if (AtOp(P, ":") && IsNameOrAttrOrSub(Expr)) {
|
||
NextTok(P);
|
||
PyObject *Annotation = ParseExpr(P);
|
||
if (Annotation == NULL) {
|
||
Py_DECREF(Expr);
|
||
return NULL;
|
||
}
|
||
PyObject *Value = NULL;
|
||
if (AtOp(P, "=")) {
|
||
NextTok(P);
|
||
Value = ParseExpr(P);
|
||
if (Value == NULL) {
|
||
Py_DECREF(Annotation);
|
||
Py_DECREF(Expr);
|
||
return NULL;
|
||
}
|
||
}
|
||
SetStoreContext(P, Expr);
|
||
int Simple = NodeIs(Expr, "Name") ? 1 : 0;
|
||
PyObject *Argv[4] = { Expr, Annotation, Value ? Value : Py_None,
|
||
PyLong_FromLong(Simple) };
|
||
PyObject *Node = NewNode(P, "AnnAssign", Argv, 4);
|
||
Py_DECREF(Argv[3]);
|
||
Py_DECREF(Annotation);
|
||
Py_XDECREF(Value);
|
||
Py_DECREF(Expr);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
P->Idx = SaveIdx;
|
||
P->Error = SaveError;
|
||
Py_DECREF(Expr);
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
/* 表达式语句(含 yield) */
|
||
static PyObject *ParseExprStmt(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Expr;
|
||
if (AtName(P, "yield")) {
|
||
Expr = ParseYield(P);
|
||
} else {
|
||
Expr = ParseExprList(P);
|
||
}
|
||
if (Expr == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[1] = { Expr };
|
||
PyObject *Node = NewNode(P, "Expr", Argv, 1);
|
||
Py_DECREF(Expr);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* import a.b.c [as x], ... */
|
||
static PyObject *ParseImport(Parser *P) {
|
||
Token *Start = NextTok(P); /* 'import' */
|
||
PyObject *Names = NewList();
|
||
if (Names == NULL) {
|
||
return NULL;
|
||
}
|
||
for (;;) {
|
||
Token *NameTok = ExpectName(P, NULL);
|
||
if (NameTok == NULL) {
|
||
Py_DECREF(Names);
|
||
return NULL;
|
||
}
|
||
Token *EndTok = NameTok;
|
||
PyObject *Parts = PyList_New(0);
|
||
if (Parts == NULL) {
|
||
Py_DECREF(Names);
|
||
return NULL;
|
||
}
|
||
PyObject *FirstPart = PyUnicode_FromStringAndSize(NameTok->Start,
|
||
NameTok->End - NameTok->Start);
|
||
if (FirstPart == NULL) {
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(Names);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Parts, FirstPart);
|
||
Py_DECREF(FirstPart);
|
||
while (AtOp(P, ".")) {
|
||
NextTok(P);
|
||
Token *PartTok = ExpectName(P, NULL);
|
||
if (PartTok == NULL) {
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(Names);
|
||
return NULL;
|
||
}
|
||
EndTok = PartTok;
|
||
PyObject *Part = PyUnicode_FromStringAndSize(PartTok->Start,
|
||
PartTok->End - PartTok->Start);
|
||
if (Part == NULL) {
|
||
Py_DECREF(Parts);
|
||
Py_DECREF(Names);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Parts, Part);
|
||
Py_DECREF(Part);
|
||
}
|
||
PyObject *Sep = PyUnicode_FromString(".");
|
||
PyObject *Full = PyUnicode_Join(Sep, Parts);
|
||
Py_DECREF(Sep);
|
||
Py_DECREF(Parts);
|
||
if (Full == NULL) {
|
||
Py_DECREF(Names);
|
||
return NULL;
|
||
}
|
||
PyObject *Asname = NULL;
|
||
if (AtName(P, "as")) {
|
||
NextTok(P);
|
||
Token *AsTok = ExpectName(P, NULL);
|
||
if (AsTok == NULL) {
|
||
Py_DECREF(Full);
|
||
Py_DECREF(Names);
|
||
return NULL;
|
||
}
|
||
EndTok = AsTok;
|
||
Asname = PyUnicode_FromStringAndSize(AsTok->Start, AsTok->End - AsTok->Start);
|
||
if (Asname == NULL) {
|
||
Py_DECREF(Full);
|
||
Py_DECREF(Names);
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Argv[2] = { Full, Asname ? Asname : Py_None };
|
||
PyObject *Alias = NewNode(P, "alias", Argv, 2);
|
||
Py_DECREF(Full);
|
||
Py_XDECREF(Asname);
|
||
if (Alias == NULL) {
|
||
Py_DECREF(Names);
|
||
return NULL;
|
||
}
|
||
/* alias 需与 vast 一致携带位置属性(编译器符号注册按节点位置关联) */
|
||
FixLoc(P, Alias, NameTok);
|
||
PyList_Append(Names, Alias);
|
||
Py_DECREF(Alias);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
PyObject *Argv[1] = { Names };
|
||
PyObject *Node = NewNode(P, "Import", Argv, 1);
|
||
Py_DECREF(Names);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* from [.]*module import ... */
|
||
static PyObject *ParseImportFrom(Parser *P) {
|
||
Token *Start = NextTok(P); /* 'from' */
|
||
int Level = 0;
|
||
while (AtOp(P, ".")) {
|
||
NextTok(P);
|
||
Level++;
|
||
}
|
||
PyObject *Module = NULL;
|
||
if (!AtName(P, "import")) {
|
||
Token *NameTok = ExpectName(P, NULL);
|
||
if (NameTok == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Parts = PyList_New(0);
|
||
if (Parts == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *FirstPart = PyUnicode_FromStringAndSize(NameTok->Start,
|
||
NameTok->End - NameTok->Start);
|
||
if (FirstPart == NULL) {
|
||
Py_DECREF(Parts);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Parts, FirstPart);
|
||
Py_DECREF(FirstPart);
|
||
while (AtOp(P, ".")) {
|
||
NextTok(P);
|
||
Token *PartTok = ExpectName(P, NULL);
|
||
if (PartTok == NULL) {
|
||
Py_DECREF(Parts);
|
||
return NULL;
|
||
}
|
||
PyObject *Part = PyUnicode_FromStringAndSize(PartTok->Start,
|
||
PartTok->End - PartTok->Start);
|
||
if (Part == NULL) {
|
||
Py_DECREF(Parts);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Parts, Part);
|
||
Py_DECREF(Part);
|
||
}
|
||
PyObject *Sep = PyUnicode_FromString(".");
|
||
Module = PyUnicode_Join(Sep, Parts);
|
||
Py_DECREF(Sep);
|
||
Py_DECREF(Parts);
|
||
if (Module == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
if (!ExpectName(P, "import")) {
|
||
Py_XDECREF(Module);
|
||
return NULL;
|
||
}
|
||
PyObject *Names = NewList();
|
||
if (Names == NULL) {
|
||
Py_XDECREF(Module);
|
||
return NULL;
|
||
}
|
||
if (AtOp(P, "(")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
if (!AtOp(P, ")")) {
|
||
for (;;) {
|
||
PyObject *Alias = ParseImportAlias(P);
|
||
if (Alias == NULL) {
|
||
Py_DECREF(Names);
|
||
Py_XDECREF(Module);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Names, Alias);
|
||
Py_DECREF(Alias);
|
||
SkipNL(P);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
if (AtOp(P, ")")) {
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (!ExpectOp(P, ")")) {
|
||
Py_DECREF(Names);
|
||
Py_XDECREF(Module);
|
||
return NULL;
|
||
}
|
||
} else {
|
||
if (AtOp(P, "*")) {
|
||
Token *StarTok = NextTok(P);
|
||
PyObject *Argv[2] = { PyUnicode_FromString("*"), Py_None };
|
||
if (Argv[0] == NULL) {
|
||
Py_DECREF(Names);
|
||
Py_XDECREF(Module);
|
||
return NULL;
|
||
}
|
||
PyObject *Alias = NewNode(P, "alias", Argv, 2);
|
||
Py_DECREF(Argv[0]);
|
||
if (Alias == NULL) {
|
||
Py_DECREF(Names);
|
||
Py_XDECREF(Module);
|
||
return NULL;
|
||
}
|
||
FixLoc(P, Alias, StarTok);
|
||
PyList_Append(Names, Alias);
|
||
Py_DECREF(Alias);
|
||
} else {
|
||
for (;;) {
|
||
PyObject *Alias = ParseImportAlias(P);
|
||
if (Alias == NULL) {
|
||
Py_DECREF(Names);
|
||
Py_XDECREF(Module);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Names, Alias);
|
||
Py_DECREF(Alias);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
PyObject *LevelObj = PyLong_FromLong(Level);
|
||
PyObject *Argv[3] = { Module ? Module : Py_None, Names, LevelObj };
|
||
PyObject *Node = NewNode(P, "ImportFrom", Argv, 3);
|
||
Py_DECREF(LevelObj);
|
||
Py_XDECREF(Module);
|
||
Py_DECREF(Names);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 单个 import 别名:name [as alias] */
|
||
static PyObject *ParseImportAlias(Parser *P) {
|
||
Token *NameTok = ExpectName(P, NULL);
|
||
if (NameTok == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Asname = NULL;
|
||
if (AtName(P, "as")) {
|
||
NextTok(P);
|
||
Token *AsTok = ExpectName(P, NULL);
|
||
if (AsTok == NULL) {
|
||
return NULL;
|
||
}
|
||
Asname = PyUnicode_FromStringAndSize(AsTok->Start, AsTok->End - AsTok->Start);
|
||
if (Asname == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Name = PyUnicode_FromStringAndSize(NameTok->Start, NameTok->End - NameTok->Start);
|
||
if (Name == NULL) {
|
||
Py_XDECREF(Asname);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Name, Asname ? Asname : Py_None };
|
||
PyObject *Alias = NewNode(P, "alias", Argv, 2);
|
||
Py_DECREF(Name);
|
||
Py_XDECREF(Asname);
|
||
if (Alias != NULL) {
|
||
FixLoc(P, Alias, NameTok);
|
||
}
|
||
return Alias;
|
||
}
|
||
|
||
/* global / nonlocal */
|
||
static PyObject *ParseGlobal(Parser *P, const char *NodeName) {
|
||
Token *Start = NextTok(P);
|
||
PyObject *Names = NewList();
|
||
if (Names == NULL) {
|
||
return NULL;
|
||
}
|
||
for (;;) {
|
||
Token *N = ExpectName(P, NULL);
|
||
if (N == NULL) {
|
||
Py_DECREF(Names);
|
||
return NULL;
|
||
}
|
||
PyObject *Name = PyUnicode_FromStringAndSize(N->Start, N->End - N->Start);
|
||
if (Name == NULL) {
|
||
Py_DECREF(Names);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Names, Name);
|
||
Py_DECREF(Name);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
PyObject *Argv[1] = { Names };
|
||
PyObject *Node = NewNode(P, NodeName, Argv, 1);
|
||
Py_DECREF(Names);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* del target, ... */
|
||
static PyObject *ParseDelete(Parser *P) {
|
||
Token *Start = NextTok(P); /* 'del' */
|
||
PyObject *Targets = NewList();
|
||
if (Targets == NULL) {
|
||
return NULL;
|
||
}
|
||
for (;;) {
|
||
PyObject *Expr = ParseExpr(P);
|
||
if (Expr == NULL) {
|
||
Py_DECREF(Targets);
|
||
return NULL;
|
||
}
|
||
SetDelContext(P, Expr);
|
||
PyList_Append(Targets, Expr);
|
||
Py_DECREF(Expr);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
PyObject *Argv[1] = { Targets };
|
||
PyObject *Node = NewNode(P, "Delete", Argv, 1);
|
||
Py_DECREF(Targets);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* assert test [, msg] */
|
||
static PyObject *ParseAssert(Parser *P) {
|
||
Token *Start = NextTok(P); /* 'assert' */
|
||
PyObject *Test = ParseExpr(P);
|
||
if (Test == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Msg = NULL;
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
Msg = ParseExpr(P);
|
||
if (Msg == NULL) {
|
||
Py_DECREF(Test);
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Argv[2] = { Test, Msg ? Msg : Py_None };
|
||
PyObject *Node = NewNode(P, "Assert", Argv, 2);
|
||
Py_DECREF(Test);
|
||
Py_XDECREF(Msg);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 装饰器 + def/class */
|
||
static PyObject *ParseDecorated(Parser *P) {
|
||
PyObject *DecoratorList = NewList();
|
||
if (DecoratorList == NULL) {
|
||
return NULL;
|
||
}
|
||
while (AtOp(P, "@")) {
|
||
Token *DecoStart = NextTok(P);
|
||
PyObject *Deco = ParseExpr(P);
|
||
if (Deco == NULL) {
|
||
Py_DECREF(DecoratorList);
|
||
return NULL;
|
||
}
|
||
FixLocEnd(P, Deco, DecoStart, NULL);
|
||
PyList_Append(DecoratorList, Deco);
|
||
Py_DECREF(Deco);
|
||
if (!ExpectNEWLINE(P)) {
|
||
Py_DECREF(DecoratorList);
|
||
return NULL;
|
||
}
|
||
SkipNEWLINE(P);
|
||
}
|
||
Token *T = PeekTok(P, 0);
|
||
if (T->Kind == TK_NAME && TokIsName(T, "extern")) {
|
||
return ParseFunctionDef(P, 0, DecoratorList);
|
||
}
|
||
if (T->Kind == TK_NAME && TokIsName(T, "export")) {
|
||
return ParseFunctionDef(P, 0, DecoratorList);
|
||
}
|
||
if (T->Kind == TK_NAME && TokIsName(T, "def")) {
|
||
return ParseFunctionDef(P, 0, DecoratorList);
|
||
}
|
||
if (T->Kind == TK_NAME && TokIsName(T, "async")
|
||
&& PeekTok(P, 1)->Kind == TK_NAME && TokIsName(PeekTok(P, 1), "def")) {
|
||
return ParseFunctionDef(P, 1, DecoratorList);
|
||
}
|
||
if (T->Kind == TK_NAME && TokIsName(T, "class")) {
|
||
return ParseClassDef(P, DecoratorList);
|
||
}
|
||
SyntaxErrorAt(P, T, "decorator must be followed by def/class");
|
||
Py_DECREF(DecoratorList);
|
||
return NULL;
|
||
}
|
||
|
||
/* def / fn / fun / func / function(含 async def) */
|
||
static PyObject *ParseFunctionDef(Parser *P, int IsAsync, PyObject *Decorators) {
|
||
Token *Start = NextTok(P);
|
||
if (Start->Kind == TK_NAME && TokIsName(Start, "async")) {
|
||
Start = NextTok(P); /* def */
|
||
}
|
||
Token *NameTok = ExpectName(P, NULL);
|
||
if (NameTok == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *TypeParams = NewList();
|
||
if (TypeParams == NULL) {
|
||
return NULL;
|
||
}
|
||
if (AtOp(P, "[")) {
|
||
Py_DECREF(TypeParams);
|
||
TypeParams = ParseTypeParams(P);
|
||
if (TypeParams == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Args = ParseArguments(P, 0, 0);
|
||
if (Args == NULL) {
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyObject *Returns = NULL;
|
||
if (AtOp(P, "->")) {
|
||
NextTok(P);
|
||
Returns = ParseExpr(P);
|
||
if (Returns == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
}
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Args);
|
||
Py_XDECREF(Returns);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyObject *Body = ParseSuite(P);
|
||
if (Body == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_XDECREF(Returns);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyObject *Name = PyUnicode_FromStringAndSize(NameTok->Start, NameTok->End - NameTok->Start);
|
||
if (Name == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_XDECREF(Returns);
|
||
Py_DECREF(TypeParams);
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[7];
|
||
Argv[0] = Name;
|
||
Argv[1] = Args;
|
||
Argv[2] = Body;
|
||
Argv[3] = Decorators ? Decorators : NewList();
|
||
Argv[4] = Returns ? Returns : Py_None;
|
||
Argv[5] = Py_None; /* type_comment */
|
||
Argv[6] = TypeParams;
|
||
if (Argv[3] == NULL) {
|
||
Py_DECREF(Name);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Body);
|
||
Py_XDECREF(Returns);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyObject *Node = NewNode(P, IsAsync ? "AsyncFunctionDef" : "FunctionDef", Argv, 7);
|
||
Py_DECREF(Name);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Body);
|
||
if (Argv[3] != Decorators) {
|
||
Py_DECREF(Argv[3]);
|
||
}
|
||
Py_XDECREF(Returns);
|
||
Py_DECREF(TypeParams);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 构造 t.Attr 注解节点:Attribute(value=Name('t', Load), attr=AttrName, ctx=Load) */
|
||
static PyObject *MakeTAttrNode(Parser *P, const char *AttrName) {
|
||
PyObject *Load = MakeCtx(P, "Load");
|
||
PyObject *TName = PyUnicode_FromString("t");
|
||
if (Load == NULL || TName == NULL) {
|
||
Py_XDECREF(Load);
|
||
Py_XDECREF(TName);
|
||
return NULL;
|
||
}
|
||
PyObject *ArgvN[2] = { TName, Load };
|
||
PyObject *TNode = NewNode(P, "Name", ArgvN, 2);
|
||
Py_DECREF(TName);
|
||
Py_DECREF(Load);
|
||
if (TNode == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Load2 = MakeCtx(P, "Load");
|
||
PyObject *AttrStr = PyUnicode_FromString(AttrName);
|
||
if (Load2 == NULL || AttrStr == NULL) {
|
||
Py_XDECREF(TNode);
|
||
Py_XDECREF(Load2);
|
||
Py_XDECREF(AttrStr);
|
||
return NULL;
|
||
}
|
||
PyObject *ArgvA[3] = { TNode, AttrStr, Load2 };
|
||
PyObject *AttrNode = NewNode(P, "Attribute", ArgvA, 3);
|
||
Py_DECREF(TNode);
|
||
Py_DECREF(AttrStr);
|
||
Py_DECREF(Load2);
|
||
return AttrNode;
|
||
}
|
||
|
||
/* extern/export 函数声明(FFI/裸名导出,对齐 vast Parser._ParseExternDef/_ParseExportDef)。
|
||
* 允许语法(4 种,配不配 def 都一样,无 `:` 时 body 为空):
|
||
* extern [def] A(x: int) -> int [': pass']
|
||
* 产出标准 FunctionDef:返回注解改写为 <原类型> | t.State(extern)/ <原类型> | t.CExport(export),
|
||
* 并设 Extern=True / Export=True 供 Unparser 还原。 */
|
||
static PyObject *ParseExternDef(Parser *P, int IsExport, PyObject *Decorators) {
|
||
Token *Start = NextTok(P); /* 'extern' / 'export' */
|
||
if (AtName(P, "def")) {
|
||
NextTok(P);
|
||
}
|
||
Token *NameTok = ExpectName(P, NULL);
|
||
if (NameTok == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *TypeParams = NewList();
|
||
if (TypeParams == NULL) {
|
||
return NULL;
|
||
}
|
||
if (AtOp(P, "[")) {
|
||
Py_DECREF(TypeParams);
|
||
TypeParams = ParseTypeParams(P);
|
||
if (TypeParams == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Args = ParseArguments(P, 0, 0);
|
||
if (Args == NULL) {
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyObject *Returns = NULL;
|
||
if (AtOp(P, "->")) {
|
||
NextTok(P);
|
||
Returns = ParseExpr(P);
|
||
if (Returns == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Body = NewList();
|
||
if (Body == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_XDECREF(Returns);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
if (AtOp(P, ":")) {
|
||
NextTok(P);
|
||
Py_DECREF(Body);
|
||
Body = ParseSuite(P);
|
||
if (Body == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_XDECREF(Returns);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Name = PyUnicode_FromStringAndSize(NameTok->Start, NameTok->End - NameTok->Start);
|
||
if (Name == NULL) {
|
||
Py_DECREF(Args);
|
||
Py_XDECREF(Returns);
|
||
Py_DECREF(TypeParams);
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[7];
|
||
Argv[0] = Name;
|
||
Argv[1] = Args;
|
||
Argv[2] = Body;
|
||
Argv[3] = Decorators ? Decorators : NewList();
|
||
Argv[4] = Returns ? Returns : Py_None;
|
||
Argv[5] = Py_None; /* type_comment */
|
||
Argv[6] = TypeParams;
|
||
if (Argv[3] == NULL) {
|
||
Py_DECREF(Name);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Body);
|
||
Py_XDECREF(Returns);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyObject *Node = NewNode(P, "FunctionDef", Argv, 7);
|
||
Py_DECREF(Name);
|
||
Py_DECREF(Args);
|
||
Py_DECREF(Body);
|
||
if (Argv[3] != Decorators) {
|
||
Py_DECREF(Argv[3]);
|
||
}
|
||
Py_DECREF(TypeParams);
|
||
if (Node == NULL) {
|
||
Py_XDECREF(Returns);
|
||
return NULL;
|
||
}
|
||
/* 标记 extern/export(Unparser 据此还原语法) */
|
||
PyObject_SetAttrString(Node, IsExport ? "Export" : "Extern", Py_True);
|
||
/* 返回注解改写:<原类型> | t.State / <原类型> | t.CExport(NewNode 后 Returns 引用仍有效) */
|
||
PyObject *TAttr = MakeTAttrNode(P, IsExport ? "CExport" : "State");
|
||
if (TAttr != NULL) {
|
||
if (Returns != NULL) {
|
||
PyObject *Op = MakeSingleton(P, "BitOr");
|
||
if (Op != NULL) {
|
||
PyObject *ArgvB[3];
|
||
ArgvB[0] = Returns;
|
||
ArgvB[1] = Op;
|
||
ArgvB[2] = TAttr;
|
||
PyObject *Bin = NewNode(P, "BinOp", ArgvB, 3);
|
||
if (Bin != NULL) {
|
||
PyObject_SetAttrString(Node, "returns", Bin);
|
||
Py_DECREF(Bin);
|
||
}
|
||
Py_DECREF(Op);
|
||
}
|
||
} else {
|
||
PyObject_SetAttrString(Node, "returns", TAttr);
|
||
}
|
||
Py_DECREF(TAttr);
|
||
}
|
||
Py_XDECREF(Returns);
|
||
FixLoc(P, Node, Start);
|
||
return Node;
|
||
}
|
||
|
||
/* PEP 695 类型参数:[T, *Ts, **P, U: Bound] */
|
||
static PyObject *ParseTypeParams(Parser *P) {
|
||
if (!ExpectOp(P, "[")) {
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
PyObject *Params = NewList();
|
||
if (Params == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!AtOp(P, "]")) {
|
||
for (;;) {
|
||
SkipNL(P);
|
||
int Star = 0;
|
||
if (AtOp(P, "*")) {
|
||
NextTok(P);
|
||
Star = 1;
|
||
} else if (AtOp(P, "**")) {
|
||
NextTok(P);
|
||
Star = 2;
|
||
}
|
||
Token *NameTok = ExpectName(P, NULL);
|
||
if (NameTok == NULL) {
|
||
Py_DECREF(Params);
|
||
return NULL;
|
||
}
|
||
PyObject *Bound = NULL;
|
||
if (Star == 0 && AtOp(P, ":")) {
|
||
NextTok(P);
|
||
Bound = ParseExpr(P);
|
||
if (Bound == NULL) {
|
||
Py_DECREF(Params);
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Name = PyUnicode_FromStringAndSize(NameTok->Start,
|
||
NameTok->End - NameTok->Start);
|
||
if (Name == NULL) {
|
||
Py_XDECREF(Bound);
|
||
Py_DECREF(Params);
|
||
return NULL;
|
||
}
|
||
PyObject *Node = NULL;
|
||
if (Star == 1) {
|
||
PyObject *Argv[1] = { Name };
|
||
Node = NewNode(P, "TypeVarTuple", Argv, 1);
|
||
} else if (Star == 2) {
|
||
PyObject *Argv[1] = { Name };
|
||
Node = NewNode(P, "ParamSpec", Argv, 1);
|
||
} else {
|
||
PyObject *Argv[2] = { Name, Bound ? Bound : Py_None };
|
||
Node = NewNode(P, "TypeVar", Argv, 2);
|
||
}
|
||
Py_DECREF(Name);
|
||
Py_XDECREF(Bound);
|
||
if (Node == NULL) {
|
||
Py_DECREF(Params);
|
||
return NULL;
|
||
}
|
||
FixLoc(P, Node, NameTok);
|
||
PyList_Append(Params, Node);
|
||
Py_DECREF(Node);
|
||
SkipNL(P);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (!ExpectOp(P, "]")) {
|
||
Py_DECREF(Params);
|
||
return NULL;
|
||
}
|
||
return Params;
|
||
}
|
||
|
||
/* class 定义 */
|
||
static PyObject *ParseClassDef(Parser *P, PyObject *Decorators) {
|
||
Token *Start = NextTok(P); /* class */
|
||
Token *NameTok = ExpectName(P, NULL);
|
||
if (NameTok == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *TypeParams = NewList();
|
||
if (TypeParams == NULL) {
|
||
return NULL;
|
||
}
|
||
if (AtOp(P, "[")) {
|
||
Py_DECREF(TypeParams);
|
||
TypeParams = ParseTypeParams(P);
|
||
if (TypeParams == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Bases = NewList();
|
||
PyObject *Keywords = NewList();
|
||
if (Bases == NULL || Keywords == NULL) {
|
||
Py_XDECREF(Bases);
|
||
Py_XDECREF(Keywords);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
if (AtOp(P, "(")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
if (!AtOp(P, ")")) {
|
||
for (;;) {
|
||
SkipNL(P);
|
||
if (AtOp(P, "**")) {
|
||
NextTok(P);
|
||
PyObject *Value = ParseExpr(P);
|
||
if (Value == NULL) {
|
||
Py_DECREF(Bases);
|
||
Py_DECREF(Keywords);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyObject *Kw = MakeKeyword(P, NULL, Value, PrevTok(P));
|
||
Py_DECREF(Value);
|
||
if (Kw == NULL) {
|
||
Py_DECREF(Bases);
|
||
Py_DECREF(Keywords);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Keywords, Kw);
|
||
Py_DECREF(Kw);
|
||
} else {
|
||
Token *A0 = PeekTok(P, 0);
|
||
Token *A1 = PeekTok(P, 1);
|
||
if (A0->Kind == TK_NAME && A1->Kind == TK_OP && TokIsOp(A1, "=")) {
|
||
Token *ArgTok = NextTok(P);
|
||
NextTok(P); /* '=' */
|
||
PyObject *Value = ParseExpr(P);
|
||
if (Value == NULL) {
|
||
Py_DECREF(Bases);
|
||
Py_DECREF(Keywords);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyObject *Arg = PyUnicode_FromStringAndSize(ArgTok->Start,
|
||
ArgTok->End - ArgTok->Start);
|
||
PyObject *Kw = MakeKeyword(P, Arg, Value, ArgTok);
|
||
Py_XDECREF(Arg);
|
||
Py_DECREF(Value);
|
||
if (Kw == NULL) {
|
||
Py_DECREF(Bases);
|
||
Py_DECREF(Keywords);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Keywords, Kw);
|
||
Py_DECREF(Kw);
|
||
} else {
|
||
PyObject *Base = ParseExpr(P);
|
||
if (Base == NULL) {
|
||
Py_DECREF(Bases);
|
||
Py_DECREF(Keywords);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Bases, Base);
|
||
Py_DECREF(Base);
|
||
}
|
||
}
|
||
SkipNL(P);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
if (AtOp(P, ")")) {
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (!ExpectOp(P, ")")) {
|
||
Py_DECREF(Bases);
|
||
Py_DECREF(Keywords);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
}
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Bases);
|
||
Py_DECREF(Keywords);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyObject *Body = ParseSuite(P);
|
||
if (Body == NULL) {
|
||
Py_DECREF(Bases);
|
||
Py_DECREF(Keywords);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyObject *Name = PyUnicode_FromStringAndSize(NameTok->Start, NameTok->End - NameTok->Start);
|
||
if (Name == NULL) {
|
||
Py_DECREF(Bases);
|
||
Py_DECREF(Keywords);
|
||
Py_DECREF(TypeParams);
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[6];
|
||
Argv[0] = Name;
|
||
Argv[1] = Bases;
|
||
Argv[2] = Keywords;
|
||
Argv[3] = Body;
|
||
Argv[4] = Decorators ? Decorators : NewList();
|
||
Argv[5] = TypeParams;
|
||
if (Argv[4] == NULL) {
|
||
Py_DECREF(Name);
|
||
Py_DECREF(Bases);
|
||
Py_DECREF(Keywords);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(TypeParams);
|
||
return NULL;
|
||
}
|
||
PyObject *Node = NewNode(P, "ClassDef", Argv, 6);
|
||
Py_DECREF(Name);
|
||
Py_DECREF(Bases);
|
||
Py_DECREF(Keywords);
|
||
Py_DECREF(Body);
|
||
if (Argv[4] != Decorators) {
|
||
Py_DECREF(Argv[4]);
|
||
}
|
||
Py_DECREF(TypeParams);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 语句块(套件) */
|
||
static PyObject *ParseSuite(Parser *P) {
|
||
if (PeekTok(P, 0)->Kind == TK_NEWLINE) {
|
||
NextTok(P);
|
||
while (PeekTok(P, 0)->Kind == TK_NL) {
|
||
NextTok(P);
|
||
}
|
||
if (PeekTok(P, 0)->Kind == TK_INDENT) {
|
||
NextTok(P);
|
||
PyObject *Body = NewList();
|
||
if (Body == NULL) {
|
||
return NULL;
|
||
}
|
||
SkipNEWLINE(P);
|
||
while (PeekTok(P, 0)->Kind != TK_DEDENT
|
||
&& PeekTok(P, 0)->Kind != TK_ENDMARKER) {
|
||
PyObject *Stmt = ParseStatement(P);
|
||
if (Stmt == NULL) {
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Body, Stmt);
|
||
Py_DECREF(Stmt);
|
||
while (AtOp(P, ";")) {
|
||
NextTok(P);
|
||
if (PeekTok(P, 0)->Kind == TK_NEWLINE) {
|
||
break;
|
||
}
|
||
PyObject *Extra = ParseStatement(P);
|
||
if (Extra == NULL) {
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Body, Extra);
|
||
Py_DECREF(Extra);
|
||
}
|
||
SkipNEWLINE(P);
|
||
}
|
||
Token *T = NextTok(P);
|
||
if (T->Kind != TK_DEDENT) {
|
||
SyntaxErrorAt(P, T, "expected DEDENT");
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
return Body;
|
||
}
|
||
/* 空套件(宽松) */
|
||
return NewList();
|
||
}
|
||
/* 单行套件 */
|
||
PyObject *Body = NewList();
|
||
if (Body == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Stmt = ParseStatement(P);
|
||
if (Stmt == NULL) {
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Body, Stmt);
|
||
Py_DECREF(Stmt);
|
||
while (AtOp(P, ";")) {
|
||
NextTok(P);
|
||
if (PeekTok(P, 0)->Kind == TK_NEWLINE) {
|
||
break;
|
||
}
|
||
PyObject *Extra = ParseStatement(P);
|
||
if (Extra == NULL) {
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Body, Extra);
|
||
Py_DECREF(Extra);
|
||
}
|
||
if (!ExpectNEWLINE(P)) {
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
return Body;
|
||
}
|
||
|
||
/* if / elif / else */
|
||
static PyObject *ParseIf(Parser *P) {
|
||
Token *Start = NextTok(P); /* if */
|
||
PyObject *Test = ParseExpr(P);
|
||
if (Test == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Test);
|
||
return NULL;
|
||
}
|
||
PyObject *Body = ParseSuite(P);
|
||
if (Body == NULL) {
|
||
Py_DECREF(Test);
|
||
return NULL;
|
||
}
|
||
PyObject *Orelse = NewList();
|
||
if (Orelse == NULL) {
|
||
Py_DECREF(Test);
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
if (AtName(P, "elif")) {
|
||
PyObject *Nested = ParseIf(P);
|
||
if (Nested == NULL) {
|
||
Py_DECREF(Test);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Orelse);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Orelse, Nested);
|
||
Py_DECREF(Nested);
|
||
} else if (AtName(P, "else")) {
|
||
NextTok(P);
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Test);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Orelse);
|
||
return NULL;
|
||
}
|
||
PyObject *ElseBody = ParseSuite(P);
|
||
if (ElseBody == NULL) {
|
||
Py_DECREF(Test);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Orelse);
|
||
return NULL;
|
||
}
|
||
Py_DECREF(Orelse);
|
||
Orelse = ElseBody;
|
||
}
|
||
PyObject *Argv[3] = { Test, Body, Orelse };
|
||
PyObject *Node = NewNode(P, "If", Argv, 3);
|
||
Py_DECREF(Test);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Orelse);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* while / else */
|
||
static PyObject *ParseWhile(Parser *P) {
|
||
Token *Start = NextTok(P); /* while */
|
||
PyObject *Test = ParseExpr(P);
|
||
if (Test == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Test);
|
||
return NULL;
|
||
}
|
||
PyObject *Body = ParseSuite(P);
|
||
if (Body == NULL) {
|
||
Py_DECREF(Test);
|
||
return NULL;
|
||
}
|
||
PyObject *Orelse = NewList();
|
||
if (Orelse == NULL) {
|
||
Py_DECREF(Test);
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
if (AtName(P, "else")) {
|
||
NextTok(P);
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Test);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Orelse);
|
||
return NULL;
|
||
}
|
||
PyObject *ElseBody = ParseSuite(P);
|
||
if (ElseBody == NULL) {
|
||
Py_DECREF(Test);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Orelse);
|
||
return NULL;
|
||
}
|
||
Py_DECREF(Orelse);
|
||
Orelse = ElseBody;
|
||
}
|
||
PyObject *Argv[3] = { Test, Body, Orelse };
|
||
PyObject *Node = NewNode(P, "While", Argv, 3);
|
||
Py_DECREF(Test);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Orelse);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* for / async for */
|
||
static PyObject *ParseFor(Parser *P, int IsAsync) {
|
||
Token *Start = NextTok(P);
|
||
if (Start->Kind == TK_NAME && TokIsName(Start, "async")) {
|
||
Start = NextTok(P); /* for */
|
||
}
|
||
PyObject *Target = ParseTargetList(P);
|
||
if (Target == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!ExpectName(P, "in")) {
|
||
Py_DECREF(Target);
|
||
return NULL;
|
||
}
|
||
PyObject *Iterable = ParseExpr(P);
|
||
if (Iterable == NULL) {
|
||
Py_DECREF(Target);
|
||
return NULL;
|
||
}
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Iterable);
|
||
return NULL;
|
||
}
|
||
PyObject *Body = ParseSuite(P);
|
||
if (Body == NULL) {
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Iterable);
|
||
return NULL;
|
||
}
|
||
PyObject *Orelse = NewList();
|
||
if (Orelse == NULL) {
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Iterable);
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
if (AtName(P, "else")) {
|
||
NextTok(P);
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Iterable);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Orelse);
|
||
return NULL;
|
||
}
|
||
PyObject *ElseBody = ParseSuite(P);
|
||
if (ElseBody == NULL) {
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Iterable);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Orelse);
|
||
return NULL;
|
||
}
|
||
Py_DECREF(Orelse);
|
||
Orelse = ElseBody;
|
||
}
|
||
PyObject *Argv[5] = { Target, Iterable, Body, Orelse, Py_None };
|
||
PyObject *Node = NewNode(P, IsAsync ? "AsyncFor" : "For", Argv, 5);
|
||
Py_DECREF(Target);
|
||
Py_DECREF(Iterable);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Orelse);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* for 目标列表(支持裸元组解包) */
|
||
static PyObject *ParseTargetList(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *First = ParseTarget(P);
|
||
if (First == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!AtOp(P, ",")) {
|
||
return First;
|
||
}
|
||
PyObject *Elts = NewList();
|
||
if (Elts == NULL) {
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, First);
|
||
while (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
SkipNL(P);
|
||
PyObject *E = ParseTarget(P);
|
||
if (E == NULL) {
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Elts, E);
|
||
Py_DECREF(E);
|
||
}
|
||
Py_DECREF(First);
|
||
PyObject *Store = MakeCtx(P, "Store");
|
||
if (Store == NULL) {
|
||
Py_DECREF(Elts);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Elts, Store };
|
||
PyObject *Node = NewNode(P, "Tuple", Argv, 2);
|
||
Py_DECREF(Elts);
|
||
Py_DECREF(Store);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* try / except* / else / finally */
|
||
static PyObject *ParseTry(Parser *P) {
|
||
Token *Start = NextTok(P); /* try */
|
||
if (!ExpectOp(P, ":")) {
|
||
return NULL;
|
||
}
|
||
PyObject *Body = ParseSuite(P);
|
||
if (Body == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Handlers = NewList();
|
||
PyObject *Orelse = NewList();
|
||
PyObject *Finalbody = NewList();
|
||
if (Handlers == NULL || Orelse == NULL || Finalbody == NULL) {
|
||
Py_XDECREF(Handlers);
|
||
Py_XDECREF(Orelse);
|
||
Py_XDECREF(Finalbody);
|
||
Py_DECREF(Body);
|
||
return NULL;
|
||
}
|
||
int IsStar = 0;
|
||
while (AtName(P, "except")) {
|
||
NextTok(P);
|
||
if (AtOp(P, "*")) {
|
||
IsStar = 1;
|
||
NextTok(P);
|
||
}
|
||
PyObject *Handler = ParseExceptHandler(P);
|
||
if (Handler == NULL) {
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Handlers);
|
||
Py_DECREF(Orelse);
|
||
Py_DECREF(Finalbody);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Handlers, Handler);
|
||
Py_DECREF(Handler);
|
||
}
|
||
if (AtName(P, "else")) {
|
||
NextTok(P);
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Handlers);
|
||
Py_DECREF(Orelse);
|
||
Py_DECREF(Finalbody);
|
||
return NULL;
|
||
}
|
||
PyObject *ElseBody = ParseSuite(P);
|
||
if (ElseBody == NULL) {
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Handlers);
|
||
Py_DECREF(Orelse);
|
||
Py_DECREF(Finalbody);
|
||
return NULL;
|
||
}
|
||
Py_DECREF(Orelse);
|
||
Orelse = ElseBody;
|
||
}
|
||
if (AtName(P, "finally")) {
|
||
NextTok(P);
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Handlers);
|
||
Py_DECREF(Orelse);
|
||
Py_DECREF(Finalbody);
|
||
return NULL;
|
||
}
|
||
PyObject *FinBody = ParseSuite(P);
|
||
if (FinBody == NULL) {
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Handlers);
|
||
Py_DECREF(Orelse);
|
||
Py_DECREF(Finalbody);
|
||
return NULL;
|
||
}
|
||
Py_DECREF(Finalbody);
|
||
Finalbody = FinBody;
|
||
}
|
||
PyObject *Argv[4] = { Body, Handlers, Orelse, Finalbody };
|
||
PyObject *Node = NewNode(P, IsStar ? "TryStar" : "Try", Argv, 4);
|
||
Py_DECREF(Body);
|
||
Py_DECREF(Handlers);
|
||
Py_DECREF(Orelse);
|
||
Py_DECREF(Finalbody);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* except [expr [as name]] ':' suite */
|
||
static PyObject *ParseExceptHandler(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *ExcType = NULL;
|
||
PyObject *Name = NULL;
|
||
if (!AtOp(P, ":")) {
|
||
ExcType = ParseExpr(P);
|
||
if (ExcType == NULL) {
|
||
return NULL;
|
||
}
|
||
if (AtName(P, "as")) {
|
||
NextTok(P);
|
||
Token *NameTok = ExpectName(P, NULL);
|
||
if (NameTok == NULL) {
|
||
Py_DECREF(ExcType);
|
||
return NULL;
|
||
}
|
||
Name = PyUnicode_FromStringAndSize(NameTok->Start, NameTok->End - NameTok->Start);
|
||
if (Name == NULL) {
|
||
Py_DECREF(ExcType);
|
||
return NULL;
|
||
}
|
||
}
|
||
}
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_XDECREF(ExcType);
|
||
Py_XDECREF(Name);
|
||
return NULL;
|
||
}
|
||
PyObject *Body = ParseSuite(P);
|
||
if (Body == NULL) {
|
||
Py_XDECREF(ExcType);
|
||
Py_XDECREF(Name);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3] = { ExcType ? ExcType : Py_None, Name ? Name : Py_None, Body };
|
||
PyObject *Node = NewNode(P, "ExceptHandler", Argv, 3);
|
||
Py_XDECREF(ExcType);
|
||
Py_XDECREF(Name);
|
||
Py_DECREF(Body);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* with / async with */
|
||
static PyObject *ParseWith(Parser *P, int IsAsync) {
|
||
Token *Start = NextTok(P);
|
||
if (Start->Kind == TK_NAME && TokIsName(Start, "async")) {
|
||
Start = NextTok(P); /* with */
|
||
}
|
||
PyObject *Items = NewList();
|
||
if (Items == NULL) {
|
||
return NULL;
|
||
}
|
||
for (;;) {
|
||
PyObject *Ctx = ParseExpr(P);
|
||
if (Ctx == NULL) {
|
||
Py_DECREF(Items);
|
||
return NULL;
|
||
}
|
||
PyObject *OptionalVars = NULL;
|
||
if (AtName(P, "as")) {
|
||
NextTok(P);
|
||
OptionalVars = ParseTarget(P);
|
||
if (OptionalVars == NULL) {
|
||
Py_DECREF(Ctx);
|
||
Py_DECREF(Items);
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Argv[2] = { Ctx, OptionalVars ? OptionalVars : Py_None };
|
||
PyObject *Item = NewNode(P, "withitem", Argv, 2);
|
||
Py_DECREF(Ctx);
|
||
Py_XDECREF(OptionalVars);
|
||
if (Item == NULL) {
|
||
Py_DECREF(Items);
|
||
return NULL;
|
||
}
|
||
/* withitem 无位置属性 */
|
||
(void)Start;
|
||
PyList_Append(Items, Item);
|
||
Py_DECREF(Item);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Items);
|
||
return NULL;
|
||
}
|
||
PyObject *Body = ParseSuite(P);
|
||
if (Body == NULL) {
|
||
Py_DECREF(Items);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3] = { Items, Body, Py_None };
|
||
PyObject *Node = NewNode(P, IsAsync ? "AsyncWith" : "With", Argv, 3);
|
||
Py_DECREF(Items);
|
||
Py_DECREF(Body);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* ================= match 语句(PEP 634) ================= */
|
||
|
||
static PyObject *ParsePattern(Parser *P);
|
||
static PyObject *ParsePatternOr(Parser *P);
|
||
static PyObject *ParsePatternAtom(Parser *P);
|
||
static PyObject *ParsePatternValue(Parser *P);
|
||
static PyObject *ParseMatchValueAttr(Parser *P);
|
||
static PyObject *ParseMatchClass(Parser *P);
|
||
static PyObject *ParsePatternClassName(Parser *P);
|
||
static PyObject *ParseMatchSequence(Parser *P);
|
||
static PyObject *ParseMatchMapping(Parser *P);
|
||
|
||
static PyObject *ParseMatch(Parser *P) {
|
||
Token *Start = NextTok(P); /* match */
|
||
PyObject *Subject = ParseExpr(P);
|
||
if (Subject == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Subject);
|
||
return NULL;
|
||
}
|
||
if (!ExpectNEWLINE(P)) {
|
||
Py_DECREF(Subject);
|
||
return NULL;
|
||
}
|
||
Token *IndentTok = NextTok(P);
|
||
if (IndentTok->Kind != TK_INDENT) {
|
||
SyntaxErrorAt(P, IndentTok, "expected INDENT");
|
||
Py_DECREF(Subject);
|
||
return NULL;
|
||
}
|
||
PyObject *Cases = NewList();
|
||
if (Cases == NULL) {
|
||
Py_DECREF(Subject);
|
||
return NULL;
|
||
}
|
||
SkipNEWLINE(P);
|
||
while (AtName(P, "case")) {
|
||
Token *CaseStart = NextTok(P);
|
||
PyObject *Pattern = ParsePattern(P);
|
||
if (Pattern == NULL) {
|
||
Py_DECREF(Cases);
|
||
Py_DECREF(Subject);
|
||
return NULL;
|
||
}
|
||
PyObject *Guard = NULL;
|
||
if (AtName(P, "if")) {
|
||
NextTok(P);
|
||
Guard = ParseExpr(P);
|
||
if (Guard == NULL) {
|
||
Py_DECREF(Pattern);
|
||
Py_DECREF(Cases);
|
||
Py_DECREF(Subject);
|
||
return NULL;
|
||
}
|
||
}
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Pattern);
|
||
Py_XDECREF(Guard);
|
||
Py_DECREF(Cases);
|
||
Py_DECREF(Subject);
|
||
return NULL;
|
||
}
|
||
PyObject *CaseBody = ParseSuite(P);
|
||
if (CaseBody == NULL) {
|
||
Py_DECREF(Pattern);
|
||
Py_XDECREF(Guard);
|
||
Py_DECREF(Cases);
|
||
Py_DECREF(Subject);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3] = { Pattern, Guard ? Guard : Py_None, CaseBody };
|
||
PyObject *Mc = NewNode(P, "match_case", Argv, 3);
|
||
Py_DECREF(Pattern);
|
||
Py_XDECREF(Guard);
|
||
Py_DECREF(CaseBody);
|
||
if (Mc == NULL) {
|
||
Py_DECREF(Cases);
|
||
Py_DECREF(Subject);
|
||
return NULL;
|
||
}
|
||
/* match_case 无位置属性 */
|
||
(void)CaseStart;
|
||
PyList_Append(Cases, Mc);
|
||
Py_DECREF(Mc);
|
||
SkipNEWLINE(P);
|
||
}
|
||
Token *DedentTok = NextTok(P);
|
||
if (DedentTok->Kind != TK_DEDENT) {
|
||
SyntaxErrorAt(P, DedentTok, "expected DEDENT");
|
||
Py_DECREF(Cases);
|
||
Py_DECREF(Subject);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Subject, Cases };
|
||
PyObject *Node = NewNode(P, "Match", Argv, 2);
|
||
Py_DECREF(Subject);
|
||
Py_DECREF(Cases);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 模式(顶层,处理 | 或模式) */
|
||
static PyObject *ParsePattern(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Patterns = NewList();
|
||
if (Patterns == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *First = ParsePatternOr(P);
|
||
if (First == NULL) {
|
||
Py_DECREF(Patterns);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Patterns, First);
|
||
while (AtOp(P, "|")) {
|
||
NextTok(P);
|
||
PyObject *Pat = ParsePatternOr(P);
|
||
if (Pat == NULL) {
|
||
Py_DECREF(Patterns);
|
||
Py_DECREF(First);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Patterns, Pat);
|
||
Py_DECREF(Pat);
|
||
}
|
||
if (PyList_GET_SIZE(Patterns) == 1) {
|
||
Py_DECREF(Patterns);
|
||
return First;
|
||
}
|
||
Py_DECREF(First);
|
||
PyObject *Argv[1] = { Patterns };
|
||
PyObject *Node = NewNode(P, "MatchOr", Argv, 1);
|
||
Py_DECREF(Patterns);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 单模式(含 as 绑定) */
|
||
static PyObject *ParsePatternOr(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Pat = ParsePatternAtom(P);
|
||
if (Pat == NULL) {
|
||
return NULL;
|
||
}
|
||
if (AtName(P, "as")) {
|
||
NextTok(P);
|
||
Token *NameTok = ExpectName(P, NULL);
|
||
if (NameTok == NULL) {
|
||
Py_DECREF(Pat);
|
||
return NULL;
|
||
}
|
||
PyObject *Name = PyUnicode_FromStringAndSize(NameTok->Start, NameTok->End - NameTok->Start);
|
||
if (Name == NULL) {
|
||
Py_DECREF(Pat);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Pat, Name };
|
||
PyObject *Node = NewNode(P, "MatchAs", Argv, 2);
|
||
Py_DECREF(Pat);
|
||
Py_DECREF(Name);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
return Pat;
|
||
}
|
||
|
||
/* 模式原子 */
|
||
static PyObject *ParsePatternAtom(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
Token *T = PeekTok(P, 0);
|
||
if (T->Kind == TK_NAME) {
|
||
if (TokIsName(T, "True") || TokIsName(T, "False") || TokIsName(T, "None")) {
|
||
NextTok(P);
|
||
PyObject *Val = TokIsName(T, "True") ? Py_True
|
||
: (TokIsName(T, "False") ? Py_False : Py_None);
|
||
PyObject *Argv[1] = { Val };
|
||
PyObject *Node = NewNode(P, "MatchSingleton", Argv, 1);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, T);
|
||
}
|
||
return Node;
|
||
}
|
||
/* 类模式:Name(...) 或 a.b.c(...) —— 扫描属性链末尾判断 '(' */
|
||
int PeekI = 1;
|
||
while (PeekTok(P, PeekI)->Kind == TK_OP && TokIsOp(PeekTok(P, PeekI), ".")
|
||
&& PeekTok(P, PeekI + 1)->Kind == TK_NAME) {
|
||
PeekI += 2;
|
||
}
|
||
if (PeekTok(P, PeekI)->Kind == TK_OP && TokIsOp(PeekTok(P, PeekI), "(")) {
|
||
return ParseMatchClass(P);
|
||
}
|
||
/* 属性值模式 a.b(无括号) */
|
||
if (PeekTok(P, 1)->Kind == TK_OP && TokIsOp(PeekTok(P, 1), ".")) {
|
||
return ParseMatchValueAttr(P);
|
||
}
|
||
/* 捕获模式(含 _ 通配符) */
|
||
NextTok(P);
|
||
PyObject *Name = NULL;
|
||
if (!TokIsName(T, "_")) {
|
||
Name = PyUnicode_FromStringAndSize(T->Start, T->End - T->Start);
|
||
if (Name == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Argv[2] = { Py_None, Name ? Name : Py_None };
|
||
PyObject *Node = NewNode(P, "MatchAs", Argv, 2);
|
||
Py_XDECREF(Name);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, T);
|
||
}
|
||
return Node;
|
||
}
|
||
if (T->Kind == TK_OP && (TokIsOp(T, "[") || TokIsOp(T, "("))) {
|
||
return ParseMatchSequence(P);
|
||
}
|
||
if (T->Kind == TK_OP && TokIsOp(T, "{")) {
|
||
return ParseMatchMapping(P);
|
||
}
|
||
if (T->Kind == TK_NUMBER || T->Kind == TK_STRING || T->Kind == TK_FSTRING
|
||
|| (T->Kind == TK_OP && (TokIsOp(T, "-") || TokIsOp(T, "+")))) {
|
||
PyObject *Value = ParsePatternValue(P);
|
||
if (Value == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[1] = { Value };
|
||
PyObject *Node = NewNode(P, "MatchValue", Argv, 1);
|
||
Py_DECREF(Value);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
if (T->Kind == TK_OP && TokIsOp(T, "*")) {
|
||
NextTok(P);
|
||
PyObject *Name = NULL;
|
||
if (PeekTok(P, 0)->Kind != TK_NEWLINE && !AtOp(P, ",")) {
|
||
Token *NameTok = ExpectName(P, NULL);
|
||
if (NameTok == NULL) {
|
||
return NULL;
|
||
}
|
||
Name = PyUnicode_FromStringAndSize(NameTok->Start, NameTok->End - NameTok->Start);
|
||
if (Name == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
PyObject *Argv[1] = { Name ? Name : Py_None };
|
||
PyObject *Node = NewNode(P, "MatchStar", Argv, 1);
|
||
Py_XDECREF(Name);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, T);
|
||
}
|
||
return Node;
|
||
}
|
||
SyntaxErrorAt(P, T, "unexpected pattern token");
|
||
return NULL;
|
||
}
|
||
|
||
/* 值模式表达式(带可选 +/- 前缀) */
|
||
static PyObject *ParsePatternValue(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
Token *T = PeekTok(P, 0);
|
||
if (T->Kind == TK_OP && (TokIsOp(T, "-") || TokIsOp(T, "+"))) {
|
||
Token *OpTok = NextTok(P);
|
||
PyObject *Inner;
|
||
if (PeekTok(P, 0)->Kind == TK_NUMBER) {
|
||
Inner = ParseNumber(P);
|
||
} else if (PeekTok(P, 0)->Kind == TK_STRING || PeekTok(P, 0)->Kind == TK_FSTRING) {
|
||
Inner = ParseStringConcat(P);
|
||
} else {
|
||
SyntaxErrorAt(P, PeekTok(P, 0), "expected literal after sign in pattern");
|
||
return NULL;
|
||
}
|
||
if (Inner == NULL) {
|
||
return NULL;
|
||
}
|
||
const char *OpName = TokIsOp(OpTok, "-") ? "USub" : "UAdd";
|
||
PyObject *Op = MakeSingleton(P, OpName);
|
||
if (Op == NULL) {
|
||
Py_DECREF(Inner);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[2] = { Op, Inner };
|
||
PyObject *Node = NewNode(P, "UnaryOp", Argv, 2);
|
||
Py_DECREF(Op);
|
||
Py_DECREF(Inner);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
if (T->Kind == TK_NUMBER) {
|
||
return ParseNumber(P);
|
||
}
|
||
return ParseStringConcat(P);
|
||
}
|
||
|
||
/* 值模式属性访问:a.b.c(无括号) */
|
||
static PyObject *ParseMatchValueAttr(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *Expr = ParseExpr(P);
|
||
if (Expr == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[1] = { Expr };
|
||
PyObject *Node = NewNode(P, "MatchValue", Argv, 1);
|
||
Py_DECREF(Expr);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 类模式:Name(pos, kw=v, ...) */
|
||
static PyObject *ParseMatchClass(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
PyObject *ClsName = ParsePatternClassName(P);
|
||
if (ClsName == NULL) {
|
||
return NULL;
|
||
}
|
||
if (!ExpectOp(P, "(")) {
|
||
Py_DECREF(ClsName);
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
PyObject *Patterns = NewList();
|
||
PyObject *KwdAttrs = NewList();
|
||
PyObject *KwdPatterns = NewList();
|
||
if (Patterns == NULL || KwdAttrs == NULL || KwdPatterns == NULL) {
|
||
Py_XDECREF(Patterns);
|
||
Py_XDECREF(KwdAttrs);
|
||
Py_XDECREF(KwdPatterns);
|
||
Py_DECREF(ClsName);
|
||
return NULL;
|
||
}
|
||
if (!AtOp(P, ")")) {
|
||
for (;;) {
|
||
SkipNL(P);
|
||
if (AtOp(P, "*")) {
|
||
NextTok(P);
|
||
PyObject *Pat = ParsePattern(P);
|
||
if (Pat == NULL) {
|
||
Py_DECREF(Patterns);
|
||
Py_DECREF(KwdAttrs);
|
||
Py_DECREF(KwdPatterns);
|
||
Py_DECREF(ClsName);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Patterns, Pat);
|
||
Py_DECREF(Pat);
|
||
} else {
|
||
Token *A0 = PeekTok(P, 0);
|
||
Token *A1 = PeekTok(P, 1);
|
||
if (A0->Kind == TK_NAME && A1->Kind == TK_OP && TokIsOp(A1, "=")) {
|
||
Token *AttrTok = NextTok(P);
|
||
NextTok(P); /* '=' */
|
||
PyObject *Attr = PyUnicode_FromStringAndSize(AttrTok->Start,
|
||
AttrTok->End - AttrTok->Start);
|
||
PyObject *Pat = ParsePattern(P);
|
||
if (Attr == NULL || Pat == NULL) {
|
||
Py_XDECREF(Attr);
|
||
Py_XDECREF(Pat);
|
||
Py_DECREF(Patterns);
|
||
Py_DECREF(KwdAttrs);
|
||
Py_DECREF(KwdPatterns);
|
||
Py_DECREF(ClsName);
|
||
return NULL;
|
||
}
|
||
PyList_Append(KwdAttrs, Attr);
|
||
PyList_Append(KwdPatterns, Pat);
|
||
Py_DECREF(Attr);
|
||
Py_DECREF(Pat);
|
||
} else {
|
||
PyObject *Pat = ParsePattern(P);
|
||
if (Pat == NULL) {
|
||
Py_DECREF(Patterns);
|
||
Py_DECREF(KwdAttrs);
|
||
Py_DECREF(KwdPatterns);
|
||
Py_DECREF(ClsName);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Patterns, Pat);
|
||
Py_DECREF(Pat);
|
||
}
|
||
}
|
||
SkipNL(P);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
if (AtOp(P, ")")) {
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (!ExpectOp(P, ")")) {
|
||
Py_DECREF(Patterns);
|
||
Py_DECREF(KwdAttrs);
|
||
Py_DECREF(KwdPatterns);
|
||
Py_DECREF(ClsName);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[4] = { ClsName, Patterns, KwdAttrs, KwdPatterns };
|
||
PyObject *Node = NewNode(P, "MatchClass", Argv, 4);
|
||
Py_DECREF(ClsName);
|
||
Py_DECREF(Patterns);
|
||
Py_DECREF(KwdAttrs);
|
||
Py_DECREF(KwdPatterns);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 类模式的类名(Name / a.b.c 属性链) */
|
||
static PyObject *ParsePatternClassName(Parser *P) {
|
||
Token *Start = PeekTok(P, 0);
|
||
Token *NameTok = ExpectName(P, NULL);
|
||
if (NameTok == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Node = MakeNameNode(P, NameTok, "Load");
|
||
if (Node == NULL) {
|
||
return NULL;
|
||
}
|
||
while (AtOp(P, ".")) {
|
||
NextTok(P);
|
||
Token *AttrTok = ExpectName(P, NULL);
|
||
if (AttrTok == NULL) {
|
||
Py_DECREF(Node);
|
||
return NULL;
|
||
}
|
||
PyObject *AttrNode = MakeAttrNode(P, Node, AttrTok, Start);
|
||
Py_DECREF(Node);
|
||
if (AttrNode == NULL) {
|
||
return NULL;
|
||
}
|
||
Node = AttrNode;
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 序列模式 [a, b] / (a, b) */
|
||
static PyObject *ParseMatchSequence(Parser *P) {
|
||
Token *Start = NextTok(P); /* '[' 或 '(' */
|
||
const char *Close = TokIsOp(Start, "[") ? "]" : ")";
|
||
PyObject *Patterns = NewList();
|
||
if (Patterns == NULL) {
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
if (!AtOp(P, Close)) {
|
||
for (;;) {
|
||
SkipNL(P);
|
||
PyObject *Pat = ParsePattern(P);
|
||
if (Pat == NULL) {
|
||
Py_DECREF(Patterns);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Patterns, Pat);
|
||
Py_DECREF(Pat);
|
||
SkipNL(P);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
if (AtOp(P, Close)) {
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (!ExpectOp(P, Close)) {
|
||
Py_DECREF(Patterns);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[1] = { Patterns };
|
||
PyObject *Node = NewNode(P, "MatchSequence", Argv, 1);
|
||
Py_DECREF(Patterns);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* 映射模式 {k: v, **rest} */
|
||
static PyObject *ParseMatchMapping(Parser *P) {
|
||
Token *Start = NextTok(P); /* '{' */
|
||
PyObject *Keys = NewList();
|
||
PyObject *Patterns = NewList();
|
||
PyObject *Rest = NULL;
|
||
if (Keys == NULL || Patterns == NULL) {
|
||
Py_XDECREF(Keys);
|
||
Py_XDECREF(Patterns);
|
||
return NULL;
|
||
}
|
||
SkipNL(P);
|
||
if (!AtOp(P, "}")) {
|
||
for (;;) {
|
||
SkipNL(P);
|
||
if (AtOp(P, "**")) {
|
||
NextTok(P);
|
||
Token *NameTok = ExpectName(P, NULL);
|
||
if (NameTok == NULL) {
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Patterns);
|
||
return NULL;
|
||
}
|
||
Rest = PyUnicode_FromStringAndSize(NameTok->Start, NameTok->End - NameTok->Start);
|
||
if (Rest == NULL) {
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Patterns);
|
||
return NULL;
|
||
}
|
||
} else {
|
||
PyObject *Key = ParseExpr(P);
|
||
if (Key == NULL) {
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Patterns);
|
||
Py_XDECREF(Rest);
|
||
return NULL;
|
||
}
|
||
if (!ExpectOp(P, ":")) {
|
||
Py_DECREF(Key);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Patterns);
|
||
Py_XDECREF(Rest);
|
||
return NULL;
|
||
}
|
||
PyObject *Pat = ParsePattern(P);
|
||
if (Pat == NULL) {
|
||
Py_DECREF(Key);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Patterns);
|
||
Py_XDECREF(Rest);
|
||
return NULL;
|
||
}
|
||
PyList_Append(Keys, Key);
|
||
PyList_Append(Patterns, Pat);
|
||
Py_DECREF(Key);
|
||
Py_DECREF(Pat);
|
||
}
|
||
SkipNL(P);
|
||
if (AtOp(P, ",")) {
|
||
NextTok(P);
|
||
if (AtOp(P, "}")) {
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (!ExpectOp(P, "}")) {
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Patterns);
|
||
Py_XDECREF(Rest);
|
||
return NULL;
|
||
}
|
||
PyObject *Argv[3] = { Keys, Patterns, Rest ? Rest : Py_None };
|
||
PyObject *Node = NewNode(P, "MatchMapping", Argv, 3);
|
||
Py_DECREF(Keys);
|
||
Py_DECREF(Patterns);
|
||
Py_XDECREF(Rest);
|
||
if (Node != NULL) {
|
||
FixLoc(P, Node, Start);
|
||
}
|
||
return Node;
|
||
}
|
||
|
||
/* ================= 模块入口 ================= */
|
||
|
||
static PyObject *VastC_Parse(PyObject *Self, PyObject *Args, PyObject *Kwargs) {
|
||
static char *KwList[] = {"source", "mode", NULL};
|
||
const char *Src = NULL;
|
||
Py_ssize_t Len = 0;
|
||
const char *Mode = "exec";
|
||
if (!PyArg_ParseTupleAndKeywords(Args, Kwargs, "s#|s:parse", KwList, &Src, &Len, &Mode)) {
|
||
return NULL;
|
||
}
|
||
Token *Tokens = NULL;
|
||
int NTokens = 0;
|
||
int *LineStarts = NULL;
|
||
int NLineStarts = 0;
|
||
if (!TokenizeText(Src, Len, &Tokens, &NTokens, &LineStarts, &NLineStarts)) {
|
||
PyErr_SetString(PyExc_MemoryError, "vast_c: out of memory during tokenize");
|
||
return NULL;
|
||
}
|
||
Parser P;
|
||
P.Src = Src;
|
||
P.Len = Len;
|
||
P.Tokens = Tokens;
|
||
P.NTokens = NTokens;
|
||
P.Idx = 0;
|
||
P.LineStarts = LineStarts;
|
||
P.NLineStarts = NLineStarts;
|
||
P.Error = 0;
|
||
P.ErrMsg = NULL;
|
||
P.ErrLine = 0;
|
||
P.FStringExprEnd = 0;
|
||
PyObject *Tree = ParseModule(&P);
|
||
PyMem_Free(Tokens);
|
||
PyMem_Free(LineStarts);
|
||
if (Tree == NULL) {
|
||
if (P.Error) {
|
||
PyErr_SetString(PyExc_SyntaxError, P.ErrMsg ? P.ErrMsg : "vast_c: syntax error");
|
||
}
|
||
return NULL;
|
||
}
|
||
if (strcmp(Mode, "exec") == 0) {
|
||
return Tree;
|
||
}
|
||
if (strcmp(Mode, "eval") == 0) {
|
||
/* 复用 vast.parse 的 eval 语义:暴露 Expr 的 value 为 Expression 节点 */
|
||
PyObject *BodyAttr = PyObject_GetAttrString(Tree, "body");
|
||
Py_DECREF(Tree);
|
||
if (BodyAttr == NULL || PyList_GET_SIZE(BodyAttr) != 1) {
|
||
Py_XDECREF(BodyAttr);
|
||
PyErr_SetString(PyExc_SyntaxError, "vast_c: eval mode requires single expression");
|
||
return NULL;
|
||
}
|
||
PyObject *Stmt = PyList_GetItem(BodyAttr, 0); /* borrowed */
|
||
PyObject *Value = PyObject_GetAttrString(Stmt, "value");
|
||
Py_DECREF(BodyAttr);
|
||
if (Value == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Argv2[1];
|
||
Argv2[0] = Value;
|
||
PyObject *ExprNode = NewNode(&P, "Expression", Argv2, 1);
|
||
Py_DECREF(Value);
|
||
return ExprNode;
|
||
}
|
||
if (strcmp(Mode, "single") == 0) {
|
||
PyObject *BodyAttr = PyObject_GetAttrString(Tree, "body");
|
||
Py_DECREF(Tree);
|
||
if (BodyAttr == NULL) {
|
||
return NULL;
|
||
}
|
||
PyObject *Argv2[1];
|
||
Argv2[0] = BodyAttr;
|
||
PyObject *IntNode = NewNode(&P, "Interactive", Argv2, 1);
|
||
Py_DECREF(BodyAttr);
|
||
return IntNode;
|
||
}
|
||
Py_DECREF(Tree);
|
||
PyErr_SetString(PyExc_ValueError, "vast_c: unsupported mode");
|
||
return NULL;
|
||
}
|
||
|
||
static PyMethodDef VastC_Methods[] = {
|
||
{"parse", (PyCFunction)VastC_Parse, METH_VARARGS | METH_KEYWORDS,
|
||
"parse(source, mode='exec') -> vast.nodes 树(完整 Python 3.12 + Viper 软关键字)"},
|
||
{NULL, NULL, 0, NULL},
|
||
};
|
||
|
||
static struct PyModuleDef VastC_Module = {
|
||
PyModuleDef_HEAD_INIT,
|
||
"vast_c",
|
||
"vast_c - C 版 Viper/Python 解析器(vast 加速层)",
|
||
-1,
|
||
VastC_Methods,
|
||
};
|
||
|
||
__declspec(dllexport) PyMODINIT_FUNC PyInit__parser(void) {
|
||
return PyModule_Create(&VastC_Module);
|
||
}
|