分为几个大类:
[]
属于括号)上述四类标记基本囊括了 vc \texttt{vc} vc 中的所有最小单元的类型,但是因为构建标记流的程序还需要完成 vasm \texttt{vasm} vasm 文件的标记流构建,因此增加第五类:汇编符号
据此,我们可以使用 enum class
记录下标记的类型,用结构体记录每一个标记的信息,用 vector
存储整个标记流,同时声明一个用于构建标记流的函数,有时候文件可能比较大,所以允许用户逐行生成标记流并整合起来。
对于一个源文件 S S S,使用两个整数变量 l , r l, r l,r ,每次让 r r r 向后移动,直到找到了一个标记的开头,或者说两个标记的分割处,然后将 S [ l , r − 1 ] S[l,r-1] S[l,r−1] 作为一个标记,生成对应的信息。
以下内容为读者可以参考的功能实现指南。
pretreat.h \texttt{pretreat.h} pretreat.h
//gloconst.h 声明了一些常用的函数
#include "gloconst.h"
namespace Interpreter {
enum class TokenType {
Empty,
Identifier = 1, ExpressionEnd,
Integer, Float, String, Char,
SBracketL, SBracketR, MBracketL, MBracketR, LBracketL, LBracketR,
//关键字
VarDefine, FuncDefine, ClassDefine, NamespaceDefine,
If, Else, Switch, Case, While, For, Continue, Break, Return,
Private, Public, Protected, Super, Using,
//运算符(除去[])
Comma, Assign,
Add, Minus, Mul, Divison, Mod, BitAnd, BitOr, BitXor, BitNot, Lmov, Rmov,
Equ, Neq, Gt, Ge, Ls, Le,
LogicAnd, LogicOr, LogicNot,
CallMember, New, As, Region, ArrIndex,
//下列内容为汇编符号,label 之前的是预处理指令集
Expose, Extern, VasmRegion, Glomem, StringRegion, Rely,
label = 1024,
vbmov, vi32mov, vi64mov, vfmov, vomov, mbmov, mi32mov, mi64mov, mfmov, momov,
add, sub, mul, _div, mod, ladd, lsub, lmul, _ldiv, lmod, fadd, fsub, fmul, fdiv, uadd, usub, umul, udiv, umod, badd, bsub, bmul, bdiv, bmod,
eq, ne, gt, ge, ls, le, feq, fne, fgt, fge, fls, fle,
_and, _or, _xor, _not, lmv, rmv, land, lor, lxor, lnot, llmv, lrmv, uand, uor, uxor, unot, ulmv, urmv, band, bor, bxor, bnot, blmv, brmv,
ret, opop, pop,
vbgvl, vi32gvl, vi64gvl, vfgvl, vogvl, mbgvl, mi32gvl, mi64gvl, mfgvl, mogvl,
push0, push1,
pvar0, pvar1, pvar2, pvar3, povar0, povar1, povar2, povar3,
arrmem1, arromem1,
pack, unpack,
_new, jmp, jz, jp,
setvar,
poparg,
push,
pvar, povar, pglo, poglo, pstr,
mem, omem,
sys,
arrnew, arrmem, arromem,
call, ecall
};
//一些常用的范围
constexpr TokenType OperTokenTypeStart = TokenType::Comma, OperTokenTypeEnd = TokenType::ArrIndex,
KeywordTokenTypeStart = TokenType::VarDefine, KeywordTokenTypeEnd = TokenType::Using;
struct Token {
//类型
TokenType Type;
//内容
ulong Ulong;
double Float;
string String;
char Char;
//该标记所处的行编号
int Line;
Token();
};
//用于调试
void PrintToken(Token& Token);
//进行一些准备和初始化,读取一个源文件之前都要运行一次
void Pretreat_Init();
//在标记流末尾添加内容,不会清空已有的内容
int Pretreat_GetTokenList(vector<Token>& list, string& str, bool is_asm_style);
}
接下来在 pretreat.cpp \texttt{pretreat.cpp} pretreat.cpp 中实现三个函数,这里就不贴出代码了。
感兴趣的,可以点击这个链接参考代码。