• 自制编译器 青木峰郎 笔记 Ch5 基于JavaCC的解析器描述


    5。1 基于EBNF语法的描述

    种类 含义 e.g
    终端符 token , , '=', "Var"
    非终端符 语法树非叶节点 stmt(), expr()

    可以省略的元素用[]括起: e.g: storage() typeref() name ["=" expr()] ";"

    5.2 语法二义性和token的超前扫描

    语法二义性可能由语言定义本身也可能由choice conflict产生。

    Choice Conflict

    如果出现了choice conflict,应该试着先提取共同部分,如果不行,那么就需要LOOKAHEAD。

    LookAhead

    1. 可以使用Lookahead(storage() type() ";")这样的语法预读不确定数目的token,javacc会读取直到该规则完全匹配/不符合该规则为止。
    2. javacc不会再对加了lookahead的地方做任何检查,所以需要编写者确保lookahead正确

    省略与冲突

    如果是语义本身的二义性,例如悬空else

    if(x) if(y){f();}else{g();}
    

    有时也可以采用LOOKAHEAD来解决。
    比如我们规定else属于最内侧的if。
    那么对于规则

    if_stmt(): {}
    {
          <IF> "(" expr() ")" stmt() {<ELSE> stmt();}
    }
    

    还是会在是否省略上产生矛盾。
    使用LOOKAHEAD改为:

    if_stmt(): {}
    {
          <IF> "(" expr() ")" stmt() {LOOKAHEAD(1) <ELSE> stmt();}
    }
    

    重复和冲突

    下列规则会导致可变长参数"," "..."不被解析,因为每次javacc都只读一个token,所以会优先匹配[",", type()]并发现无法匹配。

    param_decls(): {}
    {
          type() ("," type())* ["," "..."]
    }
    

    使用LOOKAHEAD后:

    param_decls(): {}
    {
          type() (LOOKAHEAD(2) "," type())* ["," "..."]
    }
    

    Packrat

    支持无限的超前扫描,无需区分扫描器和解析器,语法无二义性

    parser combinator

    直接用编程语言来描述语法,解析器生成器是单纯的程序库,无需导入额外的工具生成代码

  • 相关阅读:
    杭电2031进制转换
    杭电2033人见人爱A+B
    【转】到底怎么样才叫看书?
    方便单个实体更新的DbContext扩展方法,比如Edit页面
    使用Newtonsoft.Json
    代码配置 vs. 配置文件
    进程到创建
    C#+VBA 操作EXCEL(转)
    基于定位的社交应用Foursquare开源网址(wp7)
    深入理解计算机系统实验
  • 原文地址:https://www.cnblogs.com/xuesu/p/14378307.html
Copyright © 2020-2023  润新知