c# - ANTLR 访问者单元测试在一条规则上成功,但在另一条规则上失败

标签 c# antlr antlr4

我正在尝试为我的 ANTLR 解析器定义单元测试。单元测试成功提取第一个 expr 的值,但提取第一个 idEscape 的值失败。这表明我误解了解析器工作方式或访问者工作方式的核心内容。

我正在编写一个用于 FileMaker Pro 中计算的解析器。在 FileMaker 中,标识符包含空格以及运算符和其他字符在技术上是有效的,否则这些字符在计算引擎中具有功能用途。在这些情况下,标识符通过用“${”和“}”包围来进行转义。虽然解析器成功地将 '${abcdef + 123}' 识别为有效表达式, 我仍然需要能够将“abcdef + 123”识别为有效标识符。当我在第二个单元测试中请求第一个 idEscape 的值时,我得到一个空字符串。 如果相关,我正在使用 ANTLR4.Runtime.Standard。

我做错了什么?任何有助于解决我的误解的帮助将不胜感激。谢谢。

语法

grammar FileMakerCalc;  

// PARSER RULES

calculation :   expr;
expr        :   idEscExpr;
idEscExpr   :   LEFTESCAPE idEscape RIGHTESCAPE;
idEscape    :   (WORD|WS|OPERATOR|INT|FLOAT)*?;


// LEXER RULES

fragment LOWERCASE  : [a-z] ;
fragment UPPERCASE  : [A-Z] ;

LEFTESCAPE  :   '${';
RIGHTESCAPE :   '}';
OPERATOR    :   ('+'|'-'|'*'|'/'|'&'|'^'|'='|'≠'|'<>'|'>'|'<'|'≤'|'<='|'≥'|'>=' );
WORD        :   (LOWERCASE | UPPERCASE)+ ;
FLOAT       :   [0-9]+ '.' [0-9]+;
INT         :   [0-9]+ ;
NEWLINE     :   [\r\n]+ ;
WS          :   [ \t];

访客

public class FileMakerCalcVisitor : FileMakerCalcBaseVisitor<String>
{


    public override string VisitExpr(FileMakerCalcParser.ExprContext context)
    {
        return context.GetText();
    }


    public override string VisitIdEscape(FileMakerCalcParser.IdEscapeContext context)
    {
        return context.GetText();
    }

}

单元测试

namespace Antler_Tests
{
    [TestFixture()]
    public class ParserTest
    {
        private FileMakerCalcParser Setup(string text)
        {
            AntlrInputStream inputStream = new AntlrInputStream(text);
            FileMakerCalcLexer lexer = new FileMakerCalcLexer(inputStream);
            CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
            FileMakerCalcParser parser = new FileMakerCalcParser(commonTokenStream);

            return parser;
        }


        // This one successfully pulls '${abcdef + 123}' as the text of the first expr
        [Test()]
        public void EscapedID_CheckForExpr()
        {
            FileMakerCalcParser parser = Setup("${abcdef + 123}");

            FileMakerCalcParser.ExprContext context = parser.expr();
            FileMakerCalcVisitor visitor = new FileMakerCalcVisitor();

            var testVal = visitor.VisitExpr(context);

            Assert.AreEqual("${abcdef + 123}", testVal, testVal);
        }


        // This one does NOT successfully pull 'abcdef + 123' as the text of the first idEscape
        [Test()]
        public void EscapedID()
        {
            FileMakerCalcParser parser = Setup("${abcdef + 123}");

            FileMakerCalcParser.IdEscapeContext context = parser.idEscape();
            FileMakerCalcVisitor visitor = new FileMakerCalcVisitor();

            var testVal = visitor.VisitIdEscape(context);

            Assert.AreEqual("abcdef + 123", testVal);
        }
    }
}

最佳答案

${abcdef + 123}不是有效的 idEscape因为它以 ${ 开头并以 } 结尾,其中 idEscape 都不是规则接受。你定义它的方式,idEscape只匹配 ${} 之间的内容和idEscapeExpr是与整个事物相匹配的那个。

因此,您希望测试调用 idEscapeExpr规则而不是 idEscape或将您正在解析的字符串更改为 abcdef + 123 (或者每个都进行一次测试)。

关于c# - ANTLR 访问者单元测试在一条规则上成功,但在另一条规则上失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57662062/

相关文章:

c# - 使用 DrawingContext.DrawRectangle 绘制的矩形会阻塞鼠标

c# - 在 C# 中以编程方式读取 VS .coveragexml 文件

c# - TLS 致命 : Handshake Failure

java - 在antlr访问者模式中如何从一种方法导航到另一种方法

java - 在 ANTLR 中,如何根据特定的低级规则解析流?

c# - 强制 Visual Studio 2008 调试器释放可执行文件

parsing - ANTLR4 - '#' 语法错误(替代规则标签)

delphi - 如何使用 ANTLR 生成 Delphi 输出?

antlr - ANTLR 4 规则中的选项发生了什么变化?

java - 是否可以让 Antlr4 从基本语法词法分析器而不是生成词法分析器生成词法分析器?