📄 lexer.h
字号:
/// <author> 任晶磊 </author>
/// <update> 2008-3-1 </update>
/// <E-mail> renjinglei@163.com </E-mail>
#ifndef LEXER_H
#define LEXER_H
#include <list>
#include <string>
#include <map>
#include <sstream>
#include "C0Types.h"
#include "File.h"
#include "Error.h"
namespace C0
{
namespace Lexer
{
using namespace std;
using FileAdapter::File;
using Interpreter::ErrorLog;
/// <summary>
/// 单词与语义编码的映射
/// </summary>
class SemanMapper
{
static map<string, SemanCode> semans;
/// <summary>
/// 初始化单词与语义编码的映射,当且仅当第一次查询时调用
/// <summary>
static void Initialize()
{
semans.insert(make_pair("{", LBRACE));
semans.insert(make_pair("+", PLUS));
semans.insert(make_pair("*", MULT));
semans.insert(make_pair("=", ASS));
semans.insert(make_pair("read", READ));
semans.insert(make_pair("write", WRITE));
semans.insert(make_pair("}", RBRACE));
semans.insert(make_pair(";", SEMI));
semans.insert(make_pair("(", OPEN));
semans.insert(make_pair(")", CLOSE));
semans.insert(make_pair("EOF", END));
}
public:
static SemanCode GetSeman(const string& word)
{
if (semans.empty()) Initialize();
return semans[word];
}
};
/// <summary>
/// 单词与记号类型的映射
/// </summary>
class TypeMapper
{
static map<string, TokenType> types;
/// <summary>
/// 初始化单词与记号类型的映射,当且仅当第一次查询时调用
/// <summary>
static void Initialize()
{
types.insert(make_pair("{", FORMAT));
types.insert(make_pair("+", OPERATOR));
types.insert(make_pair("*", OPERATOR));
types.insert(make_pair("=", OPERATOR));
types.insert(make_pair("read", KEYWORD));
types.insert(make_pair("write", KEYWORD));
types.insert(make_pair("}", FORMAT));
types.insert(make_pair(";", FORMAT));
types.insert(make_pair("(", FORMAT));
types.insert(make_pair(")", FORMAT));
types.insert(make_pair("EOF", FORMAT));
}
public:
static TokenType GetType(const string &word)
{
if (types.empty()) Initialize();
return types[word];
}
};
/// <summary>
/// 标识符与语义编码映射
/// </summary>
class IDTable
{
static map<string, SemanCode> idSeman;
public:
static SemanCode GetSeman(const string &id)
{
SemanCode sc = idSeman[id];
if (!sc) sc = idSeman[id] = SemanCode(idSeman.size());
return sc;
}
};
/// <summary>
/// 语义记号抽象类
/// </summary>
class Token
{
protected:
int lineNum;
int charNum;
string word;
SemanCode seman;
Token(const string& word, int lineNum, int charNum)
{
this->word = word;
this->lineNum = lineNum;
this->charNum = charNum;
}
public:
int GetLineNum()
{
return lineNum;
}
int GetCharNum()
{
return charNum;
}
string& GetWord()
{
return word;
}
SemanCode GetSeman()
{
return seman;
}
virtual TokenType GetType() = 0;
};
//各实现类型
//保留字
class Keyword : public Token
{
public:
Keyword(const string& word, int lineNum, int charNum)
:Token(word, lineNum, charNum)
{
seman = SemanMapper::GetSeman(word);
}
TokenType GetType()
{
return KEYWORD;
}
};
//标识符
class Identifier : public Token
{
public:
Identifier(const string& word, int lineNum, int charNum)
:Token(word, lineNum, charNum)
{
seman = IDTable::GetSeman(word);
}
TokenType GetType()
{
return IDENTIFIER;
}
};
//常数
class Constant : public Token
{
public:
Constant(const string& word, int lineNum, int charNum)
:Token(word, lineNum, charNum)
{
int tempSeman;
std::stringstream sstr;
sstr << word;
sstr >> tempSeman;
seman = SemanCode(tempSeman);
}
TokenType GetType()
{
return CONSTANT;
}
};
//运算符
class Operator : public Token
{
public:
Operator(const string& word, int lineNum, int charNum)
:Token(word, lineNum, charNum)
{
seman = SemanMapper::GetSeman(word);
}
TokenType GetType()
{
return OPERATOR;
}
};
//格式符
class Format : public Token
{
public:
Format(const string& word, int lineNum, int charNum)
:Token(word, lineNum, charNum)
{
seman = SemanMapper::GetSeman(word);
}
TokenType GetType()
{
return FORMAT;
}
};
/// <summary>
/// 语义记号链表
/// </summary>
class TokenList
{
typedef list<Token *> LIST;
LIST ptokens;
/// <summary>
/// 指向在堆中开辟的计数变量,记录指向相同Token对象集的TokenList
/// </summary>
int* pcount;
string fileName;
void destroy()
{
for (LIST::iterator it = ptokens.begin(); it != ptokens.end(); ++it)
{
delete *it;
}
delete pcount;
}
public:
TokenList():pcount(new int(1)){}
void SetFileName(const string& fileName)
{
this->fileName = fileName;
}
TokenList(const string& fileName):pcount(new int(1)), fileName(fileName){}
TokenList(const TokenList& t):ptokens(t.ptokens), pcount(t.pcount),fileName(t.fileName)
{
++(*pcount);
}
string GetFileName()
{
return fileName;
}
TokenList& operator =(const TokenList &t)
{
if (pcount == t.pcount) return *this;
if (--(*pcount) == 0) destroy();
ptokens = t.ptokens;
pcount = t.pcount;
fileName = t.fileName;
++(*pcount);
return *this;
}
~TokenList()
{
if (--(*pcount) == 0) destroy();
}
/// <summary>
/// 用于元素遍历的迭代器
/// </summary>
class Iterator
{
public:
Iterator(){}
Iterator(LIST::iterator i):it(i){}
Iterator& operator ++()
{
++it;
return *this;
}
Iterator& operator --()
{
--it;
return *this;
}
bool operator ==(Iterator right)
{
return this->it == right.it;
}
bool operator !=(Iterator right)
{
return this->it != right.it;
}
Token* operator ->()
{
return *it;
}
private:
LIST::iterator it;
};
void PushBack(const string &word, int lineNum, int charNum)
{
//追加记号为常数
if ('0' <= word[0] && word[0] <= '9')
{
ptokens.push_back(new Constant(word, lineNum, charNum));
return;
}
//追加记号不是常数
Token *token;
switch(TypeMapper::GetType(word))
{
case IDENTIFIER:
token = new Identifier(word, lineNum, charNum);
break;
case KEYWORD:
token = new Keyword(word, lineNum, charNum);
break;
case OPERATOR:
token = new Operator(word, lineNum, charNum);
break;
case FORMAT:
token = new Format(word, lineNum, charNum);
break;
case CONSTANT:
token = new Constant(word, lineNum, charNum);
}
ptokens.push_back(token);
}
Iterator Begin()
{
return Iterator( ptokens.begin() );
}
Iterator End()
{
return Iterator( --ptokens.end() );
}
};
/// <summary>
/// 词法分析器
/// </summary>
class Lexer
{
File inFile;
TokenList tokens;
ErrorLog* errors;
public:
Lexer(){}
void Open(const string& file)
{
inFile.Open(file);
tokens.SetFileName(file);
}
Lexer(const string& fileName)
{
Open(fileName);
}
void SetErrorLog(ErrorLog* el)
{
errors = el;
}
void PrintSourceFile();
/// <summary>
/// 对源程序文件执行解析
/// </summary>
/// <returns>返回对记号链表的常引用</returns>
const TokenList& Execute();
~Lexer()
{
inFile.Close();
}
private:
/// <summary>
/// 获得字母的小写形式
/// </summary>
/// <returns>返回转化是否成功;如果参数不是字母,返回false</returns>
bool Lexer::ToLowercase(char &letter);
string Lexer::GetNum(File& inFile);
string Lexer::GetIdentifier(File& inFile);
};
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -