语法 LaTeX 喜欢混合空格 utf 和命令

Grammar LaTeX like with mixed whitespace utf and commands

我尝试实现一个类似于 LaTeX 的语法,它可以让我解析这种句子:

\title{Un pré é"'§è" \VAR state \draw( 200\if{expression kjlkjé} ) bis tèr }

如您所见,\title{ } 可以包含多种项目:

这些项目可以嵌套。

我从 ANTLR 4 书中介绍的 XML 解析器中获得灵感并尝试使用模式。我遇到了一个关于识别右括号的右括号的问题。我还遇到了一些空格的问题,例如跟随 \variable_name 的那个(我得到一个:无关输入'')。

这是我的词法分析器语法代码:

 lexer grammar OEFLexer;
    // Default mode rules (the SEA)
    SEA_WS      :   (' '|'\t'|'\r'? '\n')+ ;
    TITLE : '\title';
    OB    : '{';
    OP    : '(';
    BSLASH  : '\'                  -> mode(CALLREFERENCE) ;      
    TEXT  : ~[\({]+;                         // clump all text together 
    // ----------------- Everything Callreference ---------------------
    mode CALLREFERENCE;

    CLOSECALLVAR : ' '          -> mode(DEFAULT_MODE) ; // back to SEA mode 
    CB           : '}'          -> mode(DEFAULT_MODE) ; // back to SEA mode 
    CP           : ')'          -> mode(DEFAULT_MODE) ; // back to SEA mode 

    DRAW    :   'draw' OP;
    IF      :   'if' OB;
    ID      :   [a-zA-Z]+ ;       // match/send ID in tag to parser

这是我的解析器语法

parser grammar OEFParser;
options { tokenVocab=OEFLexer; }

document: TITLE OB ( callreference | string )* CB;

string  : TEXT;
var     : ID;
commandDraw : DRAW ( callreference | string )* CP ;
commandIf   : IF ( callreference | string )* CB ;

callreference : BSLASH ID | BSLASH commandDraw CP | BSLASH commandIf CP;

当我尝试解析开头提到的 \title 代码时,我得到:

line 1:25 extraneous input ' ' expecting {'\', TEXT, '}'}
line 1:37 extraneous input ' ' expecting {'\', TEXT, ')'}
line 1:45 mismatched input 'expression' expecting {'\', TEXT, '}'}
line 1:75 extraneous input '<EOF>' expecting {'\', TEXT, ')'}

用Grun生成的这个生成树

感谢您帮助我解决这个问题。 克里斯

问题是expression之后的space:

\title{Un pré é"'§è" \VAR state \draw( 200\if{expression kjlkjé} ) bis tèr }
                                                        ^
                                                        ^
                                                        ^

这会导致模式返回 DEFAULT_MODE:

CLOSECALLVAR : ' ' -> mode(DEFAULT_MODE) ;

您不想要的东西,因为您(显然)仍处于 CALLREFERENCE 上下文中。

处理此问题的一种方法是使用 -> pushMode(...)-> popMode 指令来创建 CALLREFERENCE 模式堆栈。每当您偶然发现 \... (\... { 时,您都会将新的 CALLREFERENCE 压入此堆栈,然后在看到 )} 时弹出一个。

快速词法分析器语法演示:

lexer grammar OEFLexer;

TITLE   : '\title' S? OB -> pushMode(CALLREFERENCE);

fragment OB : '{';
fragment OP : '(';
fragment S : [ \t\r\n]+;

mode CALLREFERENCE;

  CB       : '}'          -> popMode;
  CP       : ')'          -> popMode;

  DRAW     : '\draw' S? OP -> pushMode(CALLREFERENCE);
  IF       : '\if' S? OB   -> pushMode(CALLREFERENCE);

  BSLASH   : '\';
  ID       : [a-zA-Z]+;
  CR_OTHER : .;

和解析器语法:

parser grammar OEFParser;

options { tokenVocab=OEFLexer; }

document
 : TITLE ( callreference | string )* CB EOF
 ;

string
 : CR_OTHER+
 | ID
 ;

commandDraw
 : DRAW ( callreference | string )* CP
 ;

commandIf
 : IF ( callreference | string )* CB
 ;

callreference
 : BSLASH ID
 | commandDraw
 | commandIf
 ;

解析您的示例输入将产生以下解析树: