`
daojin
  • 浏览: 690202 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

自己动手写C语言编译器(2)

 
阅读更多

 


直接上代码 :

支持:左右结合性

// MyCompiler.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <fstream>
#include <list>
#include <map>
#include <string>
#include <iostream>
#include <vector>
//把Token转换为字符串
#define  ATokenToString(l, r) if(l == r)return #r;
using namespace std;
namespace tokens{
	enum TOKEN
	{
		INVALID_TYPE,
			WHITE_SPACE,
			NAME,
			NUMBER,
			END,
			PLUS,
			MINUS,
			MUL,
			DIV,
			PRINT,
			ASSIGN,
			LP,
			RP,
	};
	static string MyTokenToString(TOKEN token)
	{
		ATokenToString(token, WHITE_SPACE)
			ATokenToString(token, NAME)
			ATokenToString(token, NUMBER)
			ATokenToString(token, END)
			ATokenToString(token, PLUS)
			ATokenToString(token, MINUS)
			ATokenToString(token, MUL)
			ATokenToString(token, DIV)
			ATokenToString(token, PRINT)
			ATokenToString(token, ASSIGN)
			ATokenToString(token, LP)
			ATokenToString(token, RP)
			return "";
	}
}

class tokenizer
{
	int mTokenTypes[256];
	string mCurrentStrToken;
	tokens::TOKEN mCurrentTokenType;
	istream& mIfStream;
public:
	tokenizer(istream& infile):mIfStream(infile)
	{
		memset(mTokenTypes, 0, 256);
		mTokenTypes['+'] = tokens::PLUS;
		mTokenTypes['-'] = tokens::MINUS;
		mTokenTypes['*'] = tokens::MUL;
		mTokenTypes['/'] = tokens::DIV;
		mTokenTypes[';'] = tokens::PRINT;
		mTokenTypes['='] = tokens::ASSIGN;
		mTokenTypes['('] = tokens::LP;
		mTokenTypes[')'] = tokens::RP;
		mTokenTypes['\t'] = tokens::WHITE_SPACE;
		mTokenTypes[' '] = tokens::WHITE_SPACE;
		char ch = 0;
		for (ch = 'a'; ch <= 'z'; ch ++)
		{
			mTokenTypes[ch] = tokens::NAME; 
		}
		for(ch = 'A'; ch <= 'Z'; ch ++)
		{
			mTokenTypes[ch] = tokens::NAME; 
		}
		for(ch = '0'; ch <= '9'; ch ++)
		{
			mTokenTypes[ch] = tokens::NUMBER; 
		}
		mTokenTypes['.'] = tokens::NUMBER;
		
	}
	bool hasNext()
	{
		char temptoken = 0;
		if(mIfStream.get(temptoken))
		{
			mIfStream.putback(temptoken);
			return true;
		}
		return false;
	}
	const string getCurrent()
	{
		return mCurrentStrToken;
	}
	tokens::TOKEN getTokenType()
	{
		return mCurrentTokenType;
	}
	const string getNext()
	{
		string strValue;
		char ch = 0;
		mIfStream>>ch;
		mCurrentTokenType = (tokens::TOKEN)mTokenTypes[ch];
		mIfStream.putback(ch);
		mIfStream>>strValue;
		mCurrentStrToken = strValue;
		return strValue;
	}
};
class Node;
struct NodeVisitor
{
	virtual void BeginVisitTree(Node* nod) = 0;
	virtual void VisitNode(Node* nod) = 0;
	virtual void EndVisitTree(Node* nod) = 0;
};

class Node
{
	char m_Data;

	NodeVisitor* m_pGetNode;
public:
	Node* m_pLeftChild;
	Node* m_pRightChild;
	Node* m_pParent;
	int m_priority_level;
public:
	char getData()
	{
		return m_Data;
	}
	
	Node()
	{
		m_Data = 0;
		m_pLeftChild = NULL;
		m_pRightChild = NULL;
		m_pParent = NULL;
		//空的Node,优先级最低
		m_priority_level = 0;
	}
	
	Node(char data)
	{
		m_Data = data;
		m_pLeftChild = NULL;
		m_pRightChild = NULL;
		m_pParent = NULL;
		m_priority_level = 0;
	}
	
	void set(Node* pL, Node* pR)
	{
		m_pLeftChild = pL;
		m_pRightChild = pR;
	}
	
	void setLeft(Node* pLeft)
	{
		m_pLeftChild = pLeft;
	}
	
	void setRight(Node* pRight)
	{
		m_pRightChild = pRight;
	}
	
	void accept(NodeVisitor* pGetIt)
	{
		m_pGetNode = pGetIt;
	}
	
	void Postorder_Traversal(NodeVisitor* pVisiter)
	{
		if(m_pLeftChild != NULL)
			m_pLeftChild->Postorder_Traversal(pVisiter);
		if (m_pRightChild != NULL)
			m_pRightChild->Postorder_Traversal(pVisiter);
		pVisiter->VisitNode(this);
	}
	
	void Inorder_Traversal(NodeVisitor* pVisiter)
	{
		//Begin Tree.
		pVisiter->BeginVisitTree(this);
		
		if(m_pLeftChild != NULL)m_pLeftChild->Inorder_Traversal(pVisiter);
		
		//Visit this node. 
		//Node should not be diffrent from tree.
		pVisiter->VisitNode(this);
		
		if (m_pRightChild != NULL)m_pRightChild->Inorder_Traversal(pVisiter);
		
		//End Tree.
		pVisiter->EndVisitTree(this);
	}
	

};

class ExpressionVisiter: public NodeVisitor
{
public:
	void BeginVisitTree(Node* nod)
	{
		if (nod->m_pLeftChild != NULL && nod->m_pRightChild != NULL)
		{
			printf("%c", '(');
		}
	}
	void VisitNode(Node* nod)
	{
		printf("%c", nod->getData());
	}
	void EndVisitTree(Node* nod)
	{
		if (nod->m_pLeftChild != NULL && nod->m_pRightChild != NULL)
		{
			printf("%c", ')');
		}
	}
};


class Tree
{
public:
	Tree()
	{
		pHead = new Node();
	}
	Node* pHead;
	~Tree()
	{
		
	}
	Node* getNext()
	{
		
	}
	void Postorder_Traversal(NodeVisitor* pVisiter)
	{
		if(pHead->m_pLeftChild!=NULL)
			pHead->m_pLeftChild->Postorder_Traversal(pVisiter);
	}
	void Inorder_Traversal(NodeVisitor* pVisiter)
	{
		if(pHead->m_pLeftChild!=NULL)
			pHead->m_pLeftChild->Inorder_Traversal(pVisiter);
	}
	Node* getCurrent()
	{
	}
	
	Node* getFirst()
	{
		
	}
	
	bool bHasNext()
	{
	}
	void setValue(Node* pNode)
	{
		pHead->m_pLeftChild = pNode;
	}
};


//打印一个字符串的所有排列。
void printSequence(char* pChara)
{	
	int i = 0;
	static int MAX_LEN = strlen(pChara);
	if (pChara[0] == '\0')
	{
		for (int i = 0; i < MAX_LEN; i ++)
		{
			printf("%c", pChara[i + 1]);
		}
		printf("\n", "");  
	}
	
	char* tempChar = pChara;
	while (*tempChar != '\0' )
	{
		char* pMyString = new char[MAX_LEN + 1];
		memcpy(pMyString, pChara, MAX_LEN + 1);
		memcpy(pMyString + i, pMyString + i + 1, MAX_LEN - i);
		pMyString[MAX_LEN] = *tempChar;
		printSequence(pMyString);
		tempChar ++;
		i ++;
		delete[] pMyString;
	}
}

#ifdef TEST
int main(int argc, char* argv[])
{
	
	ExpressionVisiter visister;
	Tree* pTree = new Tree();
	Node* pNode1 = new Node('-');
	
	
	Node* pNode11 = new Node('+');
	Node* pNode12 = new Node('/');
	
	Node* pNode111 = new Node('a');
	Node* pNode112 = new Node('*');
	Node* pNode121 = new Node('e');
	Node* pNode122 = new Node('f');
	
	
	Node* pNode1121 = new Node('b');
	Node* pNode1122 = new Node('-');
	
	Node* pNode11221 = new Node('c');
	Node* pNode11222 = new Node('d');
	
	
	pNode1->set(pNode11, pNode12);
	pNode11->set(pNode111, pNode112);
	pNode12->set(pNode121, pNode122);
	pNode112->set(pNode1121, pNode1122);
	pNode1122->set(pNode11221, pNode11222);
	pTree->setValue(pNode1);
	pTree->Inorder_Traversal(&visister);
	
	//printSequence("a");
	system("PAUSE");
	return 1;
}
#else

//字符的类型
class SH_CHARACTER_TYPE
{
public:
	enum CHARACTER_TYPE
	{
		ILLIGAL_CHAR = 0x00000000,
		DIGITAL_CHAR = 0x00000001,
		NON_DIGITAL_CHAR = 0x00000002,
		UNIVERSAL_CHAR = 0x00000004,
		INTEGER_CONSTANT_CHAR = 0x00000008,
		FLOATING_CONSTANT_CHAR = 0x00000010,
		ENUMERATION_CONSTANT_CHAR = 0x00000020,
		CHARACTER_CONSTANT_CHAR = 0x00000040,
		STRING_LITERAL_CHAR =  0x00000080,
		PUNCTUATOR_CHAR = 0x00000100,
		EOL_CHAR = 0x00000200,
		EOF_CHAR = 0x00000400,
		WHITESPACE_CHAR = 0x00000800,
		OPERATOR_CHAR = 0x00001000,
	};
};


class sh_ctype
{
private:
	int ctypeTable[256];
public:
	void clear()
	{
		//清除
		for (int i = 0; i < 256;  ++ i)
		{
			ctypeTable[i] = SH_CHARACTER_TYPE::ILLIGAL_CHAR;
		}
	}
	sh_ctype()
	{
		clear();
		
		setCtype('a', 'z', SH_CHARACTER_TYPE::NON_DIGITAL_CHAR);
		setCtype('A', 'Z', SH_CHARACTER_TYPE::NON_DIGITAL_CHAR);

		setCtype('0', '9', SH_CHARACTER_TYPE::DIGITAL_CHAR);
		
		setCtype('0', '9', SH_CHARACTER_TYPE::INTEGER_CONSTANT_CHAR);
		setCtype('x', SH_CHARACTER_TYPE::INTEGER_CONSTANT_CHAR);
		setCtype('X', SH_CHARACTER_TYPE::INTEGER_CONSTANT_CHAR);
		setCtype('u', SH_CHARACTER_TYPE::INTEGER_CONSTANT_CHAR);
		setCtype('U', SH_CHARACTER_TYPE::INTEGER_CONSTANT_CHAR);
		setCtype('l', SH_CHARACTER_TYPE::INTEGER_CONSTANT_CHAR);
		setCtype('L', SH_CHARACTER_TYPE::INTEGER_CONSTANT_CHAR);
		
		
		setCtype('0', '9', SH_CHARACTER_TYPE::FLOATING_CONSTANT_CHAR);
		setCtype('e', SH_CHARACTER_TYPE::FLOATING_CONSTANT_CHAR);
		setCtype('E', SH_CHARACTER_TYPE::FLOATING_CONSTANT_CHAR);
		setCtype('l', SH_CHARACTER_TYPE::FLOATING_CONSTANT_CHAR);
		setCtype('L', SH_CHARACTER_TYPE::FLOATING_CONSTANT_CHAR);
		setCtype('f', SH_CHARACTER_TYPE::FLOATING_CONSTANT_CHAR);
		setCtype('F', SH_CHARACTER_TYPE::FLOATING_CONSTANT_CHAR);

		//标点符号字符
		setCtype(0x21,0x2F, SH_CHARACTER_TYPE::PUNCTUATOR_CHAR);
		setCtype(0x3a,0x40, SH_CHARACTER_TYPE::PUNCTUATOR_CHAR);
		setCtype(0x5B,0x60, SH_CHARACTER_TYPE::PUNCTUATOR_CHAR);

		//空白字符
		setCtype(0x20, SH_CHARACTER_TYPE::WHITESPACE_CHAR);
		setCtype(0x09, 0x0D, SH_CHARACTER_TYPE::WHITESPACE_CHAR);

		setCtype('+', SH_CHARACTER_TYPE::OPERATOR_CHAR);
	}
	
	//断定是否是某种类型
	bool assert(char ch, SH_CHARACTER_TYPE::CHARACTER_TYPE type)
	{
		if ((getCtype(ch)&type) == type)
		{
			return true;
		}
		return false;
	}

	void setCtype(char from, char to, SH_CHARACTER_TYPE::CHARACTER_TYPE type)
	{
		for (char ch = from; ch <= to ; ++ ch)
		{
			ctypeTable[ch] = ctypeTable[ch]|type;
		}
	}

	void setCtype(char ch, SH_CHARACTER_TYPE::CHARACTER_TYPE type)
	{
		ctypeTable[ch] = ctypeTable[ch]|type;
	}

	int getCtype(char ch)
	{
		return ctypeTable[ch];
	}
};

bool bIsRightAttach(char  ch)
{
	if (ch == '=')
	{
		return true;
	}
	return false;
}
int getLevel(char ch)
{
	switch(ch)
	{
	case ',':
		return 0;
	case '=':
		return 1;
	case '|': 
	    return 2;
	case '^':
		return 3;

	case '>': case '<':
		return 5;
	case '+' : case '-':
		return 6;
	case '*': case '/':
		return 7;
	case '&':
		return 8;
	case '.':
		return 9;
	default:
		return INT_MAX;

	}
}

static int const INVALID = 0;
static int const EXPRESSION = 0x0001;
static int const LVALUE = 0x0002;
static int const OPERATOR_LEFT = 0x0004;
static int const OPERATOR_RIGHT = 0x0008;

int main(int argc, char* argv[])
{
	sh_ctype ct;
	Node* pHead = NULL;
	Node* preTreeOperator = NULL;
	char ch;
	while (cin.get(ch) && ch != '\n')
	{
		//如果目前没有操作子Tree
		if (preTreeOperator == NULL)
		{
			preTreeOperator = new Node(ch);
			preTreeOperator->m_priority_level = getLevel(ch);
			pHead = preTreeOperator;
			continue;
		}
		else
		{
		   Node* no = new Node(ch);
		   no->m_priority_level = getLevel(ch);
		   Node* theTree = preTreeOperator;

		   //头节点的优先级为INTMAX(说明是标识符,而不是操作符),
		   //并且新节点的优先级也是INTMAX(说明是标识符,而不是操作符),
		   //那么说明两个叶子相邻,因此报错。
		   if(pHead->m_priority_level == no->m_priority_level
			   && pHead->m_priority_level == INT_MAX)
		   {
				std::cout<<"Unkown symbol "<<"\""<<ch<<"\"";
				system("PAUSE");
				return;
		   }

			
		   if (no->m_priority_level < pHead->m_priority_level)
		   {

				 pHead->m_pParent = no;
				 no->m_pLeftChild = pHead;
				 pHead = no;
				 preTreeOperator = no;
				 continue;
		   }
		   else
		   {
			   //优先级相等的情况下
			   if(no->m_priority_level == pHead->m_priority_level)
			   {
					//左结合,先算左边,因此左边优先级比右边优先级高。
				    //no插在pHead之上,pHead作为no的左节点。
					if (!bIsRightAttach(ch))
					{
							
						//设置左节点
						no->m_pLeftChild = pHead;
						//设置父节点
						pHead->m_pParent = no;

						//保存新的pHead 和 preTreeOperator
						pHead = no;
						preTreeOperator = no;
						continue;
					}
					else
					{
						/************************************************************************/
						/*右结合,先算右边。也就是说,右边优先级比左边高。
						/no插在pHead 和 pHead->m_pRightChild之间。
						/pHead->m_pRightChild 从pHead的右边,设置到no的左边。                   */
						/************************************************************************/
						
						
						//设置父节点。
						no->m_pParent = pHead;
						//设置左节点
						no->m_pLeftChild = pHead->m_pRightChild;
						//连接pHead
						pHead->m_pRightChild = no;


						//保存新的preTreeOperator,头节点没有变化
						preTreeOperator = no;
						continue;
					}
			   }
		   }

		   if(theTree->m_priority_level == no->m_priority_level
			   && theTree->m_priority_level == INT_MAX)
		   {
				std::cout<<"Unkown symbol "<<"\""<<ch<<"\"";
				system("PAUSE");
				return;
		   }

		   //找到一个theTree, 它优先级比no小。

		   //在优先级相等的情况下,如果是右结合,那么theTree就相当于优先级比no小。此时,循环应跳出。
		   //否则就相当于theTree优先级比no大,需要继续循环。
		   while (theTree!= NULL&& theTree->m_priority_level >= no->m_priority_level)
		   {
			   if (theTree->m_priority_level == no->m_priority_level)
			   {
				   if (bIsRightAttach(ch))
				   {
					   break;
				   }
				   else
				   {
					  theTree = theTree->m_pParent;
				   }
			   }
			   theTree = theTree->m_pParent;
		   }

		   if (theTree != NULL)
		   {
				no->m_pLeftChild = theTree->m_pRightChild;
				no->m_pParent = theTree;
				theTree->m_pRightChild = no;
				preTreeOperator = no;
		   }
		}
	}
	Tree tree;
	ExpressionVisiter vister;
	tree.setValue(pHead);
	tree.Inorder_Traversal(&vister);
	system("PAUSE");
}
#endif
分享到:
评论

相关推荐

    c语言编译器

    学习和理解这些源代码可以帮助开发者深入理解编译器的工作机制,甚至动手编写自己的编译器或解释器。 编写一个C语言编译器是一项复杂但极富挑战性的任务,涉及到编译原理、数据结构和算法等多个领域的知识。初学者...

    自己动手写编译器、链接器_编译器_

    本书讲述了一个真实编译器的开发过程源语言是以C语言为蓝本进行适当简化定义的一门新语言称之为SC语言(简化的C语言)目标语言是大家熟悉的Intelx86机器语言。在本书中读者将看到从 SC语言定义到SCC编译器开发的完整...

    一款用C语言写的C语言编译器。.zip

    标题中的“一款用C语言写的C语言编译器”指的是使用C语言开发的源代码,用于编译其他C语言程序的工具。C语言编译器是将人类可读的C语言源代码转换为计算机可执行的机器代码的关键软件。这个项目可能是为了教学目的,...

    一整套的c语言编译器的文档和代码资源

    这一资源集合旨在帮助用户深入理解编译器的工作原理,以及如何构建自己的C语言编译器。 【描述】:“一整套的c语言编译器的文档和代码资源”不仅包括了详尽的理论文档,也包含了实际的源代码,这对于学习编译原理...

    cpp-9cc一个很小的C语言编译器是8cc编译器的继承者

    这些知识对于深入理解计算机系统、提高编程技能,甚至自己动手编写编译器都大有裨益。 此外,了解9cc这样的小型编译器也有助于开发者在实际项目中优化性能。例如,对于特定场景下的嵌入式开发或者需要快速编译的...

    C语言写的一个编译器源码

    对于这个C语言编译器,生成的可能是与C语言兼容的目标代码,便于进一步的链接和执行。 这个“伪编译器”可能并未实现完整的编译器功能,例如优化和错误处理。但它的价值在于提供了一个简化的编译过程模型,帮助初学...

    动手写一个C语言编译器

    动手编写一个C语言编译器是一项挑战性的任务,但也是一个深入了解计算机工作原理的绝佳途径。编译器将高级语言转化为机器可执行的指令,涉及语言学、计算机科学和软件工程等多个领域。以下是一些关键的知识点: 1. ...

    一个最简的C语言编译器.zip

    《构建最简C语言编译器的探索与实践》 C语言是一种强大的、广泛应用的编程语言,它的简洁性、灵活性和高效性使得它在软件开发领域占有重要地位。然而,你知道C语言是如何被计算机理解并执行的吗?答案就是通过...

    简单的类C语言编译器的实现-电子商城例子

    在哈工大的编译原理课程设计...总之,"简单的类C语言编译器的实现-电子商城例子" 是一个综合性的实践项目,涵盖了编译原理的多个重要方面,并将其应用于实际问题中,对于提高学生的理论知识和动手能力有着显著的帮助。

    简单C语言编译器(编译原理).pdf

    《简单C语言编译器(编译原理)》是一份关于编译技术的文档,它主要探讨了如何构建一个简单的C语言编译器。编译器是将高级编程语言(如C语言)转换为机器可执行代码的软件,这个过程涉及多个阶段,包括词法分析、语法...

    C语言文本编译器源代码

    通过研究这个C语言编译器的源代码,初学者可以了解到编译器内部的运作机制,并学习如何使用C语言实现这些功能。这不仅有助于提升编程技能,还能加深对计算机系统底层的理解。 此外,项目中的源代码提供了一个很好的...

    自己动手打造C语言IDE源码

    "自己动手打造C语言IDE源码" 这个标题表明这是一个关于创建一个集成开发环境(IDE)的项目,专为C语言设计。IDE是程序员编写、调试和运行程序的软件平台,它通常包含代码编辑器、编译器、调试器等组件。在这个项目中...

    基于Vue.js的简易C语言编译器 [ 编译原理课程设计 ].zip

    这些实践环节有助于提高学生的动手能力和解决问题的能力,使他们更好地将理论知识应用于实际项目中。 综上所述,C语言课程设计具有基础性强、可移植性好、效率高、结构清晰、资源丰富和实践性强等优点。通过C语言的...

    一个简易c语言的编译器源码

    总结来说,这个简易C语言编译器项目为学习编译原理提供了一个实践平台。通过研究它的源代码,开发者可以理解编译器如何将高级语言翻译为机器语言,从而提升编程和软件工程的技能。同时,这个项目也鼓励动手实践,对...

    2023春季学期 北京邮电大学 编译原理与技术课程设计 Pascal-S到C语言编译器.zip

    这些实践环节有助于提高学生的动手能力和解决问题的能力,使他们更好地将理论知识应用于实际项目中。 综上所述,C语言课程设计具有基础性强、可移植性好、效率高、结构清晰、资源丰富和实践性强等优点。通过C语言的...

    C语言简化编译器前端 编译原理 LR1

    同时,提供的"Compiler"文件可能包含了编译器的源代码,通过阅读和研究这些代码,可以深入了解编译器的工作原理,并动手进行调试和改进,这对于提升编程和系统设计能力非常有益。 总的来说,这个项目旨在让开发者...

    编译原理课程设计,实现简易类C语言编译器,包括词法分析、语法分析、语义分析、翻译与简单优化.zip

    这些实践环节有助于提高学生的动手能力和解决问题的能力,使他们更好地将理论知识应用于实际项目中。 综上所述,C语言课程设计具有基础性强、可移植性好、效率高、结构清晰、资源丰富和实践性强等优点。通过C语言的...

    自己动手写CPU.rar

    在本项目中,"自己动手写CPU.rar" 是一个压缩包,其中包含了关于设计和实现CPU的源代码和相关资料。这个项目的核心是利用硬件描述语言Verilog进行CPU的开发,这是一种广泛应用于数字逻辑设计的语言,特别适用于创建...

    编译原理C语言小子集的编译器

    基于C++的C语言小子集编译器实现,包含了词法分析、语法分析、语义分析、中间代码生成等,从中理解编译程序的构造原理,掌握编译程序的构造方法与技术。通过实习,既加深对编译原理基础理论的理解,又提高动手能力,...

    plo编译器 c语言

    对于想要深入学习PLO编译器工作原理或者想要自己动手实现一个简单编译器的人来说,这是一个宝贵的资源。 总的来说,PLO编译器为初学者提供了一个学习编程的友好环境,而其C语言的实现则保证了编译器的效率和兼容性...

Global site tag (gtag.js) - Google Analytics