我试图实现像LaTeX这样的语法,可以让我解析这种句子:
\title{Un pré é"'§è" \VAR state \draw( 200\if{expression kjlkjé} ) bis tèr }
如您所见,\ title {}可以包含多种项目:
字符串(不带引号和空格),我想 保留一个令牌
变量调用为:\ variable_name
一些\关键字后跟括号或其他带有花括号的关键字:例如\ draw(utf8 \ var \ if {} ...)或\ if {idem}。
这些项目可以嵌套。
我从ANTLR 4书中介绍的XML解析器中得到启发,并尝试使用模式。我遇到一个有关识别圆括号的大括号的问题。我也遇到了一些空格问题,例如遵循\ variable_name的空格(我得到了:无关输入'')。
这是我的lexer gramar代码:
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生成的此生成树
感谢您的帮助,以帮助我解决此问题。 克里斯
答案 0 :(得分:1)
问题是expression
后的空格:
\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
;
解析您的示例输入将产生以下解析树: