当前位置: 首页 > news >正文

免费物流公司网站模板重庆学校网站建设

免费物流公司网站模板,重庆学校网站建设,网站空间去哪买,深圳网站建设公司公司上一节我们研究了增强语法#xff0c;本节我们看看何为属性语法。属性语法实则是在语法规则上附带上一些重要的解析信息#xff0c;随着语法解析的进行#xff0c;我们可以利用附带的解析信息去进行一系列操作#xff0c;例如利用解析信息实现代码生成。我们先看属性语法的…上一节我们研究了增强语法本节我们看看何为属性语法。属性语法实则是在语法规则上附带上一些重要的解析信息随着语法解析的进行我们可以利用附带的解析信息去进行一系列操作例如利用解析信息实现代码生成。我们先看属性语法的一个实例 NUMBER(156, 156)NUMBER 是语法解析中的终结符他附带有两个属性一个是该标签对应字符串的内容“156”另一个是他对应的数值也就是 156如果符号是 ID也就是变量那么它可以附带一个属性就是一个指针指向符号表的入口该符号表包含了该变量的字符串名称该变量对应的数据等等。 属性信息分为两种一种是继承属性也就是属性从语法表达式箭头左边的符号传递给右边的符号另一种是综合属性属性信息从箭头右边符号汇总后传递给左边符号。从前面代码中我们看到语法解析本质上就是函数的调用例如语法 expr - term expr_prime对应的代码实现就是 expr() {term()expr_prime()}对于继承属性那就是父函数expr 在调用是被输入了某些参数这些参数再传递给里面的 term,和 expr_prime例如 expr(param) {term(param)expr_prime(param) }而综合属性就是子函数有返回值父函数获取子函数的返回值后综合起来处理例如 expr() {val_term : term()val_expr_prime : expr_prime(param)do_something(val_term, val_expr_prime)}在上一节我们使用增强语法来生成代码时代码生成所需要的信息例如寄存器等是从全局函数或全局变量例如全局寄存器数组等中获取在属性语法中我们就可以把这些信息作为参数传递给特定的语法解析函数这样在生成代码时就能更灵活。我们看具体的实现你就能更明白什么叫属性语法我们还是利用上一节识别算术表达式的语法 stmt - epsilon | expr SEMI stmt expr - term expr_prime expr_prime - PLUS term expr_prime term - factor term_prime term_prime - MUL factor term_prime | epsilon factor - NUMBER | LEFT_PAREN expr RIGHT_PAREN在原有项目中创建新文件夹 attribute_parser,在里面创建文件 attribute_parser.go添加代码如下 package attribute_parserimport (fmtlexer )type AttributeParser struct {parserLexer lexer.LexerreverseToken []lexer.Token//用于存储虚拟寄存器的名字registerNames []string//存储当前已分配寄存器的名字regiserStack []string//当前可用寄存器名字的下标registerNameIdx int }func NewAttributeParser(parserLexer lexer.Lexer) *AttributeParser {return AttributeParser{parserLexer: parserLexer,reverseToken: make([]lexer.Token, 0),registerNames: []string{t0, t1, t2, t3, t4, t5, t6, t7},regiserStack: make([]string, 0),registerNameIdx: 0,} }func (a *AttributeParser) putbackToken(token lexer.Token) {a.reverseToken append(a.reverseToken, token) }func (a *AttributeParser) getToken() lexer.Token {//先看看有没有上次退回去的 tokenif len(a.reverseToken) 0 {token : a.reverseToken[len(a.reverseToken)-1]a.reverseToken a.reverseToken[0 : len(a.reverseToken)-1]return token}token, err : a.parserLexer.Scan()if err ! nil token.Tag ! lexer.EOF {sErr : fmt.Sprintf(get token with err:%s\n, err)panic(sErr)}return token }func (a *AttributeParser) match(tag lexer.Tag) bool {token : a.getToken()if token.Tag ! tag {a.putbackToken(token)return false}return true }func (a *AttributeParser) newName() string {//返回一个寄存器的名字if a.registerNameIdx len(a.registerNames) {//没有寄存器可用panic(register name running out)}name : a.registerNames[a.registerNameIdx]a.registerNameIdx 1return name }func (a *AttributeParser) freeName(name string) {//释放当前寄存器名字if a.registerNameIdx len(a.registerNames) {panic(register name index out of bound)}if a.registerNameIdx 0 {panic(register name is full)}a.registerNameIdx - 1a.registerNames[a.registerNameIdx] name }func (a *AttributeParser) Parse() {a.stmt() }func (a *AttributeParser) stmt() {for a.match(lexer.EOF) ! true {t : a.newName()a.expr(t)a.freeName(t)if a.match(lexer.SEMI) ! true {panic(missing ; at the end of expression)}} }func (a *AttributeParser) expr(t string) {a.term(t)a.expr_prime(t) }func (a *AttributeParser) expr_prime(t string) {if a.match(lexer.PLUS) {t2 : a.newName()a.term(t2)fmt.Printf(%s %s\n, t, t2)a.freeName(t2)a.expr_prime(t)} }func (a *AttributeParser) term(t string) {a.factor(t)a.term_prime(t) }func (a *AttributeParser) term_prime(t string) {if a.match(lexer.MUL) {t2 : a.newName()a.factor(t2)fmt.Printf(%s * %s\n, t, t2)a.freeName(t2)a.term_prime(t)} }func (a *AttributeParser) factor(t string) {if a.match(lexer.NUM) {fmt.Printf(%s %s\n, t, a.parserLexer.Lexeme)} else if a.match(lexer.LEFT_BRACKET) {a.expr(t)if a.match(lexer.RIGHT_BRACKET) ! true {panic(missing ) for expr)}} } 我们可以看到 AttributeParser 跟我们前面实现的 AugmentedParser 区别不大一个明显区别是解析函数接受一个传进来的参数这个参数可以看做是语法属性他由语法表达式左边符号对应的函数创建然后传递给右边符号对应的函数。我们看如下代码 func (a *AttributeParser) stmt() {for a.match(lexer.EOF) ! true {t : a.newName()a.expr(t)a.freeName(t)if a.match(lexer.SEMI) ! true {panic(missing ; at the end of expression)}} }stmt 函数在调用时创建了一个寄存器名称然后调用 expr 时将该名称作为参数传入在语法表达上相当于 stmt_(t) - expr_(t) SEMI stmt其中 t 是左边 stmt 符号附带的参数他将该参数传递给右边符号 exprexpr 利用该传过来的符号在语法解析时进行代码生成。从上面代码我们也能看出它实际上是增强语法和属性语法的结合体例如代码将属性作为参数传入同时在解析的过程中又在特定位置执行特定步骤因此上面的解析过程其实可以对应成如下的“增强属性语法” stmt - epsilon | {tnewName()} expt_(t) SEMI stmt expr_(t) - term_(t) expr_prime_(t) expr_prime_(t) - PLUS {t2 newName()} term_(t2) {print(%s%s\n,t,t2) freenName(t2)} expr_prime_(t) | epsilon term_(t) - factor term_prime term_prime_(t) - MUL {t2 newName()} factor_(t2) {print(%s%s\n,t,t2) freeName(t2)} term_prime_(t) factor_(t) - NUM {print(%s*%s\n,t, lexeme)} | LEFT_PAREN expr_(t) RIGHT_PAREN最后我们在 main.go 中调用属性语法解析器看看运行结果 package mainimport (attribute_parserlexer )func main() {exprLexer : lexer.NewLexer(12*(43);)attributeParser : attribute_parser.NewAttributeParser(exprLexer)attributeParser.Parse() } 上面代码运行后结果如下 t0 1 t1 2 t2 4 t3 3 t2 t3 t1 * t2 t0 t1可以看到生成的结果跟我们上一节一样。更多内容请在 b 站搜索 coding 迪斯尼。代码下载 https://github.com/wycl16514/compiler-attribute-grammar.git
http://www.pierceye.com/news/976941/

相关文章:

  • 彩网站开发购物小程序源码
  • 优秀的网站建设开发案例合肥备案
  • 做网站怎么签订协议大数据下的精准营销
  • wordpress模版建站城乡建设部网站施工员证书查询
  • 手机网站前端网站开发成本包括
  • 有了主机和域名后如何做网站seo网站建站公司的主页
  • 株洲网站制作360广告联盟平台
  • 网站pv是什么意思vps开wordpress
  • 国外网站模版免费下载南通建设网站公司
  • 网站建设 广西学3d建模学费一般多少
  • 整站外包优化公司金山西安网站建设
  • 做3d动画网站广州公关公司排行榜
  • 网站开发确认表seo技术教程博客
  • 彩票网站建设一条龙淘客app
  • 泰安网站推广优化网站百度收录是什么意思
  • 免费虚拟主机控制面板长沙推广优化公司
  • 重庆企业网站建站公司建站系统
  • 规划设计网站推荐自己做采集电影网站
  • 免费学编程的网站有哪些做网站设计用什么软件
  • 网站成品超市学室内设计去哪好
  • 网站备案一个主体无锡建设银行网站
  • delphi xe10网站开发台州做网站多少钱
  • 怎样设计卖奖的网站做电影网站哪个服务器好
  • 找外包公司做网站的好处和坏处wordpress 访问量大
  • 淄博 网站设计越秀公司网站建设
  • 网站该如何做本地网站搭建软件
  • 如何做汽车团购网站学做馒头面包哪个网站好
  • 中国科技成就总结莱芜网站优化排名公司
  • 中国建设银行网站企业网银收费北京网站建设小程序开发
  • 成交型网站倡导公司网络营销课程总结1000字