parsing - 仅在 ANTLR 语法的一部分显式处理换行符

标签 parsing antlr antlr4 lexer

我目前正在为一种旧的类似标记的专有语言开发一个解析器,该语言必须转换为更新的标准。为此,我正在使用 ANTLR 4。

该结构由由特定起始符及其相关终止符分隔的 block 组成(例如 { ... }< ... >INPUT ... END ).在每个 block 中,元素按行指定,以换行符分隔;实际上,只有在某些地方需要这些换行符才能理解代码的含义。

例如:

< ID
SOME_VAR "optional modifier string"
$anEnvironmentVariable
"a constant string"
"another constant" "with its optional modifier"
>

像下面这样的解析器规则

field
  : OPEN_ANGLED_BRACKET row_id
    ((ENVIRONMENT_VAR | DQUOTE_STR | VAR) DQUOTE_STR?)+
    CLOSED_ANGLED_BRACKET
  ;

// [...]

WHITESPACE
  : [ \t\r\n] -> skip
  ;

可以很容易地解析上面的例子,但是因为忽略了换行符,所以它实际上无法区分双引号字符串是常量(意味着它在行的开头)还是修饰符字符串(跟在前一个变量/常量在同一行)。

我实际上可以像这样显式处理换行符:

field
  : OPEN_ANGLED_BRACKET row_id NEWLINE
    ((ENVIRONMENT_VAR | DQUOTE_STR | VAR) DQUOTE_STR? NEWLINE)+
    CLOSED_ANGLED_BRACKET NEWLINE
  ;

// [...]

WHITESPACE
  : [ \t] -> skip
  ;

NEWLINE
  : '\r'? '\n'
  | '\r'
  ;

但是我必须在语法的其余部分处显式处理换行符,这使它变得复杂了很多!

有什么方法可以将明确的换行符限制在有角度的括号内,“自动”在其他任何地方跳过它?

最佳答案

你可以使用 lexical modes这里。您必须定义单独的词法分析器和解析器语法才能使用词法模式。

每当您在词法分析器中遇到 ENVIRONMENT_VARVARDQUOTE_STR(一行中的第一个值)时,您就会更改词法模式.在这个新的词法模式中,你匹配 3 个东西:字符串、空格(你跳过)和换行(你也跳过,在这个标记之后,你改回默认模式)。这一切听起来可能有点含糊,所以这里有一个简短的演示:

文件:MarkupLexer.g4

lexer grammar MarkupLexer;

ENVIRONMENT_VAR       : '$' VAR    -> mode(MODIFIER_MODE);
VAR                   : [a-zA-Z_]+ -> mode(MODIFIER_MODE);
DQUOTE_STR            : STR        -> mode(MODIFIER_MODE);
OPEN_ANGLED_BRACKET   : '<';
CLOSED_ANGLED_BRACKET : '>';
SPACES                : [ \t\r\n] -> skip;

fragment STR : '"' ~["\r\n]* '"';

mode MODIFIER_MODE;

  MODIFIER_MODE_SPACES : [ \t] -> skip;
  MODIFIER_MODE_NL     : [\r\n]+ -> skip, mode(DEFAULT_MODE);
  MODIFIER_MODE_STRING : STR;

解析器看起来像这样:

文件:MarkupParser.g4

parser grammar MarkupParser;

options {
  tokenVocab=MarkupLexer;
}

field
  : OPEN_ANGLED_BRACKET row_id row+ CLOSED_ANGLED_BRACKET
  ;

row
 : (ENVIRONMENT_VAR | DQUOTE_STR | VAR) MODIFIER_MODE_STRING?
 ;

row_id
 : VAR
 ;

当你解析输入时:

< ID
SOME_VAR "optional modifier string"
$anEnvironmentVariable
"a constant string"
"another constant" "with its optional modifier"
>

你会得到如下解析树:

enter image description here

关于parsing - 仅在 ANTLR 语法的一部分显式处理换行符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62478937/

相关文章:

c++ - TinyXML2 C++ - 从旧的/格式不正确的 XML 文件中提取特定数据

c# - 字符串标记的 Antlr 标记定义

ANTLR 4 树注入(inject)/重写运算符

javascript - ANTLR4 Javascript 解析器正则表达式和除法运算符冲突

parsing - 将 WordNet 数据库解析为 SQL?

c++ - C 风格字符串的 boost::spirit::qi 和 qi::alnum 的模板编译错误

c++ - 如何使用 boost split 拆分字符串并忽略空值?

antlr - 如何在antlr中找到 token 的长度?

java - ANTLR - 输入错误不匹配

java - ANTLR4 一个或多个选项的规则*按顺序*