whitespace - 语法 LaTeX,如混合空格 utf 和命令
问题描述
我试图实现一个类似 LaTeX 的语法,它可以让我解析这种句子:
\title{Un pré é"'§è" \VAR state \draw( 200\if{expression kjlkjé} ) bis tèr }
如您所见, \title{ } 可以包含多种项目:
utf8 中不带引号和空格的字符串,我想将其保留在一个标记中
变量调用为:\variable_name
一些 \keyword 后跟括号或其他大括号:例如 \draw( utf8 \var \if{ } ...) 或 \if{ idem }。
这些项目可以嵌套。
我从 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
:
\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
;
解析您的示例输入将产生以下解析树:
推荐阅读
- android - 将 swipeRefresh 进度的位置更改为中心
- google-app-engine - GAE - Python 3.7 - 如何记录?
- maven - 为整个团队共享相同的 settings.xml Maven 配置
- c# - DurableOrchestrationClient - 返回一个结果对象
- python - 如何提高python中大数据程序的速度
- php - 如何创建 REST api 发布请求
- svelte - Svelte.js - 如何代理绑定?
- python - WSGI、Flask、Python 2.7、Apache2、ImportError = no modul named flask
- azure - 为 azure mysql 配置静态/公共 ip
- git - 从 TFS 迁移到 GIT 并希望保持同步