1

简而言之:如何在 ANTLR 中实现动态变量?
我再次带着一个基本的 ANTLR 问题来找你。
我有这个语法:

grammar Amethyst;

options {
    language = Java;
}

@header {
    package org.omer.amethyst.generated;
    import java.util.HashMap;
}

@lexer::header {
    package org.omer.amethyst.generated;
}

@members {
    HashMap memory = new HashMap();
}

begin: expr;

expr: (defun | println)*
;

println:
    'println' atom {System.out.println($atom.value);}
;

defun:
    'defun' VAR INT {memory.put($VAR.text, Integer.parseInt($INT.text));}
    | 'defun' VAR STRING_LITERAL {memory.put($VAR.text, $STRING_LITERAL.text);}
;

atom returns [Object value]:
    INT {$value = Integer.parseInt($INT.text);}

    |   ID
    {
    Object v = memory.get($ID.text);
    if (v != null) $value = v;
    else System.err.println("undefined variable " + $ID.text);
    }

| STRING_LITERAL
  {
    String v = (String) memory.get($STRING_LITERAL.text);
    if (v != null) $value = String.valueOf(v);
    else System.err.println("undefined variable " + $STRING_LITERAL.text);
  }
;

INT: '0'..'9'+ ;
STRING_LITERAL: '"' .* '"';

VAR: ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')* ;
ID: ('a'..'z'|'A'..'Z'|'0'..'9')+ ;
LETTER: ('a..z'|'A'..'Z')+ ;
WS: (' '|'\t'|'\n'|'\r')+ {skip();} ;

到目前为止,它所做的(或应该做的)是有一个内置的“println”函数来做你认为它做的事情,以及一个定义变量的“defun”规则。
当对字符串或整数调用“defun”时,该值被放入“memory”HashMap,第一个参数是变量名,第二个参数是它的值。
当对原子调用 println 时,它应该显示原子的值。原子可以是字符串或整数。它从内存中获取它的值并返回它。例如:

defun greeting "Hello world!"

println greeting

但是当我运行这段代码时,我得到了这个错误:

line 3:8 no viable alternative at input 'greeting'
null

注意:当我这样做时,会出现此输出:

println "greeting"

输出:

undefined variable "greeting"null

有谁知道为什么会这样?对不起,如果我不清楚,我不明白这一点。

4

1 回答 1

1
defun greeting "Hello world!"

println greeting

但是当我运行这段代码时,我得到了这个错误:

第 3:8 行在输入“问候”时没有可行的替代方案

因为输入"greeting"被标记为 aVAR而 aVAR是 no atom。因此输入与规则的第二种选择defun greeting "Hello world!"正确匹配:defun

defun
 : 'defun' VAR INT               // 1st alternative
 | 'defun' VAR STRING_LITERAL    // 2nd alternative
 ;

但输入println "greeting"不能被println规则匹配:

println
 : 'println' atom
 ;

您必须意识到词法分析器不会根据解析器在特定时间尝试匹配的内容来生成标记。输入"greeting"将始终被标记为 a VAR,而不是作为ID规则。

您需要做的是ID从词法分析器中删除规则,并在解析器规则中替换ID为。VAR

于 2012-05-04T06:55:10.367 回答