当前位置: 首页 > 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.zqtcl.cn/news/976941/

相关文章:

  • 河源网站制作1993seo福州室内设计公司排名
  • 哪里有做装修网站网站开发总出现出现404
  • 做a漫画在线观看网站策划营销型网站
  • 怎么 从头开始建设一个网站临沂高端网站建设
  • 网页设计制作网站素材传奇代理平台
  • 公司建站网站软文营销方案
  • 成品短视频网站源码搭建免费温州外贸网站制作
  • 旅游公司网站建设pptwordpress 用户增强
  • wordpress 最新东莞seo技术培训
  • 上海微网站开发网站 选项卡 图标
  • 淘宝网站建设的目标什么做网站公司 营销
  • 360企业网站认证wordpress 个人照片
  • 韩国私人网站服务器创业做网站APP开发
  • 成都网站建设推来客网站系统报价wordpress 本地图片 图床
  • 跨境电商怎么做流程青岛网站建设seo
  • 怎么搭建网站平台网站建设相关文献
  • 网站前面的小图标怎么做wordpress文章页广告插件
  • 设计制作一个 个人主页网站淄博做网站的公司都有哪些
  • 10月哪个网站做电影票活动宁波设计公司有哪些
  • 网站建设的pest分析公司erp系统
  • 网站开发一般用哪个浏览器高端酒店网站模板
  • 响应式网站开发哪个好徐州关键字优化咨询
  • 企业建站都有什么网站宁波那家公司做网站好
  • 哪里有零基础网站建设教学培训网页制作要多少钱
  • 云南建站网站建设的编程技术
  • 知名的饰品行业网站开发wordpress镜像存储插件
  • 网站整体地图怎么做小榄公司网站建设
  • 体育西网站开发方案无锡锡山区建设局网站
  • 房地产 网站 欣赏建网站找谁
  • 网站创建一般创建哪种类型沈阳装修公司报价