视频与PR:https://github.com/terrajobst/minsk/blob/master/docs/episode-02.md

作者是 Immo Landwerth(https://twitter.com/terrajobst),微软 .NET 团队的项目经理。

这一集的主要内容:

1.添加 Binder,充当语义分析作用。

Binder 基于 SyntaxTree,大体上 SyntaxKind.XXX_Expression => Bind_XXX_Expression。

在 SyntaxTree 中,运算符只是个枚举值(即也就只是个符号),而在 Binder 中必须赋予更加具体的语义。

比如:

> SyntaxKind.PlusToken => BoundBinaryOperatorKind.Addition (“+”代表累加)

> SyntaxKind.AmpersandAmpersandToken => BoundBinaryOperatorKind.LogicalAnd(“&&”代表逻辑与)

在 Binder 中,运算符有更加宽泛的含义,如果是二元运算符,必须可以获取其符号的 SyntaxKind、BoundBinaryOperatorKind、LeftType、RightType、ResultType。计算结果的类型代表了该二元表达式的类型。

以 BoundBinaryOperator 作为具体实现:

using System;

using Minsk.CodeAnalysis.Syntax;

namespace Minsk.CodeAnalysis.Binding
{
internal sealed class BoundBinaryOperator
{
private BoundBinaryOperator(SyntaxKind syntaxKind, BoundBinaryOperatorKind kind, Type type)
: this(syntaxKind, kind, type, type, type)
{ } private BoundBinaryOperator(SyntaxKind syntaxKind, BoundBinaryOperatorKind kind, Type operandType, Type resultType)
: this(syntaxKind, kind, operandType, operandType, resultType)
{ } private BoundBinaryOperator(SyntaxKind syntaxKind, BoundBinaryOperatorKind kind, Type leftType, Type rightType, Type resultType)
{
SyntaxKind = syntaxKind;
Kind = kind;
LeftType = leftType;
RightType = rightType;
Type = resultType;
} public SyntaxKind SyntaxKind { get; }
public BoundBinaryOperatorKind Kind { get; }
public Type LeftType { get; }
public Type RightType { get; }
public Type Type { get; } private static BoundBinaryOperator[] _operators =
{
new BoundBinaryOperator(SyntaxKind.PlusToken, BoundBinaryOperatorKind.Addition, typeof(int)),
new BoundBinaryOperator(SyntaxKind.MinusToekn, BoundBinaryOperatorKind.Subtraction, typeof(int)),
new BoundBinaryOperator(SyntaxKind.StarToken, BoundBinaryOperatorKind.Multiplication, typeof(int)),
new BoundBinaryOperator(SyntaxKind.SlashToken, BoundBinaryOperatorKind.Division, typeof(int)),
new BoundBinaryOperator(SyntaxKind.EqualsEqualsToken, BoundBinaryOperatorKind.Equals, typeof(int), typeof(bool)),
new BoundBinaryOperator(SyntaxKind.BangEqualsToken, BoundBinaryOperatorKind.NotEquals, typeof(int), typeof(bool)), new BoundBinaryOperator(SyntaxKind.AmpersandAmpersandToken, BoundBinaryOperatorKind.LogicalAnd, typeof(bool)),
new BoundBinaryOperator(SyntaxKind.PipePipeToken, BoundBinaryOperatorKind.LogicalOr, typeof(bool)),
new BoundBinaryOperator(SyntaxKind.EqualsEqualsToken, BoundBinaryOperatorKind.Equals, typeof(bool)),
new BoundBinaryOperator(SyntaxKind.BangEqualsToken, BoundBinaryOperatorKind.NotEquals, typeof(bool)),
}; public static BoundBinaryOperator Bind(SyntaxKind syntaxKind, Type leftType, Type rightType)
{
foreach (var op in _operators)
{
if (op.SyntaxKind == syntaxKind && op.LeftType == leftType && op.RightType == rightType)
return op;
} return null;
}
}
}

以及 BoundBinaryExpression 的实现:

using System;

namespace Minsk.CodeAnalysis.Binding
{
internal sealed class BoundBinaryExpression : BoundExpression
{
public BoundBinaryExpression(BoundExpression left, BoundBinaryOperator op, BoundExpression right)
{
Left = left;
Op = op;
Right = right;
} public override Type Type => Op.Type;
public override BoundNodeKind Kind => BoundNodeKind.BinaryExpression;
public BoundExpression Left { get; }
public BoundBinaryOperator Op { get; }
public BoundExpression Right { get; }
}
}

2.Evaluator 不再基于 SyntaxTree 求值,而是基于 Binder 求值。

3.优先级更加通用的做法。

namespace Minsk.CodeAnalysis.Syntax
{
internal static class SyntaxFacts
{
public static int GetUnaryOperatorPrecedence(this SyntaxKind kind)
{
switch (kind)
{
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToekn:
case SyntaxKind.BangToken:
return 6; default:
return 0;
}
} public static int GetBinaryOperatorPrecedence(this SyntaxKind kind)
{
switch (kind)
{
case SyntaxKind.StarToken:
case SyntaxKind.SlashToken:
return 5; case SyntaxKind.PlusToken:
case SyntaxKind.MinusToekn:
return 4; case SyntaxKind.EqualsEqualsToken:
case SyntaxKind.BangEqualsToken:
return 3; case SyntaxKind.AmpersandAmpersandToken:
return 2; case SyntaxKind.PipePipeToken:
return 1; default:
return 0;
}
} internal static SyntaxKind GetKeyWordKind(string text)
{
switch (text)
{
case "true":
return SyntaxKind.TrueKeyword;
case "false":
return SyntaxKind.FalseKeyword;
default:
return SyntaxKind.IdentifierToken;
}
}
}
}

结合优先级可以更加深刻理解递归下降分析的思路。

4.实现了 Boolean 类型,以及其他的运算符。

C#语言点:

1.扩展方法。将 this XXX 作为 static 函数的第一个成员,然后该函数成为 XXX 的成员函数。这也是一般意义上实现类成员函数的方法。

2.库函数

public static class Enumerable
{
public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second);
}

在System.Linq中,库为 Enumerable 扩展了很多方法,见第一点。

工具:

VS的代码转换技巧,比如快速对逻辑表达式取反、快速将 if 转为 switch。

笔记 - C#从头开始构建编译器 - 2的更多相关文章

  1. 笔记 - C#从头开始构建编译器 - 1

    视频与PR:https://github.com/terrajobst/minsk/blob/master/docs/episode-01.md 作者是 Immo Landwerth(https:// ...

  2. 笔记 - C#从头开始构建编译器 - 3

    视频与PR:https://github.com/terrajobst/minsk/blob/master/docs/episode-03.md 作者是 Immo Landwerth(https:// ...

  3. keras 学习笔记:从头开始构建网络处理 mnist

    全文参考 < 基于 python 的深度学习实战> import numpy as np from keras.datasets import mnist from keras.model ...

  4. 软工读书笔记 week 9 ——《构建之法》

    软工读书笔记  week 9                 ——<构建之法> 最近的三周我们正式开始我们的项目.然后我也把<构建之法>中的相关章节再拿出来读了一番.以下是一些 ...

  5. [HeadFrist-HTMLCSS学习笔记]第三章构建模块:Web页面建设

    [HeadFrist-HTMLCSS学习笔记]第三章构建模块:Web页面建设 敲黑板!! <q>元素添加短引用,<blockquote>添加长引用 在段落里添加引用就使用< ...

  6. blfs(systemd版本)学习笔记-为桌面环境构建xorg服务

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! lfs准备使用桌面环境,首先需要构建xorg服务 xorg服务项目地址:http://www.linuxfromscratch. ...

  7. blfs(systemv版本)学习笔记-为桌面环境构建xorg服务

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! lfs准备使用桌面环境,首先需要构建xorg服务 xorg服务项目地址:http://www.linuxfromscratch. ...

  8. 软工读书笔记 week 5 ——《构建之法》

    本周主要对<构建之法>中的一部分进行阅读. 一.软件与软件工程究竟是什么? 本书的概论部分就指出“软件 = 程序 + 软件工程”.而我们这门课的名字就叫“现代软件工程”.其实在上课之前,我 ...

  9. 《Maven实战》笔记-10-灵活的构建

    一.灵活构建的意义 一个优秀的构建系统必须足够灵活,它应该能够让项目在不同的环境下都能成功地构建.例如,典型的项目都会有开发环境.测试环境和产品环境,这些环境的数据库配置不尽相同,那么项目构建的时候就 ...

随机推荐

  1. Looper: Looper,Handler,MessageQueue三者之间的联系

    在Android中每个应用的UI线程是被保护的,不能在UI线程中进行耗时的操作,其他的子线程也不能直接进行UI操作.为了达到这个目的Android设计了handler Looper这个系统框架,And ...

  2. vscode 常用设置与插件推荐

    1.Chinese (Simplified) Language Pack for Visual Studio Code 适用于 VS Code 的中文(简体)语言包 2.Color Info Visu ...

  3. 创建WebApi Odata v3 终结点

    开放数据协议(OData) 是用于 web 的数据访问协议. OData 提供统一的方法来构造数据. 查询的数据和操作该数据集通过 CRUD 操作 (创建. 读取. 更新和删除). OData 支持 ...

  4. python for test

    for i,value in enumerate(['A', 'B', 'C']) print(i,value)

  5. k8s记录-flanneld+docker网络部署(四)

    1)程序准备tar xvf flannel-v0.10.0-linux-amd64.tar.gz mkdir -p /data/projects/common/kubernetes/{bin,cfg, ...

  6. 如何发布自定义的UI 组件库到 npmjs.com 并且编写 UI组件说明文档

    记录基于 antd 封装业务组件并发布到npm 上的过程:(TS + React + Sass) 初始化项目: 1.yarn create react-app winyhui --typescript ...

  7. Swift4.0复习结构体

    1.基本语法: /** 定义了一个结构体 */ struct Structure {   /// 一个常量存储式实例属性, /// 并直接为它初始化 let constProperty =   /// ...

  8. idea中报Can't start Git: git.exe The path to Git executable is probably not valid. Fix it

    解决办法,点解Fix it,或者File ----setting------version control-------git,设置git的可执行文件路径就可以了 设置好了git的安装路径的可运行文件 ...

  9. github账户初始化设置

    1.首先在github官网https://github.com/上注册自己的账户: 2.去git官网https://git-scm.com/downloads,根据电脑系统下载合适的版本并安装. 3. ...

  10. ECOC 2019展会:以太网联盟公开展示其下一代网络100/200/400G互通测试能力,网络自动化测试能力再次被提出

    欧洲光纤通讯展ECOC 2019正在火热进行,以太网联盟组织Ethernet Alliance在其公开展台演示了其下一代高速网络100G/200G/400G相关能力,其成员单位Cisco,Arista ...