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

时间:2014-03-11 17:31:34

标签: c# parsing antlr4

[解决] 在Edit3下面的底部

我目前正在开发一种新的语法(从我无法改变的某些要求),以下要求带来了问题,我现在无法解决。我正在使用Antlr4和C#目标。

语法如下:

print [blabla ]

因此括号内的所有内容都被视为字符串。所以这也是:

print [3 + 2]

将打印

3 + 2

现在我有lexer规则,显然会将3作为整数匹配。那么如何创建一个解析器规则来解析任何东西直到找到']'?我目前有以下产品:

control
: 
| Print expr
| Print LeftBracket printArg RightBracket
    ;

我面临的问题是左括号并不总是启动一个字符串。有时(例如在while中)条件也在括号中。我想到只接受每个Lexer规则,直到到达RightBracket,然后在我使用生成的解析树时在运行时生成字符串,但在我看来非常烦人,我需要稍后插入空格,这将是困难的。 / p>

如果你需要我语法的更多部分,请在评论中提问,我会向你提供更多细节 亲切的问候

的Lukas

编辑:有关我的语法的更多信息: 以下生产使用括号:

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

EDIT2: 所以我尝试使用这些模式,但是我从它们返回时遇到了问题。这些是关于模式的代码行:

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

mode stringMode;
String : ~']'+;
RightBracketPrint: ']' -> popMode;

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

EDIT3: 接下来我尝试使用一些内联代码并使用lookahead,最终解决了我的问题:

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

mode stringMode;
String : ~']'+;
RightBracketPrint: ']' -> popMode;

2 个答案:

答案 0 :(得分:3)

我首先将括号内的所有内容视为词法分析器中的BracketLiteral

LeftBracket : '[' -> pushMode(BracketLiteralMode);

mode BracketLiteralMode;

  BracketLiteral : ~']'+;
  RightBracket : ']' -> popMode;

在确定如何处理特殊情况之前,我会列举BracketLiteral规则的异常在语法中出现的最后可能性。如果您可以添加这些详细信息,我可以就如何处理这些案例提出一些建议。

答案 1 :(得分:1)

如果我理解正确,在解释括号内容时存在二元性,它可以是字符串或表达式,具体取决于上下文(对于打印,它是一个字符串)。

2可能有风险:

    在lexer级别
  • 检查左括号时的上下文,然后进入字符串模式或常规模式(即表达式)
  • 也是在lexer级别创建一个缓冲区,只要你点击左括号并用下面的文字填充它,使用右括号值(通常它没用)作为通过逐字字符串的车辆

我认为第一种方法更容易,因为在第二种方法中你必须为print内容编写解析规则,这可能无法解析:

print [ a ++++ 2 ]