一个编译器的实现1——开篇
已重写的文章在(编译原理(前端)的算法和实现)(2023年6月24日)
我在准备重写本文的内容,本文不必再看。(2023年3月25日)
一直就想弄懂编译原理,弄明白编译器是怎么工作的。
学了编译原理的课,只理解到了语法分析,后面的理解就无法再在想象中完成了。
于是想做一个编译器。虽然书上把编译原理讲的那么深奥难懂,但是说穿了,编译器也只不过是几个算法而已。书也有,编程也学了,算法现成的,写个编译器,有什么难的呢。就这么愉快的决定了~
目标确定为:写个C语言的编译器,包括词法分析、语法分析、语义分析、中间代码生成,代码优化。如果心情好,就写写生成最终可执行程序那部分。这是主要目标,另外我希望这个编译器工程的代码具有可扩展性,就是得能够比较方便的修改为各种语言的编译器。
首先要确定数据结构。
源代码,用字符串就可以了。
源代码经过词法分析器(LexicalAnalyzer),得到单词流。“流”这个概念太玄幻,其实就是单词的列表(TokenList),一个数组或者链表而已。
单词列表经过语法分析器(SyntaxParser)的分析,得到语法树(SyntaxTree),语法树是用树状的数据结构表示程序的方式。
语法树再经过语义分析,就得到了信息更加丰富的语法树,之后就可以据此生成中间代码或其它想要的东西了。
中间代码生成可执行程序的部分,我先不考虑写,因为不是很感兴趣,都是一些零零散散的东西,形式化程度不强。
那么基本的数据结构就有了:词法分析器;单词列表;语法分析器;语法树。
为了更具可扩展性和灵活性,我设计了如下的接口和类来实现上述数据结构。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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();
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
{
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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;
}
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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);
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 字段和属性
}
}
![]() |
微信扫码,自愿捐赠。天涯同道,共谱新篇。
微信捐赠不显示捐赠者个人信息,如需要,请注明联系方式。 |