04|如何让我们的语言支持变量和类型?
宫文学
你好,我是宫文学。
到目前为止,我们的语言已经能够处理语句,也能够处理表达式,并且都能够解释执行了。不过,我们目前程序能够处理的数据,还都只是字面量而已。接下来,我们要增加一个重要的能力:支持变量。
在程序中声明变量、对变量赋值、基于变量进行计算,是计算机语言的基本功能。只有支持了变量,我们才能实现那些更加强大的功能,比如,你可以用程序写一个计算物体下落的速度和位置,如何随时间变化的公式。这里的时间就是变量,通过给时间变量赋予不同的值,我们可以知道任意时间的物体速度和位置。
这一节,我就带你让我们手头上的语言能够支持变量。在这个过程中,你还会掌握语义分析的更多技能,比如类型处理等。
好了,我们已经知道了这一节的任务。那么第一步要做什么呢?你可以想到,我们首先要了解与处理变量声明和初始化有关的语法规则。
与变量有关的语法分析功能
在 TypeScript 中,我们在声明变量的时候,可以指定类型,这样有助于在编译期做类型检查:
如果编译成 JavaScript,那么类型信息就会被抹掉:
不过,因为我们的目标是教给你做类型分析的方法,以后还要静态编译成二进制的机器码,所以我们选择的是 TypeScript 的语法。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了编程语言中变量和类型支持的重要性,并介绍了实现编程语言变量和类型支持的方法。文章首先讨论了变量的声明、赋值和计算的基本功能,然后详细介绍了与变量相关的语法分析功能,包括变量声明和初始化的语法规则以及LL算法的计算过程。作者还提供了示例代码来说明如何实现增强的语法分析程序,以支持变量声明和初始化语句。此外,文章还讨论了变量赋值语句的支持,包括赋值表达式的右结合性质和相应的语法规则修改。另外,文章还讨论了类型处理的语义分析功能,包括属性计算和类型推断。最后,提到了其他需要实现的语义分析功能,如赋值语句中左值的规定和字符串的运算规则等。通过迭代开发方式,文章展示了如何让编程语言的功能一点点变强。读者可以从中学习如何增加新的语法规则、使用LL算法、引入符号表以简化引用消解机制,以及实现类型的检查和自动推断。文章还提出了思考题,鼓励读者深入思考变量声明的语法规则。整体而言,本文对编程语言中与变量和类型相关的语法分析和实现方法进行了深入浅出的介绍,对想要深入了解编程语言内部实现的读者来说,具有很高的参考价值。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《手把手带你写一门编程语言》,新⼈⾸单¥59
《手把手带你写一门编程语言》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(12)
- 最新
- 精选
- 千无几节课学下来,除了第一节课用了老师的代码(经过自己的改造),后面都是基于改造的代码来逐步迭代升级。 每行代码都是自己思考过才写下来的,实现了自己想要的功能后(比如第一节结束后,我扩展实现了作用域链,以支持不同作用域下的变量声明、函数传参,以及赋值表达式),再对比老师的代码来学习老师的编程思想。 这样看代码的时候能够一目十行,而且因为是带着问题去看的,所以会有更多收获。 唯一难受的,这个过程很痛苦。 但我想,这是最慢,但也是最快的一种学习方式。2021-08-2712
- _______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 结构体类型2021-08-172
- 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但并未在哪里用到阿.2021-08-1711
- ifelse学习打卡2022-09-10归属地:浙江
- 慢动作变量声明的语法规则中,typeAnnotation 的 Follow 集合是不是=和;?2021-10-19
- 黄东老师好,这个存放变量的值的map,全是编译时的还是运行时的呢,如果是编译时的,那运行时的变量的值的变化跟这个有关系吗2021-09-05
- 奇想天外好像不支持负数?let i = -10 + 1; 这样的语句好像不行?2021-08-29
- 有学识的兔子first 是: follow就很多了,string,number ,boolean,object,支持的数据类型,对象类型等,但应该不含关键字,原因是关键字一般在变量前面使用,与语法规则不符。2021-08-21
- _______R宫老师,04的代码是不是还不完整?我用go调试了好久函数总是没消解引用,调了ts的好像也是没有2021-08-19
- chrisRefResolver.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); } }2021-08-17
收起评论