首页 > 解决方案 > 语法 LaTeX,如混合空格 utf 和命令

问题描述

我试图实现一个类似 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 生成的这个生成树

在此处输入图像描述

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

标签: whitespacegrammarantlr4

解决方案


问题是后面的空格expression

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

这导致模式回到DEFAULT_MODE

CLOSECALLVAR : ' ' -> mode(DEFAULT_MODE) ;

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

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

一个快速的词法分析演示:

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
 ;

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

在此处输入图像描述


推荐阅读