手把手带你写一门编程语言
宫文学
北京原点代码 CEO
7235 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 49 讲
起步篇:让一门超简单的语言跑起来 (21讲)
结束语 (1讲)
手把手带你写一门编程语言
15
15
1.0x
00:00/00:00
登录|注册

04|如何让我们的语言支持变量和类型?

你好,我是宫文学。
到目前为止,我们的语言已经能够处理语句,也能够处理表达式,并且都能够解释执行了。不过,我们目前程序能够处理的数据,还都只是字面量而已。接下来,我们要增加一个重要的能力:支持变量
在程序中声明变量、对变量赋值、基于变量进行计算,是计算机语言的基本功能。只有支持了变量,我们才能实现那些更加强大的功能,比如,你可以用程序写一个计算物体下落的速度和位置,如何随时间变化的公式。这里的时间就是变量,通过给时间变量赋予不同的值,我们可以知道任意时间的物体速度和位置。
这一节,我就带你让我们手头上的语言能够支持变量。在这个过程中,你还会掌握语义分析的更多技能,比如类型处理等。
好了,我们已经知道了这一节的任务。那么第一步要做什么呢?你可以想到,我们首先要了解与处理变量声明和初始化有关的语法规则。

与变量有关的语法分析功能

在 TypeScript 中,我们在声明变量的时候,可以指定类型,这样有助于在编译期做类型检查:
let myAge : number = 18;
如果编译成 JavaScript,那么类型信息就会被抹掉:
var myAge = 18;
不过,因为我们的目标是教给你做类型分析的方法,以后还要静态编译成二进制的机器码,所以我们选择的是 TypeScript 的语法。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《手把手带你写一门编程语言》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(12)

  • 最新
  • 精选
  • 千无
    几节课学下来,除了第一节课用了老师的代码(经过自己的改造),后面都是基于改造的代码来逐步迭代升级。 每行代码都是自己思考过才写下来的,实现了自己想要的功能后(比如第一节结束后,我扩展实现了作用域链,以支持不同作用域下的变量声明、函数传参,以及赋值表达式),再对比老师的代码来学习老师的编程思想。 这样看代码的时候能够一目十行,而且因为是带着问题去看的,所以会有更多收获。 唯一难受的,这个过程很痛苦。 但我想,这是最慢,但也是最快的一种学习方式。
    11
  • _______R
    关于 typeAnnotation 的 follow 集合,根据文中的说法,冒号 ':' 是 First 集,那么 Follow 集就是各个类型关键字,这些关键字有: : booleaan 布尔值 : number 数字 : string 字符串 : void : any : never : null : undefined : object 对象 : Array<typeName> 数组 : typeName[] 数组 : [] 元组 : identifier 自定义类型 如果是 go 语言,则是 i集合:int、int8、int16、int32、int64 u集合:uint、uint8、uint16、uint32、uint64 f集合:float32、float64 c集合:complex64、complex128 string 字符串 bool 布尔值 rune int32类型的别名,代表一个 UTF-8 字符 byte uint8类型的别名,代表一个 ASCII 字符 interface{} 空接口类型 [n]typeName 数组类型 []typeName slice 类型 map[typeName]typeName map类型 chan typeName channel 类型 struct 结构体类型
    2
  • chris
    老师目前的语法规则我仔细看后觉得好像还不是很严谨 * prog = statementList? EOF; * statementList = (variableDecl | functionDecl | expressionStatement)+ ; * variableDecl : 'let' Identifier typeAnnotation? ('=' singleExpression) ';'; * typeAnnotation : ':' typeName; * functionDecl: "function" Identifier "(" ")" functionBody; * functionBody : '{' statementList? '}' ; * statement: functionDecl | expressionStatement; * expressionStatement: expression ';' ; * expression: primary (binOP primary)* ; * primary: StringLiteral | DecimalLiteral | IntegerLiteral | functionCall | '(' expression ')' ; * binOP: '+' | '-' | '*' | '/' | '=' | '+=' | '-=' | '*=' | '/=' | '==' | '!=' | '<=' | '>=' | '<' * | '>' | '&&'| '||'|...; * functionCall : Identifier '(' parameterList? ')' ; * parameterList : expression (',' expression)* ; 例如variableDecl的最后一个括号是否应该带一个?, 且singleExpression未给出定义. 还有定义了一条statement但并未在哪里用到阿.
    1
    1
  • ifelse
    学习打卡
    归属地:浙江
  • 慢动作
    变量声明的语法规则中,typeAnnotation 的 Follow 集合是不是=和;?
  • 黄东
    老师好,这个存放变量的值的map,全是编译时的还是运行时的呢,如果是编译时的,那运行时的变量的值的变化跟这个有关系吗
  • 奇想天外
    好像不支持负数?let i = -10 + 1; 这样的语句好像不行?
  • 有学识的兔子
    first 是: follow就很多了,string,number ,boolean,object,支持的数据类型,对象类型等,但应该不含关键字,原因是关键字一般在变量前面使用,与语法规则不符。
  • _______R
    宫老师,04的代码是不是还不完整?我用go调试了好久函数总是没消解引用,调了ts的好像也是没有
  • chris
    RefResolver.visitFunctionCall是否应该加一段对functionCall.parameters的visit, 如下: visitFunctionCall(functionCall:FunctionCall):any{ let symbol = this.symTable.getSymbol(functionCall.name); if (symbol != null && symbol.kind == SymKind.Function){ functionCall.decl = symbol.decl as FunctionDecl; } else{ if (functionCall.name != "println"){ //系统内置函数不用报错 console.log("Error: cannot find declaration of function " + functionCall.name); return; } } for(let param of functionCall.parameters) { this.visit(param); } }
收起评论
显示
设置
留言
12
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部