parsing - Antlr4如何构建允许关键字作为标识符的语法

标签 parsing antlr antlr4 peg

这是一个演示代码

label:
var id
let id = 10
goto label

如果允许关键字作为标识符,将会是

let:
var var
let var = 10
goto let

这是完全合法的代码。但在antlr中似乎很难做到这一点。

AFAIK,如果 antlr 匹配 token let,则永远不会回退到 id token。所以对于antlr它会看到

LET_TOKEN :
VAR_TOKEN <missing ID_TOKEN>VAR_TOKEN
LET_TOKEN <missing ID_TOKEN>VAR_TOKEN = 10

虽然antlr允许predicate ,我必须控制所有 token 匹配和问题。语法变成这样

grammar Demo;
options {
  language = Go;
}
@parser::members{
    var _need = map[string]bool{}
    func skip(name string,v bool){
        _need[name] = !v
        fmt.Println("SKIP",name,v)
    }
    func need(name string)bool{
        fmt.Println("NEED",name,_need[name])
        return _need[name]
    }
}

proj@init{skip("inst",false)}: (line? NL)* EOF;
line
    : VAR ID
    | LET ID EQ? Integer
    ;

NL: '\n';
VAR: {need("inst")}? 'var' {skip("inst",true)};
LET: {need("inst")}? 'let' {skip("inst",true)};
EQ: '=';

ID: ([a-zA-Z] [a-zA-Z0-9]*);
Integer: [0-9]+;

WS: [ \t] -> skip;

看起来很糟糕。

但这在 Hook 中很容易,在 pegjs 中测试一下

Expression = (Line? _ '\n')* ;

Line
  = 'var' _ ID
  / 'let' _ ID _ "=" _ Integer

Integer "integer"
  = [0-9]+ { return parseInt(text(), 10); }

ID = [a-zA-Z] [a-zA-Z0-9]*

_ "whitespace"
  = [ \t]*

我实际上是在 peggo 中完成的和 javacc .

我的问题是如何在antlr4.6中处理这些语法,我对antlr4.6 go目标非常兴奋,但似乎我为我的语法选择了错误的工具?

最佳答案

最简单的方法是为标识符定义解析器规则:

id: ID | VAR | LET;

VAR: 'var';
LET: 'let';
ID: [a-zA-Z] [a-zA-Z0-9]*;

然后在解析器规则中使用 id 而不是 ID

另一种方法是使用 ID 作为标识符关键字,并使用谓词来消除歧义。但它的可读性较差,所以我会使用第一种方式。

关于parsing - Antlr4如何构建允许关键字作为标识符的语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41421644/

相关文章:

C 字符串解析和转换

java - PDF 中的文本以不同方式吐出

java - 仅使用字符串和值解析 JSON 对象

compiler-construction - ANTLR:忽略解析器中的语句

intellij-idea - 如何知道 IntelliJ 中的 gradle 任务错误消息?

python - AnTLR4:INDENT 和 DEDENT 代币

arrays - ELM 如何解码 json 数组中的不同值

java - Antlr 3 无法处理句法谓词

antlr4 - ANTLR 4.1 变量 ANTLR 4 token 多重性产生错误 : "closure with at least one alternative that can match empty string"

algorithm - 运行解析器时出现 Antlr4 错误