一个编译器的实现1——开篇

一直就想弄懂编译原理,弄明白编译器是怎么工作的。

学了编译原理的课,只理解到了语法分析,后面的理解就无法再在想象中完成了。

于是想做一个编译器。虽然书上把编译原理讲的那么深奥难懂,但是说穿了,编译器也只不过是几个算法而已。书也有,编程也学了,算法现成的,写个编译器,有什么难的呢。就这么愉快的决定了~

目标确定为:写个C语言的编译器,包括词法分析、语法分析、语义分析、中间代码生成,代码优化。如果心情好,就写写生成最终可执行程序那部分。这是主要目标,另外我希望这个编译器工程的代码具有可扩展性,就是得能够比较方便的修改为各种语言的编译器。

首先要确定数据结构。

源代码,用字符串就可以了。

源代码经过词法分析器(LexicalAnalyzer),得到单词流。“流”这个概念太玄幻,其实就是单词的列表(TokenList),一个数组或者链表而已。

单词列表经过语法分析器(SyntaxParser)的分析,得到语法树(SyntaxTree),语法树是用树状的数据结构表示程序的方式。

语法树再经过语义分析,就得到了信息更加丰富的语法树,之后就可以据此生成中间代码或其它想要的东西了。

中间代码生成可执行程序的部分,我先不考虑写,因为不是很感兴趣,都是一些零零散散的东西,形式化程度不强。

那么基本的数据结构就有了:词法分析器;单词列表;语法分析器;语法树。

为了更具可扩展性和灵活性,我设计了如下的接口和类来实现上述数据结构。

词法分析器接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmileWei.Compiler.MiddleData
{
/// <summary>
/// 词法分析器接口
/// <para>编写自己的词法分析器并实现此接口,可立即使用本系列产品的其他功能,如实时词法分析器</para>
/// </summary>
/// <typeparam name="TEnumTokenType">单词的枚举类型</typeparam>
public interface ILexicalAnalyzer<TEnumTokenType>
where TEnumTokenType : struct, IComparable, IFormattable, IConvertible
{
/// <summary>
/// 要分析的源代码
/// </summary>
string SourceCode { get; set; }
/// <summary>
/// 分析源代码获得Token序列
/// <para>分析之前会重置词法分析器到初始状态</para>
/// </summary>
/// <returns></returns>
TokenList<TEnumTokenType> Analyze();
/// <summary>
/// 分析源代码获得Token序列
/// <para>当得到maxTokenCount数目的Token时(或源代码分析完毕时)返回</para>
/// </summary>
/// <param name="maxTokenCount">应分析得到的Token数目最大值</param>
/// <returns></returns>
TokenList<TEnumTokenType> Analyze(int maxTokenCount);
/// <summary>
/// 重置此词法分析器,这样就可以开始分析新的源代码
/// <para>重置的目的是保证Token的行、列数正确</para>
/// </summary>
void Reset();
}
}
单词列表
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Linq;

namespace SmileWei.Compiler.MiddleData
{
/// <summary>
/// Description of TokenList.
/// </summary>
/// <typeparam name="TEnumTokenType">单词的枚举类型</typeparam>
public class TokenList<TEnumTokenType> : List<Token<TEnumTokenType>>
where TEnumTokenType : struct, IComparable, IFormattable, IConvertible
{
}
}
单词
using System;
using System.Xml.Linq;

namespace SmileWei.Compiler.MiddleData
{
/// <summary>
/// 单词,即词法分析器输出列表的元素
/// </summary>
/// <typeparam name="TEnumTokenType">单词的枚举类型</typeparam>
public class Token<TEnumTokenType>
where TEnumTokenType : struct, IComparable, IFormattable, IConvertible
{
/// <summary>
/// 单词类型
/// </summary>
public TEnumTokenType TokenType { get; set; }
/// <summary>
/// 具体信息
/// </summary>
public string Detail { get; set; }
/// <summary>
/// 备注说明,一般在LexicalError为true的时候不为空
/// </summary>
public string Tag { get; set; }
/// <summary>
/// 标识是否是正确的单词
/// </summary>
public bool LexicalError { get; set; }
/// <summary>
/// 所在行(从0开始)
/// </summary>
public int Line { get; set; }
/// <summary>
/// 所在列(从0开始)
/// </summary>
public int Column { get; set; }
/// <summary>
/// 第一个字符在源代码字符串中的索引
/// </summary>
public int IndexOfSourceCode { get; set; }
/// <summary>
/// 单词长度(字符个数)
/// </summary>
public int Length { get; set; }
/// <summary>
/// 创建一个单词
/// </summary>
public Token()
{
TokenType = default(TEnumTokenType);
Detail = string.Empty;
LexicalError = false;
Tag = string.Empty;
}
/// <summary>
/// 显示[具体信息]$[单词类型]$[行数]$[列数]$[是否是正确的单词]$[备注说明]
/// </summary>
/// <returns></returns>
public override string ToString()
{
return string.Format("[{0}]$[{1}]$[{2},{3}]$[{4}]$[{5}]"
, Detail.ToString().Replace("\r\n", "$").Replace('\r', '$').Replace('\n', '$')
, TokenType, Line, Column, LexicalError
, Tag.Replace("\r\n", "$").Replace('\r', '$').Replace('\n', '$'));
}


/// <summary>
/// 检验两个单词是否一样
/// </summary>
/// <param name="tk"></param>
/// <returns></returns>
public bool SameWith(Token<TEnumTokenType> tk)
{
if (tk == null) return false;
if (this.Column != tk.Column) return false;
if (this.Detail != tk.Detail) return false;
if (this.IndexOfSourceCode != tk.IndexOfSourceCode) return false;
if (this.Length != tk.Length) return false;
if (this.LexicalError != tk.LexicalError) return false;
if (this.Line != tk.Line) return false;
if (this.Tag != tk.Tag) return false;
if (this.TokenType.CompareTo(tk.TokenType) != 0) return false;
return true;
}

}
}
语法分析器接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmileWei.Compiler.MiddleData
{
/// <summary>
/// 语法分析器接口
/// <para>编写自己的语法分析器并实现此接口,可立即使用本系列产品的其他功能,如直接处理词法分析器的输出</para>
/// </summary>
/// <typeparam name="TEnumTokenType">单词的枚举类型</typeparam>
/// <typeparam name="TEnumVType">语法分析中的结点类型(某Vn or 某Vt),建议使用枚举类型</typeparam>
public interface ISyntaxParser<TEnumTokenType, TEnumVType, TTreeNodeValue>
where TEnumTokenType : struct, IComparable, IFormattable, IConvertible
where TEnumVType : struct, IComparable, IFormattable, IConvertible
where TTreeNodeValue : class, new()
{
/// <summary>
/// 要分析的单词列表
/// </summary>
TokenList<TEnumTokenType> TokenListSource { get; set; }
/// <summary>
/// 分析TokenListSource获得语法树
/// <para>分析之前会重置词法分析器到初始状态</para>
/// </summary>
/// <returns></returns>
SyntaxTree<TEnumTokenType, TEnumVType, TTreeNodeValue> Parse();
/// <summary>
/// 重置此语法分析器,这样就可以重新分析
/// <para>重置的目的是保证语法分析器内部TokenListSource的索引指针回到第一个Token的位置</para>
/// </summary>
void Reset();
/// <summary>
/// 获取源代码的规范格式
/// </summary>
/// <returns></returns>
string GetFormattedSourceCode();
/// <summary>
/// 获取源代码的规范格式
/// </summary>
/// <returns></returns>
string GetFormattedSourceCode(SyntaxTree<TEnumTokenType, TEnumVType, TTreeNodeValue> tree);
}
}
语法树
using System;
using System.Collections.Generic;

namespace SmileWei.Compiler.MiddleData
{
/// <summary>
/// Description of SyntaxTreeGeneric.
/// </summary>
/// <typeparam name="TEnumTokenType">单词的枚举类型</typeparam>
/// <typeparam name="TEnumVType">语法分析中的结点类型(某Vn or 某Vt),建议使用枚举类型</typeparam>
/// <typeparam name="TTreeNodeValue">语法树结点值,根据语音特性自定义类型进行填充</typeparam>
public class SyntaxTree<TEnumTokenType, TEnumVType, TTreeNodeValue>
where TEnumTokenType : struct, IComparable, IFormattable, IConvertible
where TEnumVType : struct, IComparable, IFormattable, IConvertible
where TTreeNodeValue : class, new()
{

#region 字段和属性
/// <summary>
/// 产生此语法树所直接调用的候选式
/// </summary>
protected Func<SyntaxTree<TEnumTokenType, TEnumVType, TTreeNodeValue>, SyntaxTree<TEnumTokenType, TEnumVType, TTreeNodeValue>> m_CandidateFunc;
/// <summary>
/// 产生此语法树所直接调用的候选式
/// </summary>
public Func<SyntaxTree<TEnumTokenType, TEnumVType, TTreeNodeValue>, SyntaxTree<TEnumTokenType, TEnumVType, TTreeNodeValue>> CandidateFunc
{
get { return m_CandidateFunc; }
set { m_CandidateFunc = value; }
}
private int m_MappedTokenStartIndex = 0;
/// <summary>
/// 对应的第一个单词
/// </summary>
public int MappedTokenStartIndex
{
get { return m_MappedTokenStartIndex; }
set { m_MappedTokenStartIndex = value; }
}
private int m_MappedTokenLength = 0;
/// <summary>
/// 对应的单词数目
/// </summary>
public int MappedTokenLength
{
get { return m_MappedTokenLength; }
set { m_MappedTokenLength = value; }
}

/// <summary>
/// 对应的单词列表
/// </summary>
public TokenList<TEnumTokenType> GetMappedTokenList()
{
var result = new TokenList<TEnumTokenType>();
if (MappedTotalTokenList != null && MappedTotalTokenList.Count > 0)
{
if (MappedTokenLength > 0)
{
for (int i = 0, j = MappedTokenStartIndex; i < MappedTokenLength; i++, j++)
{
result.Add(MappedTotalTokenList[j]);
}
}
}
return result;
}
private TokenList<TEnumTokenType> m_MappedTotalTokenList = new TokenList<TEnumTokenType>();
/// <summary>
/// 整个语法树对应的单词列表
/// </summary>
public TokenList<TEnumTokenType> MappedTotalTokenList
{
get { return m_MappedTotalTokenList; }
set { m_MappedTotalTokenList = value; }
}
private string m_Tag = string.Empty;
/// <summary>
/// 标记,若发生语法错误,应在此说明
/// </summary>
public string Tag
{
get { return m_Tag; }
set { m_Tag = value; }
}
private bool m_SyntaxError = false;
/// <summary>
/// 是否有语法错误
/// </summary>
public bool SyntaxError
{
get { return m_SyntaxError; }
set { m_SyntaxError = value; }
}
/// <summary>
/// 此结点的值
/// </summary>
private TTreeNodeValue m_NodeValue = new TTreeNodeValue();
/// <summary>
/// 此结点的值
/// </summary>
public TTreeNodeValue NodeValue
{
get { return m_NodeValue; }
set { m_NodeValue = value; }
}
private SyntaxTreeList<TEnumTokenType, TEnumVType, TTreeNodeValue> m_Children = new SyntaxTreeList<TEnumTokenType, TEnumVType, TTreeNodeValue>();
/// <summary>
/// 子结点
/// </summary>
public SyntaxTreeList<TEnumTokenType, TEnumVType, TTreeNodeValue> Children
{
get { return m_Children; }
set { m_Children = value; }
}
private SyntaxTree<TEnumTokenType, TEnumVType, TTreeNodeValue> m_Parent = null;
/// <summary>
/// 父结点
/// </summary>
public SyntaxTree<TEnumTokenType, TEnumVType, TTreeNodeValue> Parent
{
get { return m_Parent; }
set { m_Parent = value; }
}
#endregion 字段和属性

}
}






 

 

 

华中科技大学 编译原理 面向过程的C语言编译器设计 功能包括词法分析和语法分析、语义分析、中间代码生成的 源码 题目:c--语言编译器设计与实现(请为自己的编译器命名) 源语言定义:或采用教材中Decaf语言,或采用C语言(或C++语言或C#语言或JAVA语言)部分关键语法规则。源语言要求至少包含的语言成分如下: 数据类型至少包括char类型、int类型和float类型 基本运算至少包括算术运算、比较运算、自增自减运算和复合赋值运算 控制语句至少包括if语句和while语句 实验内容:完整可运行的自定义语言编译器 实验一:词法语法分析器的设计与实现:建议使用词法语法生成工具如:LEX/FLEX ,YACC/BISON等专业工具完成。 实验二:符号表的设计与属性计算:设计符号表数据结构和关键管理功能。动态展现符号表变化过程。无论语法分析使用工具还是自己设计,都必须对符号表进行设计和管理,属性计算可以语义子程序实现。 实验三:语义分析和中间代码生成:生成抽象语法树,进行语义分析,实现类型检查和控制语句目标地址计算,生成中间代码。中间代码的形式可以采用不同形式,但实验中要求定义自己的中间形式。 实验四:目标代码生成:在前三个实验的基础上实现目标代码生成。也可以使用工具如LLVM来生成目标代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值