【问题标题】:ANTLR check if commontree is correct or How to check if given input matches the ANTLR grammar?ANTLR 检查 commontree 是否正确或如何检查给定的输入是否与 ANTLR 语法匹配?
【发布时间】:2012-03-13 07:39:04
【问题描述】:

您好,我想做一个 java 或 c# 方法,它将根据给定的输入返回一个布尔表达式 true 或 false。例如:

if(输入匹配 antlr 语法) 返回真; 别的 返回假; 所以问题是我不知道如何检查公共树是否有任何不匹配的令牌。我试图遍历树,但它没有给出任何 mismatchetoken 作为树的节点。问题可能在于 AST 仅在解析树中不显示不匹配的标记。如果有人告诉我如何从解析器中获取解析树,也会有所帮助?

我已经完成了 ANTLR .g 文件,它运行良好,现在我需要执行以下操作:我必须检查输入是否正确,我已经这样做了,但它不起作用:

 public static boolean check() {
    String file = "test.txt";
    ANTLRReaderStream input;
    try{

            input = new ANTLRReaderStream(new FileReader(file));
            regExLexer lexer = new regExLexer(input);
            CommonTokenStream tokens = new CommonTokenStream(lexer);
            regExParser parser = new regExParser(tokens);

            CommonTree root = (CommonTree)parser.goal().getTree();

        return true;}
catch{
return false;}
}

所以我希望我的方法仅在输入字符串正确时返回 true,否则返回 false。我这样做的方式总是返回 true,但是当字符串不正确时它会打印

"第 1:4 行无关输入 '+' 期待 EOF"

在控制台中。

【问题讨论】:

    标签: java compiler-construction antlr finite-automata antlrworks


    【解决方案1】:

    正如我在您的问题下的 cmets 中所暗示的那样:this previous Q&A 回答了您的问题。我会用一个例子来演示。

    假设您有一个接受数字(并忽略空格)的语法。您只需要覆盖解析器和词法分析器的reportError 并在该方法中抛出异常:这样解析器(或词法分析器)将不会继续。捕获错误并在 static 辅助方法中简单地返回 false

    grammar T;
    
    @parser::members {
    
      public static boolean matches(String input) {
        try {
          TLexer lexer = new TLexer(new ANTLRStringStream(input));
          TParser parser = new TParser(new CommonTokenStream(lexer));
          parser.parse();
          return true;
        } catch(Exception e) {
          return false;
        }
      }
    
      @Override
      public void reportError(RecognitionException e) {
        throw new RuntimeException(e); 
      }
    }
    
    @lexer::members {
      @Override
      public void reportError(RecognitionException e) {
        throw new RuntimeException(e); 
      }
    }
    
    parse
     : NUMBER* EOF
     ;
    
    NUMBER : '0'..'9'+;
    SPACE  : ' ' {skip();};
    

    现在开始上课了:

    import org.antlr.runtime.*;
    
    public class Main {
      public static void main(String[] args) throws Exception {
        System.out.println(TParser.matches(""));
        System.out.println(TParser.matches("1 234 42"));
        System.out.println(TParser.matches("12 556 f"));
      }
    }
    

    将打印:

    true
    true
    false
    

    【讨论】:

    • 谢谢,非常好。现在我还有一个问题。例如,我的语法接受这个字符串 ab 但不接受 a*b,这部分效果很好,但是当我添加一个不属于语言的字符串时,它会引发异常但返回 true,例如 a *b_。在这种情况下,“_”不是我的语言的一部分。任何建议
    • 哦,我忘了在我的词法分析器中添加@Override。非常感谢。
    【解决方案2】:

    ANTLR 会为您恢复一些错误(例如丢失明显的标记),如果您不熟悉它可能会很痛苦。

    如果你愿意,你可以重写 regExParser 类中的 BaseRecognizer.recoverFromMismatchedToken 并在发现不匹配的令牌时总是抛出异常。

    参考:

    ANTLR: error recovery and reporting

    【讨论】:

    • 感谢您的回答,但我认为通过覆盖该类我将实现显示自定义错误,这不是我需要的。我只需要知道何时发生错误(任何错误)我想做这样的事情:if(error发生){do smth} else {do smth else} by error发生我的意思是检查给定的输入是否与antlr语法匹配在 .g 文件中指定?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    • 2017-07-24
    • 1970-01-01
    相关资源
    最近更新 更多