写一个简单的解释器(2) 构建标记流

确定标记类型

分为几个大类:

  1. 用户符号(类型/标识符/数字/字符串…)
  2. 关键字 (流程控制和定义符)
  3. 括号 (这里暂时认为 [] 属于括号)
  4. 分号

上述四类标记基本囊括了 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,r1] 作为一个标记,生成对应的信息。

代码参考

以下内容为读者可以参考的功能实现指南。

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 中实现三个函数,这里就不贴出代码了。

感兴趣的,可以点击这个链接参考代码。

你可能感兴趣的:(解释器的实现,算法,c语言,开发语言)