ANTLR 访客单元测试在一条规则上成功,但在另一条规则上失败



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

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

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

语法

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     :   [rn]+ ;
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(或为每个测试设置一个测试)。

相关内容

  • 没有找到相关文章

最新更新