将LeftBracket之后的所有内容解释为字符串,直到下一个RightBracket为止

本文关键字:字符串 下一个 为止 RightBracket 解释 之后 LeftBracket | 更新日期: 2023-09-27 17:49:44

[解决方案]在Edit3 下方的底部

我目前正在开发一种新的语法(根据某些我无法更改的要求(,下面的要求带来了一个问题,我目前无法解决。我正在将Antlr4与C#目标一起使用。

语法如下:

print [blabla ]

因此括号内的所有内容都被视为字符串。还有这个:

print [3 + 2]

将打印

3 + 2

现在我有了lexer规则,它显然会将3作为整数进行匹配。那么,我该如何创建一个解析规则来解析任何内容,直到找到"]"?我目前有以下产品:

control
: 
| Print expr
| Print LeftBracket printArg RightBracket
    ;

我面临的问题是左括号并不总是以字符串开头。有时(如while中(条件也在括号中。我曾想过只接受每个Lexer规则,直到达到RightBracket,然后在运行时使用生成的解析树生成字符串,但在我看来,这很烦人,以后我需要插入空格,这会很困难。

如果你需要我语法的更多部分,请发表评论,我会为你提供更多细节问候

卢卡斯

编辑:关于我的语法的更多信息:以下生产使用支架:

Print LeftBracket printArg RightBracket
Repeat IntegerConstant LeftBracket body RightBracket
While LeftBracket expr RightBracket LeftBracket body RightBracket
If expr LeftBracket body RightBracket LeftBracket body RightBracket
SetPos LeftBracket IntegerConstant IntegerConstant RightBracket

第2版:所以我试着使用这些模式,但在返回时遇到了问题。以下是关于模式的代码行:

mode printMode;
WhitespacePrint
    :   [ 't]+
        -> skip
    ;
LeftBracketPrint : '[' -> popMode, pushMode(stringMode);
NotLeftBracket : ~'[' -> popMode;
mode stringMode;
String : ~']'+;
RightBracketPrint: ']' -> popMode;

我在Printlexer规则上添加了一个pushMode(printMode((匹配关键字(现在解析print[1+2]创建一个包含括号内整个字符串的单个令牌。现在,当我使用print 1+2(应该输出3(时,我得到了一个不可行的替代ar输入"print1"异常,因为"1"的类型是NotLeftBracket。如何在不消耗输入的情况下切换模式?

第3版:接下来,我尝试使用一些内联代码并使用前瞻性,这最终解决了我的问题:

mode printMode;
LeftBracketPrint : [ 't]+ '[' -> popMode, pushMode(stringMode);
WhitespacePrint
    :   [ 't]+ {_input.La(1) != '['}?
        -> skip, popMode
    ;
mode stringMode;
String : ~']'+;
RightBracketPrint: ']' -> popMode;

将LeftBracket之后的所有内容解释为字符串,直到下一个RightBracket为止

我首先将括号内的所有内容都视为lexer中的BracketLiteral

LeftBracket : '[' -> pushMode(BracketLiteralMode);
mode BracketLiteralMode;
  BracketLiteral : ~']'+;
  RightBracket : ']' -> popMode;

在确定如何处理特殊情况之前,我会列举出BracketLiteral规则异常可能出现在语法中的最后一种可能性。如果你能补充这些细节,我将能够就如何处理这些案件提出一些建议。

如果我正确理解,在解释方括号内容时存在对偶性,它要么是字符串,要么是表达式,这取决于上下文(对于打印,它是字符串(。

2种可能的场景:

  • 在lexer级别,当点击左括号时检查上下文,然后进入字符串模式或常规模式(即表达式(
  • 在lexer级别,每当您点击左括号并用以下文本填充时,都会创建一个缓冲区,使用右括号值(通常是无用的(作为传递逐字字符串的工具

我认为第一种方法更容易,因为在第二种方法中,你必须为打印内容编写解析规则,而这可能是不可解析的:

print [ a ++++ 2 ]