Lyon ee90f9a60f add new file
update cmsis-pack to v1.10

update v1.10.0 to cmsis-pack

update makepdsc
2022-08-08 21:58:16 +08:00

2653 lines
82 KiB
C

/*
* This file is part of the PikaScript project.
* http://github.com/pikastech/pikascript
*
* MIT License
*
* Copyright (c) 2021 lyon 李昂 liang6516@outlook.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "PikaParser.h"
#include "BaseObj.h"
#include "PikaObj.h"
#include "dataQueue.h"
#include "dataQueueObj.h"
#include "dataStack.h"
#include "dataStrs.h"
/* local head */
typedef QueueObj AST;
char* AST_toPikaASM(AST* ast, Args* outBuffs);
char* Lexer_getTokens(Args* outBuffs, char* stmt);
int32_t AST_deinit(AST* ast);
char* Parser_multiLineToAsm(Args* outBuffs, char* multiLine);
uint8_t Parser_isContainToken(char* tokens,
enum TokenType token_type,
char* pyload);
void ParserState_init(struct ParserState* ps);
void ParserState_parse(struct ParserState* ps, char* stmt);
void ParserState_deinit(struct ParserState* ps);
void ParserState_beforeIter(struct ParserState* ps);
void ParserState_iterStart(struct ParserState* ps);
void ParserState_iterEnd(struct ParserState* ps);
char* Parser_popToken(Args* buffs_p, char* tokens);
/* Syntex item */
const SyntaxItem syntexItemList[] = {
/* clang-format off */
{
.asmCode = "RUN",
.astNodeName = "method",
.isUseNodeValue = PIKA_TRUE
},
{
.asmCode = "OPT",
.astNodeName = "operator",
.isUseNodeValue = PIKA_TRUE
},
{
.asmCode = "BYT",
.astNodeName = "bytes",
.isUseNodeValue = PIKA_TRUE
},
{
.asmCode = "NUM",
.astNodeName = "num",
.isUseNodeValue = PIKA_TRUE
},
{
.asmCode = "IMP",
.astNodeName = "import",
.isUseNodeValue = PIKA_TRUE
},
{
.asmCode = "REF",
.astNodeName = "ref",
.isUseNodeValue = PIKA_TRUE
},
{
.asmCode = "STR",
.astNodeName = "string",
.isUseNodeValue = PIKA_TRUE
},
#if PIKA_SYNTAX_SLICE_ENABLE
{
.asmCode = "SLC",
.astNodeName = "slice",
.isUseNodeValue = PIKA_FALSE
},
#endif
#if PIKA_BUILTIN_STRUCT_ENABLE
{
.asmCode = "DCT",
.astNodeName = "dict",
.isUseNodeValue = PIKA_FALSE
},
{
.asmCode = "LST",
.astNodeName = "list",
.isUseNodeValue = PIKA_FALSE
},
#endif
{
.asmCode = "OUT",
.astNodeName = "left",
.isUseNodeValue = PIKA_TRUE
}
/* clang-format on */
};
uint16_t Tokens_getSize(char* tokens) {
if (strEqu("", tokens)) {
return 0;
}
return strCountSign(tokens, 0x1F) + 1;
}
char* strsPopTokenWithSkip_byStr(Args* outBuffs,
char* stmts,
char* str,
char skipStart,
char skipEnd) {
uint8_t divider_index = 0;
Arg* keeped_arg = arg_newStr("");
Arg* poped_arg = arg_newStr("");
ParserState_forEachToken(ps, stmts) {
ParserState_iterStart(&ps);
if (ps.branket_deepth == 0) {
if (strEqu(str, ps.token1.pyload)) {
divider_index = ps.iter_index;
}
}
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
ParserState_forEachTokenExistPs(ps, stmts) {
ParserState_iterStart(&ps);
if (ps.iter_index < divider_index) {
poped_arg = arg_strAppend(poped_arg, ps.token1.pyload);
}
if (ps.iter_index > divider_index) {
keeped_arg = arg_strAppend(keeped_arg, ps.token1.pyload);
}
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
char* keeped = arg_getStr(keeped_arg);
char* poped = strsCopy(outBuffs, arg_getStr(poped_arg));
__platform_memcpy(stmts, keeped, strGetSize(keeped) + 1);
arg_deinit(poped_arg);
arg_deinit(keeped_arg);
return poped;
}
char* strsGetCleanCmd(Args* outBuffs, char* cmd) {
pika_assert(cmd != NULL);
int32_t size = strGetSize(cmd);
/* lexer may generate more chars than input */
char* strOut = args_getBuff(outBuffs, size * 2);
int32_t iOut = 0;
ParserState_forEachToken(ps, cmd) {
ParserState_iterStart(&ps);
for (uint16_t k = 0; k < strGetSize(ps.token1.pyload); k++) {
strOut[iOut] = ps.token1.pyload[k];
iOut++;
}
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
/* add \0 */
strOut[iOut] = 0;
return strOut;
}
char* strsDeleteBetween(Args* buffs_p, char* strIn, char begin, char end) {
int32_t size = strGetSize(strIn);
char* strOut = args_getBuff(buffs_p, size);
uint8_t deepth = 0;
uint32_t iOut = 0;
for (int i = 0; i < size; i++) {
if (end == strIn[i]) {
deepth--;
}
if (0 == deepth) {
strOut[iOut] = strIn[i];
iOut++;
}
if (begin == strIn[i]) {
deepth++;
}
}
strOut[iOut] = 0;
return strOut;
}
static uint8_t Lexer_isError(char* line) {
Args buffs = {0};
uint8_t res = 0; /* not error */
char* tokens = Lexer_getTokens(&buffs, line);
if (NULL == tokens) {
res = 1; /* lex error */
goto exit;
}
goto exit;
exit:
strsDeinit(&buffs);
return res;
}
static char* __removeTokensBetween(Args* outBuffs,
char* input,
char* token_pyload1,
char* token_pyload2) {
Args buffs = {0};
uint8_t block_deepth = 0;
char* output = "";
ParserState_forEachToken(ps, input) {
ParserState_iterStart(&ps);
if (strEqu(token_pyload1, ps.token1.pyload)) {
if (block_deepth == 0) {
output = strsAppend(&buffs, output, ps.token1.pyload);
}
block_deepth++;
}
if (strEqu(token_pyload2, ps.token1.pyload)) {
block_deepth--;
}
if (block_deepth == 0) {
output = strsAppend(&buffs, output, ps.token1.pyload);
}
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
output = strsCopy(outBuffs, output);
strsDeinit(&buffs);
return output;
}
static enum StmtType Lexer_matchStmtType(char* right) {
Args buffs = {0};
enum StmtType stmtType = STMT_none;
char* rightWithoutSubStmt = __removeTokensBetween(&buffs, right, "(", ")");
rightWithoutSubStmt =
__removeTokensBetween(&buffs, rightWithoutSubStmt, "[", "]");
rightWithoutSubStmt =
__removeTokensBetween(&buffs, rightWithoutSubStmt, "{", "}");
PIKA_BOOL is_get_operator = PIKA_FALSE;
PIKA_BOOL is_get_method = PIKA_FALSE;
PIKA_BOOL is_get_string = PIKA_FALSE;
PIKA_BOOL is_get_bytes = PIKA_FALSE;
PIKA_BOOL is_get_number = PIKA_FALSE;
PIKA_BOOL is_get_symbol = PIKA_FALSE;
PIKA_BOOL is_get_list = PIKA_FALSE;
PIKA_BOOL is_get_slice = PIKA_FALSE;
PIKA_BOOL is_get_dict = PIKA_FALSE;
PIKA_BOOL is_get_import = PIKA_FALSE;
PIKA_BOOL is_get_chain = PIKA_FALSE;
ParserState_forEachToken(ps, rightWithoutSubStmt) {
ParserState_iterStart(&ps);
/* collect type */
if (strEqu(ps.token1.pyload, " import ")) {
is_get_import = PIKA_TRUE;
goto iter_continue;
}
if (strEqu(ps.token2.pyload, "[")) {
/* (symble | iteral | <]> | <)>) + <[> */
if (TOKEN_symbol == ps.token1.type ||
TOKEN_literal == ps.token1.type ||
strEqu(ps.token1.pyload, "]") ||
strEqu(ps.token1.pyload, ")")) {
is_get_slice = PIKA_TRUE;
goto iter_continue;
}
/* ( <,> | <=> ) + <[> */
is_get_list = PIKA_TRUE;
goto iter_continue;
}
if (strEqu(ps.token1.pyload, "[") && ps.iter_index == 1) {
/* VOID + <[> */
is_get_list = PIKA_TRUE;
goto iter_continue;
}
if (strEqu(ps.token1.pyload, "...")) {
goto iter_continue;
}
if (strIsStartWith(ps.token1.pyload, ".")) {
if (ps.iter_index != 1) {
is_get_chain = PIKA_TRUE;
goto iter_continue;
}
}
if (strEqu(ps.token1.pyload, "{")) {
is_get_dict = PIKA_TRUE;
goto iter_continue;
}
if (ps.token1.type == TOKEN_operator) {
is_get_operator = PIKA_TRUE;
goto iter_continue;
}
/* <(> */
if (strEqu(ps.token1.pyload, "(")) {
is_get_method = PIKA_TRUE;
goto iter_continue;
}
if (ps.token1.type == TOKEN_literal) {
if (ps.token1.pyload[0] == '\'' || ps.token1.pyload[0] == '"') {
is_get_string = PIKA_TRUE;
goto iter_continue;
}
if (ps.token1.pyload[1] == '\'' || ps.token1.pyload[1] == '"') {
if (ps.token1.pyload[0] == 'b') {
is_get_bytes = PIKA_TRUE;
goto iter_continue;
}
}
is_get_number = PIKA_TRUE;
goto iter_continue;
}
if (ps.token1.type == TOKEN_symbol) {
is_get_symbol = PIKA_TRUE;
goto iter_continue;
}
iter_continue:
ParserState_iterEnd(&ps);
}
if (is_get_import) {
stmtType = STMT_import;
goto exit;
}
if (is_get_operator) {
stmtType = STMT_operator;
goto exit;
}
if (is_get_slice) {
stmtType = STMT_slice;
goto exit;
}
if (is_get_list) {
stmtType = STMT_list;
goto exit;
}
if (is_get_dict) {
stmtType = STMT_dict;
goto exit;
}
if (is_get_chain) {
stmtType = STMT_chain;
goto exit;
}
if (is_get_method) {
stmtType = STMT_method;
goto exit;
}
if (is_get_string) {
stmtType = STMT_string;
goto exit;
}
if (is_get_bytes) {
stmtType = STMT_bytes;
goto exit;
}
if (is_get_number) {
stmtType = STMT_number;
goto exit;
}
if (is_get_symbol) {
stmtType = STMT_reference;
goto exit;
}
exit:
ParserState_deinit(&ps);
strsDeinit(&buffs);
return stmtType;
}
char* Lexer_printTokens(Args* outBuffs, char* tokens) {
/* init */
Args buffs = {0};
char* printOut = strsCopy(&buffs, "");
/* process */
uint16_t token_size = Tokens_getSize(tokens);
for (uint16_t i = 0; i < token_size; i++) {
char* token = Parser_popToken(&buffs, tokens);
if (token[0] == TOKEN_operator) {
printOut = strsAppend(&buffs, printOut, "{opt}");
printOut = strsAppend(&buffs, printOut, token + 1);
}
if (token[0] == TOKEN_devider) {
printOut = strsAppend(&buffs, printOut, "{dvd}");
printOut = strsAppend(&buffs, printOut, token + 1);
}
if (token[0] == TOKEN_symbol) {
printOut = strsAppend(&buffs, printOut, "{sym}");
printOut = strsAppend(&buffs, printOut, token + 1);
}
if (token[0] == TOKEN_literal) {
printOut = strsAppend(&buffs, printOut, "{lit}");
printOut = strsAppend(&buffs, printOut, token + 1);
}
}
/* out put */
printOut = strsCopy(outBuffs, printOut);
strsDeinit(&buffs);
return printOut;
}
uint8_t Parser_checkIsDirect(char* str) {
Args buffs = {0};
char* tokens = Lexer_getTokens(&buffs, str);
uint8_t res = 0;
pika_assert(NULL != tokens);
if (Parser_isContainToken(tokens, TOKEN_operator, "=")) {
res = 1;
goto exit;
}
exit:
strsDeinit(&buffs);
return res;
}
Arg* Lexer_setToken(Arg* tokens_arg,
enum TokenType token_type,
char*
operator) {
Args buffs = {0};
char token_type_buff[3] = {0};
token_type_buff[0] = 0x1F;
token_type_buff[1] = token_type;
char* tokens = arg_getStr(tokens_arg);
tokens = strsAppend(&buffs, tokens, token_type_buff);
tokens = strsAppend(&buffs, tokens, operator);
Arg* new_tokens_arg = arg_setStr(tokens_arg, "", tokens);
arg_deinit(tokens_arg);
strsDeinit(&buffs);
return new_tokens_arg;
}
Arg* Lexer_setSymbel(Arg* tokens_arg,
char* stmt,
int32_t i,
int32_t* symbol_start_index) {
Args buffs = {0};
char* symbol_buff = NULL;
if (-1 == *symbol_start_index) {
/* no found symbol start index */
goto exit;
}
/* nothing to add symbel */
if (i == *symbol_start_index) {
goto exit;
}
symbol_buff = args_getBuff(&buffs, i - *symbol_start_index);
__platform_memcpy(symbol_buff, stmt + *symbol_start_index,
i - *symbol_start_index);
/* literal */
if ((symbol_buff[0] == '\'') || (symbol_buff[0] == '"')) {
/* "" or '' */
tokens_arg = Lexer_setToken(tokens_arg, TOKEN_literal, symbol_buff);
goto exit;
}
if ((symbol_buff[0] >= '0') && (symbol_buff[0] <= '9')) {
/* number */
tokens_arg = Lexer_setToken(tokens_arg, TOKEN_literal, symbol_buff);
goto exit;
}
if ((symbol_buff[0] == 'b') &&
((symbol_buff[1] == '\'') || (symbol_buff[1] == '"'))) {
/* b"" or b'' */
tokens_arg = Lexer_setToken(tokens_arg, TOKEN_literal, symbol_buff);
goto exit;
}
/* symbol */
tokens_arg = Lexer_setToken(tokens_arg, TOKEN_symbol, symbol_buff);
goto exit;
exit:
*symbol_start_index = -1;
strsDeinit(&buffs);
return tokens_arg;
}
/* tokens is devided by space */
/* a token is [TOKENTYPE|(CONTENT)] */
char* Lexer_getTokens(Args* outBuffs, char* stmt) {
/* init */
Arg* tokens_arg = New_arg(NULL);
tokens_arg = arg_setStr(tokens_arg, "", "");
int32_t size = strGetSize(stmt);
uint8_t bracket_deepth = 0;
uint8_t cn1 = 0;
uint8_t c0 = 0;
uint8_t c1 = 0;
uint8_t c2 = 0;
uint8_t c3 = 0;
uint8_t c4 = 0;
uint8_t c5 = 0;
uint8_t c6 = 0;
int32_t symbol_start_index = -1;
int is_in_string = 0;
char* tokens;
/* process */
for (int32_t i = 0; i < size; i++) {
/* update char */
cn1 = 0;
c0 = stmt[i];
c1 = 0;
c2 = 0;
c3 = 0;
c4 = 0;
c5 = 0;
c6 = 0;
if (i - 1 >= 0) {
cn1 = stmt[i - 1];
}
if (i + 1 < size) {
c1 = stmt[i + 1];
}
if (i + 2 < size) {
c2 = stmt[i + 2];
}
if (i + 3 < size) {
c3 = stmt[i + 3];
}
if (i + 4 < size) {
c4 = stmt[i + 4];
}
if (i + 5 < size) {
c5 = stmt[i + 5];
}
if (i + 6 < size) {
c6 = stmt[i + 6];
}
if (-1 == symbol_start_index) {
symbol_start_index = i;
}
/* solve string */
if (0 == is_in_string) {
if ('\'' == c0 && '\\' != cn1) {
/* in ' */
is_in_string = 1;
continue;
}
if ('"' == c0 && '\\' != cn1) {
/* in "" */
is_in_string = 2;
continue;
}
}
if (1 == is_in_string) {
if ('\'' == c0 && '\\' != cn1) {
is_in_string = 0;
tokens_arg = Lexer_setSymbel(tokens_arg, stmt, i + 1,
&symbol_start_index);
}
continue;
}
if (2 == is_in_string) {
if ('"' == c0 && '\\' != cn1) {
is_in_string = 0;
tokens_arg = Lexer_setSymbel(tokens_arg, stmt, i + 1,
&symbol_start_index);
}
continue;
}
/* match devider*/
if (('(' == c0) || (')' == c0) || (',' == c0) || ('[' == c0) ||
(']' == c0) || (':' == c0) || ('{' == c0) || ('}' == c0)) {
tokens_arg =
Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index);
char content[2] = {0};
content[0] = c0;
tokens_arg = Lexer_setToken(tokens_arg, TOKEN_devider, content);
if (c0 == '(') {
bracket_deepth++;
}
if (c0 == ')') {
bracket_deepth--;
}
continue;
}
/* match operator */
if (('>' == c0) || ('<' == c0) || ('*' == c0) || ('/' == c0) ||
('+' == c0) || ('-' == c0) || ('!' == c0) || ('=' == c0) ||
('%' == c0) || ('&' == c0) || ('|' == c0) || ('^' == c0) ||
('~' == c0)) {
if (('*' == c0) || ('/' == c0)) {
/*
=, **=, //
*/
if ((c0 == c1) && ('=' == c2)) {
char content[4] = {0};
content[0] = c0;
content[1] = c1;
content[2] = '=';
tokens_arg = Lexer_setSymbel(tokens_arg, stmt, i,
&symbol_start_index);
tokens_arg =
Lexer_setToken(tokens_arg, TOKEN_operator, content);
i = i + 2;
continue;
}
}
/*
>>, <<, **, //
*/
if (('>' == c0) || ('<' == c0) || ('*' == c0) || ('/' == c0)) {
if (c0 == c1) {
char content[3] = {0};
content[0] = c0;
content[1] = c1;
tokens_arg = Lexer_setSymbel(tokens_arg, stmt, i,
&symbol_start_index);
tokens_arg =
Lexer_setToken(tokens_arg, TOKEN_operator, content);
i = i + 1;
continue;
}
}
/*
>=, <=, *=, /=, +=, -=, !=, ==, %=
*/
if (('>' == c0) || ('<' == c0) || ('*' == c0) || ('/' == c0) ||
('+' == c0) || ('-' == c0) || ('!' == c0) || ('=' == c0) ||
('%' == c0)) {
if ('=' == c1) {
char content[3] = {0};
content[0] = c0;
content[1] = c1;
tokens_arg = Lexer_setSymbel(tokens_arg, stmt, i,
&symbol_start_index);
tokens_arg =
Lexer_setToken(tokens_arg, TOKEN_operator, content);
i = i + 1;
continue;
}
}
/* single operator */
/*
+, -, *, ... /
*/
char content[2] = {0};
content[0] = c0;
tokens_arg =
Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index);
tokens_arg = Lexer_setToken(tokens_arg, TOKEN_operator, content);
continue;
}
// not the string operator
if ((cn1 >= 'a' && cn1 <= 'z') || (cn1 >= 'A' && cn1 <= 'Z') ||
(cn1 >= '0' && cn1 <= '9') || cn1 == '_' || cn1 == '.') {
goto after_match_string_operator;
}
/* not */
if ('n' == c0) {
if (('o' == c1) && ('t' == c2) && (' ' == c3)) {
tokens_arg =
Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index);
tokens_arg =
Lexer_setToken(tokens_arg, TOKEN_operator, " not ");
i = i + 3;
continue;
}
}
/* and */
if ('a' == c0) {
if (('n' == c1) && ('d' == c2) && (' ' == c3)) {
tokens_arg =
Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index);
tokens_arg =
Lexer_setToken(tokens_arg, TOKEN_operator, " and ");
i = i + 3;
continue;
}
}
/* or */
if ('o' == c0) {
if (('r' == c1) && (' ' == c2)) {
tokens_arg =
Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index);
tokens_arg = Lexer_setToken(tokens_arg, TOKEN_operator, " or ");
i = i + 2;
continue;
}
}
/* as */
if ('a' == c0) {
if (('s' == c1) && (' ' == c2)) {
tokens_arg =
Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index);
tokens_arg = Lexer_setToken(tokens_arg, TOKEN_operator, " as ");
i = i + 2;
continue;
}
}
/* import */
if ('i' == c0) {
if (('m' == c1) && ('p' == c2) && ('o' == c3) && ('r' == c4) &&
('t' == c5) && (' ' == c6)) {
tokens_arg =
Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index);
tokens_arg =
Lexer_setToken(tokens_arg, TOKEN_operator, " import ");
i = i + 5;
continue;
}
}
after_match_string_operator:
/* skip spaces */
if (' ' == c0) {
/* not get symbal */
if (i == symbol_start_index) {
symbol_start_index++;
} else {
/* already get symbal */
tokens_arg =
Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index);
}
}
if (i == size - 1) {
/* last check symbel */
// if('\n' == c0){
// continue;
// }
tokens_arg =
Lexer_setSymbel(tokens_arg, stmt, size, &symbol_start_index);
}
}
if (0 != bracket_deepth) {
/* bracket match error */
tokens = NULL;
goto exit;
}
/* output */
tokens = arg_getStr(tokens_arg);
tokens = strsCopy(outBuffs, tokens);
exit:
arg_deinit(tokens_arg);
return tokens;
}
char* Parser_popToken(Args* buffs_p, char* tokens) {
return strsPopToken(buffs_p, tokens, 0x1F);
}
enum TokenType Token_getType(char* token) {
return (enum TokenType)token[0];
}
char* Token_getPyload(char* token) {
return (char*)((uintptr_t)token + 1);
}
uint8_t Parser_isContainToken(char* tokens,
enum TokenType token_type,
char* pyload) {
Args buffs = {0};
char* tokens_buff = strsCopy(&buffs, tokens);
uint8_t res = 0;
uint16_t token_size = Tokens_getSize(tokens);
for (int i = 0; i < token_size; i++) {
char* token = Parser_popToken(&buffs, tokens_buff);
if (token_type == Token_getType(token)) {
if (strEqu(Token_getPyload(token), pyload)) {
res = 1;
goto exit;
}
}
}
exit:
strsDeinit(&buffs);
return res;
}
static const char operators[][9] = {
"**", "~", "*", "/", "%", "//", "+", "-", ">>", "<<",
"&", "^", "|", "<", "<=", ">", ">=", "!=", "==", "%=",
"/=", "//=", "-=", "+=", "*=", "**=", " not ", " and ", " or ", " import "};
char* Lexer_getOperator(Args* outBuffs, char* stmt) {
Args buffs = {0};
char* operator= NULL;
char* tokens = Lexer_getTokens(&buffs, stmt);
// use parse state foreach to get operator
for (uint32_t i = 0; i < sizeof(operators) / 9; i++) {
ParserState_forEachToken(ps, tokens) {
ParserState_iterStart(&ps);
// get operator
if (strEqu(ps.token2.pyload, (char*)operators[i])) {
// solve the iuuse of "~-1"
operator= strsCopy(&buffs, (char*)operators[i]);
ParserState_iterEnd(&ps);
break;
}
ParserState_iterEnd(&ps);
};
ParserState_deinit(&ps);
}
/* solve the iuuse of "~-1" */
if (strEqu(operator, "-")) {
ParserState_forEachToken(ps, stmt) {
ParserState_iterStart(&ps);
if (strEqu(ps.token2.pyload, "-")) {
if (ps.token1.type == TOKEN_operator) {
operator= strsCopy(&buffs, ps.token1.pyload);
ParserState_iterEnd(&ps);
break;
}
}
ParserState_iterEnd(&ps);
};
ParserState_deinit(&ps);
}
/* match the last operator in equal level */
if ((strEqu(operator, "+")) || (strEqu(operator, "-"))) {
ParserState_forEachToken(ps, stmt) {
ParserState_iterStart(&ps);
if (strEqu(ps.token1.pyload, "+")) {
operator= strsCopy(&buffs, "+");
}
if (strEqu(ps.token1.pyload, "-")) {
operator= strsCopy(&buffs, "-");
}
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
}
/* out put */
if (NULL == operator) {
return NULL;
}
operator= strsCopy(outBuffs, operator);
strsDeinit(&buffs);
return operator;
}
const char void_str[] = "";
void LexToken_update(struct LexToken* lex_token) {
lex_token->type = Token_getType(lex_token->token);
if (lex_token->type == TOKEN_strEnd) {
lex_token->pyload = (char*)void_str;
} else {
lex_token->pyload = Token_getPyload(lex_token->token);
}
}
void ParserState_iterStart(struct ParserState* ps) {
ps->iter_index++;
ps->iter_buffs = New_strBuff();
/* token1 is the last token */
ps->token1.token = strsCopy(ps->iter_buffs, arg_getStr(ps->last_token));
/* token2 is the next token */
ps->token2.token = Parser_popToken(ps->iter_buffs, ps->tokens);
/* store last token */
arg_deinit(ps->last_token);
ps->last_token = arg_newStr(ps->token2.token);
LexToken_update(&ps->token1);
LexToken_update(&ps->token2);
if (strEqu(ps->token1.pyload, "(")) {
ps->branket_deepth++;
}
if (strEqu(ps->token1.pyload, ")")) {
ps->branket_deepth--;
}
if (strEqu(ps->token1.pyload, "[")) {
ps->branket_deepth++;
}
if (strEqu(ps->token1.pyload, "]")) {
ps->branket_deepth--;
}
}
void LexToken_init(struct LexToken* lt) {
lt->pyload = NULL;
lt->token = NULL;
lt->type = TOKEN_strEnd;
}
void ParserState_init(struct ParserState* ps) {
ps->tokens = NULL;
ps->length = 0;
ps->iter_index = 0;
ps->branket_deepth = 0;
ps->last_token = NULL;
ps->iter_buffs = NULL;
ps->buffs_p = New_strBuff();
ps->result = PIKA_RES_OK;
LexToken_init(&ps->token1);
LexToken_init(&ps->token2);
}
void ParserState_iterEnd(struct ParserState* ps) {
args_deinit(ps->iter_buffs);
}
void ParserState_deinit(struct ParserState* ps) {
if (NULL != ps->last_token) {
arg_deinit(ps->last_token);
}
args_deinit(ps->buffs_p);
}
void ParserState_parse(struct ParserState* ps, char* stmt) {
if (NULL == stmt) {
ps->result = PIKA_RES_ERR_SYNTAX_ERROR;
return;
}
ps->tokens = Lexer_getTokens(ps->buffs_p, stmt);
if (NULL == ps->tokens) {
ps->result = PIKA_RES_ERR_SYNTAX_ERROR;
return;
}
ps->length = Tokens_getSize(ps->tokens);
}
void ParserState_beforeIter(struct ParserState* ps) {
/* clear first token */
if (ps->result != PIKA_RES_OK) {
return;
}
Parser_popToken(ps->buffs_p, ps->tokens);
ps->last_token = arg_newStr(Parser_popToken(ps->buffs_p, ps->tokens));
}
#if PIKA_SYNTAX_SLICE_ENABLE
static void Slice_getPars(Args* outBuffs,
char* inner,
char** pStart,
char** pEnd,
char** pStep) {
Args buffs = {0};
*pStart = "";
*pEnd = "";
*pStep = "";
/* slice */
uint8_t colon_i = 0;
ParserState_forEachToken(ps, inner) {
ParserState_iterStart(&ps);
if (strEqu(ps.token1.pyload, ":") && ps.branket_deepth == 0) {
colon_i++;
goto iter_continue1;
}
if (colon_i == 0) {
*pStart = strsAppend(&buffs, *pStart, ps.token1.pyload);
}
if (colon_i == 1) {
*pEnd = strsAppend(&buffs, *pEnd, ps.token1.pyload);
}
if (colon_i == 2) {
*pStep = strsAppend(&buffs, *pStep, ps.token1.pyload);
}
iter_continue1:
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
if (colon_i == 1) {
*pStep = "1";
if (strEqu(*pStart, "")) {
*pStart = "0";
}
if (strEqu(*pEnd, "")) {
*pEnd = "-1";
}
}
if (colon_i == 0) {
*pEnd = strsAppend(&buffs, *pStart, " + 1");
*pStep = "1";
}
/* slice with step */
/* output */
*pStart = strsCopy(outBuffs, *pStart);
*pEnd = strsCopy(outBuffs, *pEnd);
*pStep = strsCopy(outBuffs, *pStep);
/* clean */
strsDeinit(&buffs);
}
#endif
#if PIKA_SYNTAX_SLICE_ENABLE
char* Suger_solveLeftBranckets(Args* outBuffs, char* right, char** left_p) {
/* init objects */
Args buffs = {0};
Arg* right_arg = arg_newStr("");
char* left = *left_p;
uint8_t is_in_brancket = 0;
args_setStr(&buffs, "inner", "");
uint8_t matched = 0;
char* right_res = NULL;
/* exit when NULL */
if (NULL == left) {
arg_deinit(right_arg);
right_arg = arg_setStr(right_arg, "", right);
goto exit;
}
/* exit when not match
(symble|iteral)'['
*/
ParserState_forEachToken(ps, left) {
ParserState_iterStart(&ps);
if (strEqu(ps.token2.pyload, "[")) {
if (TOKEN_symbol == ps.token1.type ||
TOKEN_literal == ps.token1.type) {
matched = 1;
ParserState_iterEnd(&ps);
break;
}
}
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
if (!matched) {
/* not contain '[', return origin */
arg_deinit(right_arg);
right_arg = arg_setStr(right_arg, "", right);
goto exit;
}
/* matched [] */
ParserState_forEachTokenExistPs(ps, left) {
ParserState_iterStart(&ps);
/* found '[' */
if ((TOKEN_devider == ps.token2.type) &&
(strEqu(ps.token2.pyload, "["))) {
/* get 'obj' from obj[] */
args_setStr(&buffs, "obj", ps.token1.pyload);
is_in_brancket = 1;
/* fond ']' */
} else if ((TOKEN_devider == ps.token2.type) &&
(strEqu(ps.token2.pyload, "]"))) {
is_in_brancket = 0;
char* inner = args_getStr(&buffs, "inner");
Arg* inner_arg = arg_newStr(inner);
inner_arg = arg_strAppend(inner_arg, ps.token1.pyload);
args_setStr(&buffs, "inner", arg_getStr(inner_arg));
arg_deinit(inner_arg);
/* update inner pointer */
inner = args_getStr(&buffs, "inner");
char* start = NULL;
char* end = NULL;
char* step = NULL;
Slice_getPars(&buffs, inner, &start, &end, &step);
/* obj = __setitem__(obj, key, val) */
right_arg = arg_strAppend(right_arg, "__setitem__(");
right_arg = arg_strAppend(right_arg, args_getStr(&buffs, "obj"));
right_arg = arg_strAppend(right_arg, ",");
right_arg = arg_strAppend(right_arg, start);
right_arg = arg_strAppend(right_arg, ",");
right_arg = arg_strAppend(right_arg, right);
right_arg = arg_strAppend(right_arg, ")");
/* clean the inner */
args_setStr(&buffs, "inner", "");
/* in brancket and found '[' */
} else if (is_in_brancket && (!strEqu(ps.token1.pyload, "["))) {
char* inner = args_getStr(&buffs, "inner");
Arg* index_arg = arg_newStr(inner);
index_arg = arg_strAppend(index_arg, ps.token1.pyload);
args_setStr(&buffs, "inner", arg_getStr(index_arg));
arg_deinit(index_arg);
/* out of brancket and not found ']' */
} else if (!is_in_brancket && (!strEqu(ps.token1.pyload, "]"))) {
if (TOKEN_strEnd != ps.token1.type) {
right_arg = arg_strAppend(right_arg, ps.token1.pyload);
}
}
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
/* clean the left */
for (size_t i = 0; i < strGetSize(left); i++) {
if (left[i] == '[') {
left[i] = '\0';
break;
}
}
exit:
/* clean and return */
right_res = strsCopy(outBuffs, arg_getStr(right_arg));
arg_deinit(right_arg);
strsDeinit(&buffs);
return right_res;
}
#endif
#if PIKA_SYNTAX_FORMAT_ENABLE
char* Suger_solveFormat(Args* outBuffs, char* right) {
/* quick skip */
if (!strIsContain(right, '%')) {
return right;
}
PIKA_BOOL is_format = PIKA_FALSE;
ParserState_forEachToken(ps1, right) {
ParserState_iterStart(&ps1);
if (ps1.branket_deepth == 0 && strEqu(ps1.token1.pyload, "%")) {
is_format = PIKA_TRUE;
}
ParserState_iterEnd(&ps1);
}
ParserState_deinit(&ps1);
if (PIKA_FALSE == is_format) {
return right;
}
char* res = right;
Arg* str_buf = arg_newStr("");
Arg* var_buf = arg_newStr("");
PIKA_BOOL is_in_format = PIKA_FALSE;
PIKA_BOOL is_tuple = PIKA_FALSE;
PIKA_BOOL is_out_vars = PIKA_FALSE;
Args buffs = {0};
char* fmt = NULL;
ParserState_forEachToken(ps, right) {
char* item = "";
ParserState_iterStart(&ps);
if (PIKA_FALSE == is_in_format) {
if (ps.token1.type != TOKEN_literal) {
item = ps.token1.pyload;
goto iter_continue;
}
if (ps.token1.pyload[0] != '\'' && ps.token1.pyload[0] != '"') {
item = ps.token1.pyload;
goto iter_continue;
}
if (!strEqu(ps.token2.pyload, "%")) {
item = ps.token1.pyload;
goto iter_continue;
}
/* found the format stmt */
is_in_format = PIKA_TRUE;
fmt = strsCopy(&buffs, ps.token1.pyload);
goto iter_continue;
}
if (PIKA_TRUE == is_in_format) {
/* check the format vars */
if (strEqu(ps.token1.pyload, "%")) {
/* is a tuple */
if (strEqu(ps.token2.pyload, "(")) {
is_tuple = PIKA_TRUE;
} else {
var_buf = arg_strAppend(var_buf, ps.token2.pyload);
}
goto iter_continue;
}
/* found the end of tuple */
if (ps.iter_index == ps.length) {
is_out_vars = PIKA_TRUE;
is_in_format = PIKA_FALSE;
} else {
/* push the vars inner the tuple */
var_buf = arg_strAppend(var_buf, ps.token2.pyload);
}
if (is_out_vars) {
if (is_tuple) {
str_buf = arg_strAppend(str_buf, "cformat(");
str_buf = arg_strAppend(str_buf, fmt);
str_buf = arg_strAppend(str_buf, ",");
str_buf = arg_strAppend(str_buf, arg_getStr(var_buf));
} else {
str_buf = arg_strAppend(str_buf, "cformat(");
str_buf = arg_strAppend(str_buf, fmt);
str_buf = arg_strAppend(str_buf, ",");
str_buf = arg_strAppend(str_buf, arg_getStr(var_buf));
str_buf = arg_strAppend(str_buf, ")");
}
}
}
iter_continue:
if (!is_in_format) {
str_buf = arg_strAppend(str_buf, item);
}
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
res = strsCopy(outBuffs, arg_getStr(str_buf));
arg_deinit(str_buf);
arg_deinit(var_buf);
strsDeinit(&buffs);
return res;
}
#endif
uint8_t Parser_solveSelfOperator(Args* outbuffs,
char* stmt,
char** right_p,
char** left_p) {
char* left_new = NULL;
char* right_new = NULL;
Arg* left_arg = arg_newStr("");
Arg* right_arg = arg_newStr("");
Arg* right_arg_new = arg_newStr("");
uint8_t is_left_exist = 0;
Args buffs = {0};
char _operator[2] = {0};
char* operator=(char*) _operator;
char* tokens = Lexer_getTokens(&buffs, stmt);
uint8_t is_right = 0;
if (Parser_isContainToken(tokens, TOKEN_operator, "+=")) {
operator[0] = '+';
}
if (Parser_isContainToken(tokens, TOKEN_operator, "-=")) {
operator[0] = '-';
}
if (Parser_isContainToken(tokens, TOKEN_operator, "*=")) {
operator[0] = '*';
}
if (Parser_isContainToken(tokens, TOKEN_operator, "/=")) {
operator[0] = '/';
}
/* not found self operator */
if (operator[0] == 0) {
goto exit;
}
/* found self operator */
is_left_exist = 1;
ParserState_forEachToken(ps, stmt) {
ParserState_iterStart(&ps);
if ((strEqu(ps.token1.pyload, "*=")) ||
(strEqu(ps.token1.pyload, "/=")) ||
(strEqu(ps.token1.pyload, "+=")) ||
(strEqu(ps.token1.pyload, "-="))) {
is_right = 1;
goto iter_continue;
}
if (!is_right) {
left_arg = arg_strAppend(left_arg, ps.token1.pyload);
} else {
right_arg = arg_strAppend(right_arg, ps.token1.pyload);
}
iter_continue:
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
/* connect right */
right_arg_new = arg_strAppend(right_arg_new, arg_getStr(left_arg));
right_arg_new = arg_strAppend(right_arg_new, operator);
right_arg_new = arg_strAppend(right_arg_new, "(");
right_arg_new = arg_strAppend(right_arg_new, arg_getStr(right_arg));
right_arg_new = arg_strAppend(right_arg_new, ")");
/* collect left_new and right_new */
left_new = arg_getStr(left_arg);
right_new = arg_getStr(right_arg_new);
exit:
strsDeinit(&buffs);
if (NULL != right_new) {
*(right_p) = strsCopy(outbuffs, right_new);
;
}
if (NULL != left_new) {
*(left_p) = strsCopy(outbuffs, left_new);
}
arg_deinit(right_arg);
arg_deinit(left_arg);
arg_deinit(right_arg_new);
return is_left_exist;
}
PIKA_RES AST_setThisNode(AST* ast, char* node_type, char* node_content) {
return obj_setStr(ast, node_type, node_content);
}
AST* AST_parseStmt(AST* ast, char* stmt);
PIKA_RES AST_parseSubStmt(AST* ast, char* node_content) {
queueObj_pushObj(ast, (char*)"stmt");
AST_parseStmt(queueObj_getCurrentObj(ast), node_content);
return PIKA_RES_OK;
}
char* Parser_popSubStmt(Args* outbuffs, char** stmt_p, char* delimiter) {
Arg* substmt_arg = arg_newStr("");
Arg* newstmt_arg = arg_newStr("");
char* stmt = *stmt_p;
PIKA_BOOL is_get_substmt = PIKA_FALSE;
Args buffs = {0};
ParserState_forEachToken(ps, stmt) {
ParserState_iterStart(&ps);
if (is_get_substmt) {
/* get new stmt */
newstmt_arg = arg_strAppend(newstmt_arg, ps.token1.pyload);
ParserState_iterEnd(&ps);
continue;
}
if (ps.branket_deepth > 0) {
/* ignore */
substmt_arg = arg_strAppend(substmt_arg, ps.token1.pyload);
ParserState_iterEnd(&ps);
continue;
}
if (strEqu(ps.token1.pyload, delimiter)) {
/* found delimiter */
is_get_substmt = PIKA_TRUE;
ParserState_iterEnd(&ps);
continue;
}
/* collect substmt */
substmt_arg = arg_strAppend(substmt_arg, ps.token1.pyload);
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
strsDeinit(&buffs);
char* substmt = strsCacheArg(outbuffs, substmt_arg);
char* newstmt = strsCacheArg(outbuffs, newstmt_arg);
*stmt_p = newstmt;
return substmt;
}
char* Parser_popLastSubStmt(Args* outbuffs, char** stmt_p, char* delimiter) {
uint8_t last_stmt_i = 0;
char* stmt = *stmt_p;
ParserState_forEachToken(ps, stmt) {
ParserState_iterStart(&ps);
if (strIsStartWith(ps.token1.pyload, delimiter)) {
/* found delimiter */
if (!strEqu(delimiter, "[") && ps.branket_deepth > 0) {
/* ignore */
ParserState_iterEnd(&ps);
continue;
}
/* for "[" */
if (ps.branket_deepth > 1) {
/* ignore */
ParserState_iterEnd(&ps);
continue;
}
last_stmt_i = ps.iter_index;
}
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
Arg* mainStmt = arg_newStr("");
Arg* lastStmt = arg_newStr("");
{
ParserState_forEachToken(ps, stmt) {
ParserState_iterStart(&ps);
if (ps.iter_index < last_stmt_i) {
mainStmt = arg_strAppend(mainStmt, ps.token1.pyload);
}
if (ps.iter_index >= last_stmt_i) {
lastStmt = arg_strAppend(lastStmt, ps.token1.pyload);
}
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
}
*stmt_p = strsCacheArg(outbuffs, mainStmt);
return strsCacheArg(outbuffs, lastStmt);
}
AST* AST_parseStmt(AST* ast, char* stmt) {
Args buffs = {0};
char* assignment = strsGetFirstToken(&buffs, stmt, '(');
char* method = NULL;
char* ref = NULL;
char* str = NULL;
char* num = NULL;
char* left = NULL;
char* right = NULL;
char* import = NULL;
PIKA_RES result = PIKA_RES_OK;
right = stmt;
/* solve check direct */
uint8_t isLeftExist = 0;
if (Parser_checkIsDirect(assignment)) {
isLeftExist = 1;
left = strsCopy(&buffs, "");
right = strsCopy(&buffs, "");
uint8_t is_meet_equ = 0;
ParserState_forEachToken(ps, stmt) {
ParserState_iterStart(&ps);
if (strEqu(ps.token1.pyload, "=") &&
ps.token1.type == TOKEN_operator) {
is_meet_equ = 1;
ParserState_iterEnd(&ps);
continue;
}
if (0 == is_meet_equ) {
left = strsAppend(&buffs, left, ps.token1.pyload);
}
if (1 == is_meet_equ) {
right = strsAppend(&buffs, right, ps.token1.pyload);
}
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
}
/* solve the += -= /= *= stmt */
if (!isLeftExist) {
isLeftExist = Parser_solveSelfOperator(&buffs, stmt, &right, &left);
}
#if PIKA_SYNTAX_SLICE_ENABLE
/* solve the [] stmt */
right = Suger_solveLeftBranckets(&buffs, right, &left);
#endif
#if PIKA_SYNTAX_FORMAT_ENABLE
right = Suger_solveFormat(&buffs, right);
#endif
/* set left */
if (isLeftExist) {
AST_setThisNode(ast, (char*)"left", left);
}
/* match statment type */
enum StmtType stmtType = Lexer_matchStmtType(right);
/* solve operator stmt */
if (STMT_operator == stmtType) {
char* rightWithoutSubStmt = strsDeleteBetween(&buffs, right, '(', ')');
char* operator= Lexer_getOperator(&buffs, rightWithoutSubStmt);
if (NULL == operator) {
result = PIKA_RES_ERR_SYNTAX_ERROR;
goto exit;
}
AST_setThisNode(ast, (char*)"operator", operator);
char* rightBuff = strsCopy(&buffs, right);
char* subStmt1 =
strsPopTokenWithSkip_byStr(&buffs, rightBuff, operator, '(', ')');
char* subStmt2 = rightBuff;
AST_parseSubStmt(ast, subStmt1);
AST_parseSubStmt(ast, subStmt2);
goto exit;
}
#if PIKA_BUILTIN_STRUCT_ENABLE
/* solve list stmt */
if (STMT_list == stmtType) {
AST_setThisNode(ast, (char*)"list", "list");
char* subStmts = strsCut(&buffs, right, '[', ']');
subStmts = strsAppend(&buffs, subStmts, ",");
while (1) {
char* subStmt = Parser_popSubStmt(&buffs, &subStmts, ",");
AST_parseSubStmt(ast, subStmt);
if (strEqu(subStmts, "")) {
break;
}
}
goto exit;
}
#endif
#if PIKA_BUILTIN_STRUCT_ENABLE
/* solve dict stmt */
if (STMT_dict == stmtType) {
AST_setThisNode(ast, (char*)"dict", "dict");
char* subStmts = strsCut(&buffs, right, '{', '}');
subStmts = strsAppend(&buffs, subStmts, ",");
while (1) {
char* subStmt = Parser_popSubStmt(&buffs, &subStmts, ",");
char* key = Parser_popSubStmt(&buffs, &subStmt, ":");
char* value = subStmt;
AST_parseSubStmt(ast, key);
AST_parseSubStmt(ast, value);
if (strEqu(subStmts, "")) {
break;
}
}
goto exit;
}
#endif
/* solve method chain */
if (STMT_chain == stmtType) {
char* stmt = strsCopy(&buffs, right);
char* lastStmt = Parser_popLastSubStmt(&buffs, &stmt, ".");
AST_parseSubStmt(ast, stmt);
AST_parseStmt(ast, lastStmt);
goto exit;
}
#if PIKA_SYNTAX_SLICE_ENABLE
if (STMT_slice == stmtType) {
/* solve slice stmt */
AST_setThisNode(ast, (char*)"slice", "slice");
char* stmt = strsCopy(&buffs, right);
char* laststmt = Parser_popLastSubStmt(&buffs, &stmt, "[");
AST_parseSubStmt(ast, stmt);
char* slice_list = strsCut(&buffs, laststmt, '[', ']');
slice_list = strsAppend(&buffs, slice_list, ":");
int index = 0;
while (1) {
char* slice_str = Parser_popSubStmt(&buffs, &slice_list, ":");
if (index == 0 && strEqu(slice_str, "")) {
AST_parseSubStmt(ast, "0");
} else if (index == 1 && strEqu(slice_str, "")) {
AST_parseSubStmt(ast, "-1");
} else {
AST_parseSubStmt(ast, slice_str);
}
index++;
if (strEqu("", slice_list)) {
break;
}
}
goto exit;
}
#endif
/* solve method stmt */
if (STMT_method == stmtType) {
method = strsGetFirstToken(&buffs, right, '(');
AST_setThisNode(ast, (char*)"method", method);
char* subStmts = strsCut(&buffs, right, '(', ')');
pika_assert(NULL != subStmts);
/* add ',' at the end */
subStmts = strsAppend(&buffs, subStmts, ",");
while (1) {
char* substmt = Parser_popSubStmt(&buffs, &subStmts, ",");
AST_parseSubStmt(ast, substmt);
if (strEqu("", subStmts)) {
break;
}
}
goto exit;
}
/* solve reference stmt */
if (STMT_reference == stmtType) {
ref = right;
AST_setThisNode(ast, (char*)"ref", ref);
goto exit;
}
/* solve import stmt */
if (STMT_import == stmtType) {
import = strsGetLastToken(&buffs, right, ' ');
AST_setThisNode(ast, (char*)"import", import);
goto exit;
}
/* solve str stmt */
if (STMT_string == stmtType) {
str = strsCopy(&buffs, right);
/* remove the first char */
str = str + 1;
/* remove the last char */
str[strGetSize(str) - 1] = '\0';
/* replace */
if (strIsContain(str, '\\')) {
str = strsReplace(&buffs, str, "\\\"", "\"");
str = strsReplace(&buffs, str, "\\'", "'");
}
AST_setThisNode(ast, (char*)"string", str);
goto exit;
}
/* solve bytes stmt */
if (STMT_bytes == stmtType) {
str = right + 1;
str = strsDeleteChar(&buffs, str, '\'');
str = strsDeleteChar(&buffs, str, '\"');
AST_setThisNode(ast, (char*)"bytes", str);
goto exit;
}
/* solve number stmt */
if (STMT_number == stmtType) {
num = right;
AST_setThisNode(ast, (char*)"num", num);
goto exit;
}
exit:
strsDeinit(&buffs);
if (result != PIKA_RES_OK) {
AST_deinit(ast);
return NULL;
}
return ast;
}
static int32_t Parser_getPyLineBlockDeepth(char* line) {
uint32_t size = strGetSize(line);
for (uint32_t i = 0; i < size; i++) {
if (line[i] != ' ') {
uint32_t spaceNum = i;
if (0 == spaceNum % 4) {
return spaceNum / 4;
}
/* space Num is not 4N, error*/
return -1;
}
}
return 0;
}
char* Parser_removeAnnotation(char* line) {
uint8_t is_annotation_exit = 0;
uint8_t is_in_single_quotes = 0;
uint8_t is_in_double_quotes_deepth = 0;
for (uint32_t i = 0; i < strGetSize(line); i++) {
if ('\'' == line[i]) {
is_in_single_quotes = !is_in_single_quotes;
continue;
}
if ('"' == line[i]) {
is_in_double_quotes_deepth = !is_in_double_quotes_deepth;
continue;
}
if (!(is_in_single_quotes == 0 && is_in_double_quotes_deepth == 0)) {
continue;
}
if ('#' == line[i]) {
/* end the line */
line[i] = 0;
is_annotation_exit = 1;
break;
}
}
/* no annotation, exit */
if (!is_annotation_exit) {
return line;
}
/* check empty line */
for (uint32_t i = 0; i < strGetSize(line); i++) {
if (' ' != line[i]) {
return line;
}
}
/* is an emply line */
line = "@annontation";
return line;
}
/* match block start keywords */
const char control_keywords[][9] = {"break", "continue"};
/* normal keyward */
const char normal_keywords[][7] = {"while", "if", "elif"};
AST* AST_parseLine(char* line, Stack* block_stack) {
/* line is not exist */
if (line == NULL) {
return NULL;
}
/* init data */
AST* ast = New_queueObj();
Args buffs = {0};
int8_t block_deepth_now, block_deepth_last = -1;
char *line_start, *stmt;
/* get block deepth */
block_deepth_now = Parser_getPyLineBlockDeepth(line);
/* set block deepth */
if (block_deepth_now == -1) {
/* get block_deepth error */
__platform_printf(
"IndentationError: unexpected indent, only support 4 spaces\r\n");
obj_deinit(ast);
ast = NULL;
goto exit;
}
obj_setInt(ast, "blockDeepth", block_deepth_now);
/* check if exit block */
if (NULL != block_stack) {
block_deepth_last = stack_getTop(block_stack);
/* exit each block */
for (int i = 0; i < block_deepth_last - block_deepth_now; i++) {
QueueObj* exit_block_queue = obj_getObj(ast, "exitBlock");
/* create an exit_block queue */
if (NULL == exit_block_queue) {
obj_newObj(ast, "exitBlock", "", New_TinyObj);
exit_block_queue = obj_getObj(ast, "exitBlock");
queueObj_init(exit_block_queue);
}
char buff[10] = {0};
char* block_type = stack_popStr(block_stack, buff);
/* push exit block type to exit_block queue */
queueObj_pushStr(exit_block_queue, block_type);
}
}
line_start = line + block_deepth_now * 4;
stmt = line_start;
// "while" "if" "elif"
for (uint32_t i = 0; i < sizeof(normal_keywords) / 7; i++) {
char* keyword = (char*)normal_keywords[i];
uint8_t keyword_len = strGetSize(keyword);
if (strIsStartWith(line_start, keyword) &&
(line_start[keyword_len] == ' ')) {
stmt = strsCut(&buffs, line_start, ' ', ':');
AST_setThisNode(ast, "block", keyword);
if (NULL != block_stack) {
stack_pushStr(block_stack, keyword);
}
goto block_matched;
}
}
/* contral keyward */
/* "break", "continue" */
for (uint32_t i = 0; i < sizeof(control_keywords) / 8; i++) {
char* keyward = (char*)control_keywords[i];
uint8_t keyward_size = strGetSize(keyward);
if ((strIsStartWith(line_start, keyward)) &&
((line_start[keyward_size] == ' ') ||
(line_start[keyward_size] == 0))) {
AST_setThisNode(ast, keyward, "");
stmt = "";
goto block_matched;
}
}
/* for */
if (strIsStartWith(line_start, "for ")) {
Args* list_buffs = New_strBuff();
char* line_buff = strsCopy(list_buffs, line_start + 4);
char* arg_in = strsPopToken(list_buffs, line_buff, ' ');
AST_setThisNode(ast, "arg_in", arg_in);
strsPopToken(list_buffs, line_buff, ' ');
char* list_in = strsPopToken(list_buffs, line_buff, ':');
list_in = strsAppend(list_buffs, "iter(", list_in);
list_in = strsAppend(list_buffs, list_in, ")");
list_in = strsCopy(&buffs, list_in);
args_deinit(list_buffs);
AST_setThisNode(ast, "block", "for");
AST_setThisNode(ast, "list_in", list_in);
if (NULL != block_stack) {
stack_pushStr(block_stack, "for");
}
stmt = list_in;
goto block_matched;
}
/* else */
if (strIsStartWith(line_start, "else")) {
if ((line_start[4] == ' ') || (line_start[4] == ':')) {
stmt = "";
AST_setThisNode(ast, "block", "else");
if (NULL != block_stack) {
stack_pushStr(block_stack, "else");
}
}
goto block_matched;
}
#if PIKA_SYNTAX_EXCEPTION_ENABLE
/* try */
if (strIsStartWith(line_start, "try")) {
if ((line_start[3] == ' ') || (line_start[3] == ':')) {
stmt = "";
AST_setThisNode(ast, "block", "try");
if (NULL != block_stack) {
stack_pushStr(block_stack, "try");
}
}
goto block_matched;
}
/* except */
if (strIsStartWith(line_start, "except")) {
if ((line_start[6] == ' ') || (line_start[6] == ':')) {
stmt = "";
AST_setThisNode(ast, "block", "except");
if (NULL != block_stack) {
stack_pushStr(block_stack, "except");
}
}
goto block_matched;
}
#endif
if (strEqu(line_start, "return")) {
AST_setThisNode(ast, "return", "");
stmt = "";
goto block_matched;
}
if (strIsStartWith(line_start, "return ")) {
char* lineBuff = strsCopy(&buffs, line_start);
strsPopToken(&buffs, lineBuff, ' ');
stmt = lineBuff;
AST_setThisNode(ast, "return", "");
goto block_matched;
}
#if PIKA_SYNTAX_EXCEPTION_ENABLE
if (strEqu(line_start, "raise")) {
AST_setThisNode(ast, "raise", "");
stmt = "RuntimeError";
goto block_matched;
}
if (strIsStartWith(line_start, "raise ")) {
char* lineBuff = strsCopy(&buffs, line_start);
strsPopToken(&buffs, lineBuff, ' ');
stmt = lineBuff;
if (strEqu("", stmt)) {
stmt = "RuntimeError";
}
AST_setThisNode(ast, "raise", "");
goto block_matched;
}
#endif
if (strIsStartWith(line_start, "global ")) {
stmt = "";
char* global_list = line_start + 7;
global_list = strsGetCleanCmd(&buffs, global_list);
AST_setThisNode(ast, "global", global_list);
goto block_matched;
}
if (strIsStartWith(line_start, "del ")) {
stmt = "";
char* del_dir = line_start + sizeof("del ") - 1;
del_dir = strsGetCleanCmd(&buffs, del_dir);
AST_setThisNode(ast, "del", del_dir);
goto block_matched;
}
if (strIsStartWith(line_start, (char*)"def ")) {
stmt = "";
char* declear = strsCut(&buffs, line_start, ' ', ':');
declear = strsGetCleanCmd(&buffs, declear);
AST_setThisNode(ast, "block", "def");
AST_setThisNode(ast, "declear", declear);
if (NULL != block_stack) {
stack_pushStr(block_stack, "def");
}
goto block_matched;
}
if (strIsStartWith(line_start, (char*)"class ")) {
stmt = "";
char* declear = strsCut(&buffs, line_start, ' ', ':');
declear = strsGetCleanCmd(&buffs, declear);
AST_setThisNode(ast, "block", "class");
AST_setThisNode(ast, "declear", declear);
if (NULL != block_stack) {
stack_pushStr(block_stack, "class");
}
goto block_matched;
}
block_matched:
if (NULL == stmt) {
AST_deinit(ast);
ast = NULL;
goto exit;
}
stmt = strsGetCleanCmd(&buffs, stmt);
ast = AST_parseStmt(ast, stmt);
goto exit;
exit:
strsDeinit(&buffs);
return ast;
}
#if PIKA_SYNTAX_IMPORT_EX_ENABLE
static char* Suger_import(Args* buffs_p, char* line) {
Args buffs = {0};
char* line_out = line;
char* alias = NULL;
char* origin = NULL;
char* stmt = line + 7;
if (!strIsStartWith(line, "import ")) {
line_out = line;
goto exit;
}
ParserState_forEachToken(ps, stmt) {
ParserState_iterStart(&ps);
/* defaut set the 'origin' as the first token */
if (ps.iter_index == 1) {
origin = strsCopy(&buffs, ps.token1.pyload);
}
if (strEqu(ps.token2.pyload, " as ")) {
origin = strsCopy(&buffs, ps.token1.pyload);
}
if (strEqu(ps.token1.pyload, " as ")) {
alias = strsCopy(&buffs, ps.token2.pyload);
}
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
/* only import, not 'as' */
if (NULL == alias) {
line_out = line;
goto exit;
}
/* 'import' and 'as' */
line_out = strsFormat(&buffs, PIKA_LINE_BUFF_SIZE, "import %s\n%s = %s",
origin, alias, origin);
line_out = strsCopy(buffs_p, line_out);
goto exit;
exit:
strsDeinit(&buffs);
return line_out;
}
#endif
#if PIKA_SYNTAX_IMPORT_EX_ENABLE
static char* Suger_from(Args* buffs_p, char* line) {
Args buffs = {0};
char* line_out = line;
char* class = NULL;
char* module = NULL;
char* alias = NULL;
char* stmt = line + 5;
if (!strIsStartWith(line, "from ")) {
line_out = line;
goto exit;
}
ParserState_forEachToken(ps, stmt) {
ParserState_iterStart(&ps);
if (strEqu(ps.token2.pyload, " import ")) {
module = strsCopy(&buffs, ps.token1.pyload);
}
if (strEqu(ps.token1.pyload, " import ")) {
class = strsCopy(&buffs, ps.token2.pyload);
}
if (strEqu(ps.token1.pyload, " as ")) {
alias = strsCopy(&buffs, ps.token2.pyload);
}
ParserState_iterEnd(&ps);
}
ParserState_deinit(&ps);
if (NULL == module) {
line_out = strsCopy(buffs_p, "");
goto exit;
}
if (NULL == class) {
line_out = strsCopy(buffs_p, "");
goto exit;
}
if (NULL == alias) {
alias = class;
}
/* skip PikaObj */
if (strEqu(module, "PikaObj")) {
line_out = strsCopy(buffs_p, "");
goto exit;
}
line_out = strsFormat(&buffs, PIKA_LINE_BUFF_SIZE, "import %s\n%s = %s.%s",
module, alias, module, class);
line_out = strsCopy(buffs_p, line_out);
exit:
strsDeinit(&buffs);
return line_out;
}
#endif
static char* Parser_linePreProcess(Args* buffs_p, char* line) {
line = Parser_removeAnnotation(line);
/* check syntex error */
if (Lexer_isError(line)) {
line = NULL;
goto exit;
}
/* process EOL */
line = strsDeleteChar(buffs_p, line, '\r');
#if PIKA_SYNTAX_IMPORT_EX_ENABLE
line = Suger_import(buffs_p, line);
line = Suger_from(buffs_p, line);
#endif
exit:
return line;
}
char* Parser_LineToAsm(Args* buffs_p, char* line, Stack* blockStack) {
char* ASM = NULL;
AST* ast = NULL;
uint8_t line_num = 0;
/* pre process */
line = Parser_linePreProcess(buffs_p, line);
if (NULL == line) {
/* preprocess error */
goto exit;
}
if (strEqu("@annontation", line)) {
ASM = "";
goto exit;
}
/*
solve more lines
preprocess may generate more lines
*/
line_num = strCountSign(line, '\n') + 1;
for (int i = 0; i < line_num; i++) {
char* single_line = strsPopToken(buffs_p, line, '\n');
/* parse tokens to AST */
ast = AST_parseLine(single_line, blockStack);
/* gen ASM from AST */
if (ASM == NULL) {
ASM = AST_toPikaASM(ast, buffs_p);
} else {
ASM = strsAppend(buffs_p, ASM, AST_toPikaASM(ast, buffs_p));
}
if (NULL != ast) {
AST_deinit(ast);
}
}
exit:
return ASM;
}
static int Parser_isVoidLine(char* line) {
for (uint32_t i = 0; i < strGetSize(line); i++) {
if (line[i] != ' ') {
return 0;
}
}
return 1;
}
static uint8_t Parser_checkIsMultiComment(char* line) {
for (uint32_t i = 0; i < strGetSize(line); i++) {
/* not match ' or " */
if ((line[i] != '\'') && (line[i] != '"')) {
continue;
}
/* not match ''' or """ */
if (!((line[i + 1] == line[i]) && (line[i + 2] == line[i]))) {
continue;
}
/* check char befor the ''' or """ */
if (!((0 == i) || (line[i - 1] == ' '))) {
continue;
}
/* check char after the ''' or """ */
if (!((line[i + 3] == ' ') || (line[i + 3] == 0))) {
continue;
}
/* mached */
return 1;
}
/* not mached */
return 0;
}
char* Parser_parsePyLines(Args* outBuffs,
ByteCodeFrame* bytecode_frame,
char* py_lines) {
Stack block_stack;
stack_init(&block_stack);
Arg* asm_buff = arg_newStr("");
uint32_t lines_offset = 0;
uint32_t lines_size = strGetSize(py_lines);
uint16_t lines_num = strCountSign(py_lines, '\n');
uint16_t lines_index = 0;
uint8_t is_in_multi_comment = 0;
Arg* line_connection_arg = arg_newStr("");
uint8_t is_line_connection = 0;
char* out_ASM = NULL;
char* single_ASM;
uint32_t line_size = 0;
/* parse each line */
while (1) {
lines_index++;
Args buffs = {0};
/* get single line by pop multiline */
char* line_origin =
strsGetFirstToken(&buffs, py_lines + lines_offset, '\n');
char* line = strsCopy(&buffs, line_origin);
/* line connection */
if (is_line_connection) {
is_line_connection = 0;
line_connection_arg = arg_strAppend(line_connection_arg, line);
line = strsCopy(&buffs, arg_getStr(line_connection_arg));
/* reflash the line_connection_arg */
arg_deinit(line_connection_arg);
line_connection_arg = arg_newStr("");
}
/* check connection */
if ('\\' == line[strGetSize(line) - 1]) {
/* remove the '\\' */
line[strGetSize(line) - 1] = '\0';
is_line_connection = 1;
line_connection_arg = arg_strAppend(line_connection_arg, line);
goto next_line;
}
/* support Tab */
line = strsReplace(&buffs, line, "\t", " ");
/* filter for not end \n */
if (lines_index != lines_num) {
if (Parser_isVoidLine(line)) {
goto next_line;
}
}
/* filter for multiline comment ''' or """ */
if (Parser_checkIsMultiComment(line)) {
is_in_multi_comment = ~is_in_multi_comment;
goto next_line;
}
/* skipe multiline comment */
if (is_in_multi_comment) {
goto next_line;
}
/* parse single Line to Asm */
single_ASM = Parser_LineToAsm(&buffs, line, &block_stack);
#if PIKA_DEBUG
pika_assert(NULL != single_ASM);
#endif
if (NULL == single_ASM) {
out_ASM = NULL;
strsDeinit(&buffs);
goto exit;
}
if (NULL == bytecode_frame) {
/* store ASM */
asm_buff = arg_strAppend(asm_buff, single_ASM);
} else if (NULL == outBuffs) {
/* store ByteCode */
byteCodeFrame_appendFromAsm(bytecode_frame, single_ASM);
}
next_line:
line_size = strGetSize(line_origin);
lines_offset = lines_offset + line_size + 1;
strsDeinit(&buffs);
/* exit when finished */
if (lines_offset >= lines_size) {
break;
}
}
if (NULL != outBuffs) {
/* load stored ASM */
out_ASM = strsCopy(outBuffs, arg_getStr(asm_buff));
} else {
out_ASM = (char*)1;
}
goto exit;
exit:
if (NULL != asm_buff) {
arg_deinit(asm_buff);
}
if (NULL != line_connection_arg) {
arg_deinit(line_connection_arg);
}
stack_deinit(&block_stack);
return out_ASM;
};
int bytecodeFrame_fromMultiLine(ByteCodeFrame* bytecode_frame,
char* multi_line) {
if (NULL == Parser_parsePyLines(NULL, bytecode_frame, multi_line)) {
/* error */
return 1;
}
/* succeed */
return 0;
};
char* Parser_multiLineToAsm(Args* outBuffs, char* multi_line) {
return Parser_parsePyLines(outBuffs, NULL, multi_line);
}
char* Parser_fileToAsm(Args* outBuffs, char* filename) {
Args buffs = {0};
Arg* file_arg = arg_loadFile(NULL, filename);
pika_assert(NULL != file_arg);
if (NULL == file_arg) {
return NULL;
}
char* lines = (char*)arg_getBytes(file_arg);
/* replace the "\r\n" to "\n" */
lines = strsReplace(&buffs, lines, "\r\n", "\n");
/* clear the void line */
lines = strsReplace(&buffs, lines, "\n\n", "\n");
/* add '\n' at the end */
lines = strsAppend(&buffs, lines, "\n\n");
char* res = Parser_multiLineToAsm(&buffs, lines);
arg_deinit(file_arg);
strsDeinit(&buffs);
return res;
}
char* AST_appandPikaASM(AST* ast, AST* subAst, Args* outBuffs, char* pikaAsm) {
int deepth = obj_getInt(ast, "deepth");
Args buffs = {0};
while (1) {
QueueObj* subStmt = queueObj_popObj(subAst);
if (NULL == subStmt) {
break;
}
obj_setInt(ast, "deepth", deepth + 1);
pikaAsm = AST_appandPikaASM(ast, subStmt, &buffs, pikaAsm);
}
char* buff = args_getBuff(&buffs, PIKA_SPRINTF_BUFF_SIZE);
/* append the syntax item */
for (size_t i = 0; i < sizeof(syntexItemList) / sizeof(SyntaxItem); i++) {
char* astNodeVal = obj_getStr(subAst, syntexItemList[i].astNodeName);
if (NULL != astNodeVal) {
/* e.g. "0 RUN print \n" */
__platform_sprintf(buff, "%d %s ", deepth,
syntexItemList[i].asmCode);
Arg* abuff = arg_newStr(buff);
if (syntexItemList[i].isUseNodeValue) {
abuff = arg_strAppend(abuff, astNodeVal);
}
abuff = arg_strAppend(abuff, "\n");
pikaAsm = strsAppend(&buffs, pikaAsm, arg_getStr(abuff));
arg_deinit(abuff);
}
}
obj_setInt(ast, "deepth", deepth - 1);
goto exit;
exit:
pikaAsm = strsCopy(outBuffs, pikaAsm);
strsDeinit(&buffs);
return pikaAsm;
}
char* ASM_addBlockDeepth(AST* ast,
Args* buffs_p,
char* pikaAsm,
uint8_t deepthOffset) {
pikaAsm = strsAppend(buffs_p, pikaAsm, (char*)"B");
char buff[11];
pikaAsm = strsAppend(
buffs_p, pikaAsm,
fast_itoa(buff, obj_getInt(ast, "blockDeepth") + deepthOffset));
pikaAsm = strsAppend(buffs_p, pikaAsm, (char*)"\n");
return pikaAsm;
}
char* AST_toPikaASM(AST* ast, Args* outBuffs) {
Args buffs = {0};
char* pikaAsm = strsCopy(&buffs, "");
QueueObj* exitBlock;
uint8_t is_block_matched;
if (NULL == ast) {
pikaAsm = NULL;
goto exit;
}
exitBlock = obj_getObj(ast, "exitBlock");
/* exiting from block */
if (exitBlock != NULL) {
while (1) {
uint8_t block_type_num = obj_getInt(exitBlock, "top") -
obj_getInt(exitBlock, "bottom") - 1;
char* block_type = queueObj_popStr(exitBlock);
if (NULL == block_type) {
break;
}
/* goto the while start when exit while block */
if (strEqu(block_type, "while")) {
pikaAsm =
ASM_addBlockDeepth(ast, outBuffs, pikaAsm, block_type_num);
pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 JMP -1\n");
}
#if PIKA_SYNTAX_EXCEPTION_ENABLE
/* goto the while start when exit while block */
if (strEqu(block_type, "try")) {
pikaAsm =
ASM_addBlockDeepth(ast, outBuffs, pikaAsm, block_type_num);
pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 NTR \n");
pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 GER \n");
pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 JEZ 2\n");
}
if (strEqu(block_type, "except")) {
pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 SER 0\n");
}
#endif
/* goto the while start when exit while block */
if (strEqu(block_type, "for")) {
pikaAsm =
ASM_addBlockDeepth(ast, outBuffs, pikaAsm, block_type_num);
pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 JMP -1\n");
/* garbage collect for the list */
pikaAsm =
ASM_addBlockDeepth(ast, outBuffs, pikaAsm, block_type_num);
char _l_x[] = "_lx";
char block_deepth_char =
obj_getInt(ast, "blockDeepth") + block_type_num + '0';
_l_x[sizeof(_l_x) - 2] = block_deepth_char;
pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 DEL ");
pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)_l_x);
pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"\n");
}
/* return when exit method */
if (strEqu(block_type, "def")) {
pikaAsm = ASM_addBlockDeepth(ast, outBuffs, pikaAsm,
block_type_num + 1);
pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 RET \n");
}
/* return when exit class */
if (strEqu(block_type, "class")) {
pikaAsm = ASM_addBlockDeepth(ast, outBuffs, pikaAsm,
block_type_num + 1);
pikaAsm =
strsAppend(outBuffs, pikaAsm, (char*)"0 RAS $origin\n");
pikaAsm = ASM_addBlockDeepth(ast, outBuffs, pikaAsm, 1);
pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 NEW self\n");
pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 RET \n");
}
}
}
/* add block deepth */
/* example: B0 */
pikaAsm = ASM_addBlockDeepth(ast, outBuffs, pikaAsm, 0);
/* "deepth" is invoke deepth, not the blockDeepth */
obj_setInt(ast, "deepth", 0);
/* match block */
is_block_matched = 0;
if (strEqu(obj_getStr(ast, "block"), "for")) {
/* for "for" iter */
char* arg_in = obj_getStr(ast, "arg_in");
Arg* newAsm_arg = arg_newStr("");
char _l_x[] = "_lx";
char block_deepth_char = '0';
block_deepth_char += obj_getInt(ast, "blockDeepth");
_l_x[sizeof(_l_x) - 2] = block_deepth_char;
/* init iter */
/* get the iter(_l<x>) */
pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm);
newAsm_arg = arg_strAppend(newAsm_arg, "0 OUT ");
newAsm_arg = arg_strAppend(newAsm_arg, _l_x);
newAsm_arg = arg_strAppend(newAsm_arg, "\n");
pikaAsm = strsAppend(&buffs, pikaAsm, arg_getStr(newAsm_arg));
arg_deinit(newAsm_arg);
newAsm_arg = arg_newStr("");
/* get next */
/* run next(_l<x>) */
/* check item is exist */
pikaAsm = ASM_addBlockDeepth(ast, outBuffs, pikaAsm, 0);
newAsm_arg = arg_strAppend(newAsm_arg, "0 RUN ");
newAsm_arg = arg_strAppend(newAsm_arg, _l_x);
newAsm_arg = arg_strAppend(newAsm_arg,
".__next__\n"
"0 OUT ");
newAsm_arg = arg_strAppend(newAsm_arg, arg_in);
newAsm_arg = arg_strAppend(newAsm_arg,
"\n"
"0 EST ");
newAsm_arg = arg_strAppend(newAsm_arg, arg_in);
newAsm_arg = arg_strAppend(newAsm_arg, "\n0 JEZ 2\n");
pikaAsm = strsAppend(&buffs, pikaAsm, arg_getStr(newAsm_arg));
arg_deinit(newAsm_arg);
is_block_matched = 1;
goto exit;
}
if (strEqu(obj_getStr(ast, "block"), "while")) {
/* parse stmt ast */
pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm);
pikaAsm = strsAppend(&buffs, pikaAsm, "0 JEZ 2\n");
is_block_matched = 1;
goto exit;
}
if (strEqu(obj_getStr(ast, "block"), "if")) {
/* parse stmt ast */
pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm);
pikaAsm = strsAppend(&buffs, pikaAsm, "0 JEZ 1\n");
is_block_matched = 1;
goto exit;
}
if (strEqu(obj_getStr(ast, "block"), "else")) {
pikaAsm = strsAppend(&buffs, pikaAsm, "0 NEL 1\n");
goto exit;
}
#if PIKA_SYNTAX_EXCEPTION_ENABLE
if (strEqu(obj_getStr(ast, "block"), "try")) {
pikaAsm = strsAppend(&buffs, pikaAsm, "0 TRY \n");
goto exit;
}
#endif
if (strEqu(obj_getStr(ast, "block"), "elif")) {
/* skip if __else is 0 */
pikaAsm = strsAppend(&buffs, pikaAsm, "0 NEL 1\n");
/* parse stmt ast */
pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm);
/* skip if stmt is 0 */
pikaAsm = strsAppend(&buffs, pikaAsm, "0 JEZ 1\n");
is_block_matched = 1;
goto exit;
}
if (strEqu(obj_getStr(ast, "block"), "def")) {
pikaAsm = strsAppend(&buffs, pikaAsm, "0 DEF ");
pikaAsm = strsAppend(&buffs, pikaAsm, obj_getStr(ast, "declear"));
pikaAsm = strsAppend(&buffs, pikaAsm,
"\n"
"0 JMP 1\n");
is_block_matched = 1;
goto exit;
}
if (strEqu(obj_getStr(ast, "block"), "class")) {
char* declear = obj_getStr(ast, "declear");
char* thisClass = NULL;
char* superClass = NULL;
if (strIsContain(declear, '(')) {
thisClass = strsGetFirstToken(&buffs, declear, '(');
superClass = strsCut(&buffs, declear, '(', ')');
} else {
thisClass = declear;
superClass = "";
}
if (strEqu("", superClass)) {
/* default superClass */
superClass = "TinyObj";
}
if (strEqu("TinyObj", superClass)) {
/* default superClass */
superClass = "TinyObj";
}
pikaAsm = strsAppend(&buffs, pikaAsm, "0 CLS ");
pikaAsm = strsAppend(&buffs, pikaAsm,
strsAppend(&buffs, thisClass,
"()\n"
"0 JMP 1\n"));
char block_deepth_str[] = "B0\n";
/* goto deeper block */
block_deepth_str[1] += obj_getInt(ast, "blockDeepth") + 1;
pikaAsm = strsAppend(&buffs, pikaAsm, block_deepth_str);
pikaAsm = strsAppend(&buffs, pikaAsm, "0 RUN ");
pikaAsm = strsAppend(&buffs, pikaAsm, superClass);
pikaAsm = strsAppend(&buffs, pikaAsm, "\n");
pikaAsm = strsAppend(&buffs, pikaAsm, "0 OUT self\n");
pikaAsm = strsAppend(&buffs, pikaAsm, block_deepth_str);
pikaAsm = strsAppend(&buffs, pikaAsm, "0 RAS self\n");
is_block_matched = 1;
goto exit;
}
if (obj_isArgExist(ast, "return")) {
/* parse stmt ast */
pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm);
pikaAsm = strsAppend(&buffs, pikaAsm, "0 RET \n");
is_block_matched = 1;
goto exit;
}
#if PIKA_SYNTAX_EXCEPTION_ENABLE
if (obj_isArgExist(ast, "raise")) {
/* parse stmt ast */
pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm);
pikaAsm = strsAppend(&buffs, pikaAsm, "0 RIS \n");
is_block_matched = 1;
goto exit;
}
#endif
if (obj_isArgExist(ast, "global")) {
/* parse stmt ast */
pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm);
pikaAsm = strsAppend(&buffs, pikaAsm, "0 GLB ");
pikaAsm = strsAppend(&buffs, pikaAsm, obj_getStr(ast, "global"));
pikaAsm = strsAppend(&buffs, pikaAsm, "\n");
is_block_matched = 1;
goto exit;
}
if (obj_isArgExist(ast, "del")) {
/* parse stmt ast */
pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm);
pikaAsm = strsAppend(&buffs, pikaAsm, "0 DEL ");
pikaAsm = strsAppend(&buffs, pikaAsm, obj_getStr(ast, "del"));
pikaAsm = strsAppend(&buffs, pikaAsm, "\n");
is_block_matched = 1;
goto exit;
}
if (obj_isArgExist(ast, "break")) {
/* parse stmt ast */
pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm);
pikaAsm = strsAppend(&buffs, pikaAsm, "0 BRK \n");
is_block_matched = 1;
goto exit;
}
if (obj_isArgExist(ast, "continue")) {
/* parse stmt ast */
pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm);
pikaAsm = strsAppend(&buffs, pikaAsm, "0 CTN \n");
is_block_matched = 1;
goto exit;
}
exit:
if (NULL == pikaAsm) {
strsDeinit(&buffs);
return NULL;
}
if (!is_block_matched) {
/* parse stmt ast */
pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm);
}
/* output pikaAsm */
pikaAsm = strsCopy(outBuffs, pikaAsm);
strsDeinit(&buffs);
return pikaAsm;
}
int32_t AST_deinit(AST* ast) {
return obj_deinit(ast);
}
ByteCodeFrame* byteCodeFrame_appendFromAsm(ByteCodeFrame* self, char* pikaAsm) {
Asmer asmer = {
.asm_code = pikaAsm,
.block_deepth_now = 0,
.is_new_line = 0,
.line_pointer = pikaAsm,
};
uint16_t const_pool_offset;
uint16_t exist_offset;
int invoke_deepth_int = 0;
for (int i = 0; i < strCountSign(pikaAsm, '\n'); i++) {
Args buffs = {0};
char* line = strsGetLine(&buffs, asmer.line_pointer);
char* data = NULL;
char ins_str[4] = "";
char invoke_deepth[3] = "";
uint8_t space_num = 0;
uint8_t invoke_deepth_i = 0;
uint8_t ins_str_i = 0;
Arg* line_buff = arg_newStr(line);
strsDeinit(&buffs);
line = arg_getStr(line_buff);
InstructUnit ins_unit = {0};
/* remove '\r' */
if (line[strGetSize(line) - 1] == '\r') {
line[strGetSize(line) - 1] = 0;
}
/* process block deepth flag*/
if ('B' == line[0]) {
asmer.block_deepth_now = fast_atoi(line + 1);
asmer.is_new_line = 1;
goto next_line;
}
/* process each ins */
/* get constPool offset */
const_pool_offset = 0;
for (int i = 0; i < (int)strGetSize(line); i++) {
if (space_num < 2) {
if (line[i] == ' ') {
space_num++;
if (space_num == 2) {
data = line + i + 1;
break;
}
continue;
}
}
if (space_num == 0) {
invoke_deepth[invoke_deepth_i++] = line[i];
continue;
}
if (space_num == 1) {
ins_str[ins_str_i++] = line[i];
continue;
}
}
exist_offset = constPool_getOffsetByData(&(self->const_pool), data);
/* get const offset */
if (strEqu(data, "")) {
/* not need const value */
const_pool_offset = 0;
} else if (65535 == exist_offset) {
/* push new const value */
const_pool_offset = constPool_getLastOffset(&(self->const_pool));
/* load const to const pool buff */
constPool_append(&(self->const_pool), data);
} else {
/* use exist const value */
const_pool_offset = exist_offset;
}
invoke_deepth_int = fast_atoi(invoke_deepth);
/* load Asm to byte code unit */
instructUnit_setBlockDeepth(&ins_unit, asmer.block_deepth_now);
instructUnit_setInvokeDeepth(&ins_unit, invoke_deepth_int);
instructUnit_setConstPoolIndex(&ins_unit, const_pool_offset);
instructUnit_setInstruct(&ins_unit, pikaVM_getInstructFromAsm(ins_str));
if (asmer.is_new_line) {
instructUnit_setIsNewLine(&ins_unit, 1);
asmer.is_new_line = 0;
}
/* append instructUnit to instructArray */
instructArray_append(&(self->instruct_array), &ins_unit);
next_line:
/* point to next line */
asmer.line_pointer += strGetLineSize(asmer.line_pointer) + 1;
arg_deinit(line_buff);
}
return self;
}
char* Parser_byteCodeToAsm(Args* outBuffs, char* pikaByteCode) {
return NULL;
}
void Parser_compilePyToBytecodeArray(char* lines) {
ByteCodeFrame bytecode_frame;
byteCodeFrame_init(&bytecode_frame);
bytecodeFrame_fromMultiLine(&bytecode_frame, lines);
/* do something */
byteCodeFrame_print(&bytecode_frame);
__platform_printf("\n\n/* clang-format off */\n");
__platform_printf("PIKA_PYTHON(\n");
__platform_printf("%s\n", lines);
__platform_printf(")\n");
__platform_printf("/* clang-format on */\n");
byteCodeFrame_printAsArray(&bytecode_frame);
/* deinit */
byteCodeFrame_deinit(&bytecode_frame);
__platform_printf("\n\n");
}