从任意纯文本中扩展特定标记 [英] Extracing specific tags from arbitrary plain text

查看:131
本文介绍了从任意纯文本中扩展特定标记的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想分析纯文本的意见和查找在其中某些标记。该类型的标签我在寻找的样子:

I want to parse plain text comments and look for certain tags within them. The types of tags I'm looking for look like:

<name#1234>



其中,名是一个[AZ]字符串(从固定列表)和1234代表一个[0-9] +号。这些标签可以在字符串中出现零次或更多次和任意其他文字所包围。例如,以下字符串都是有效的:

Where "name" is a [a-z] string (from a fixed list) and "1234" represents a [0-9]+ number. These tags can occur within a string zero or more times and be surrounded by arbitrary other text. For example, the following strings are all valid:

"Hello <foo#56> world!"
"<bar#1>!"
"1 &lt; 2"
"+<baz#99>+<squid#0> and also<baz#99>.\n\nBy the way, maybe <foo#9876>"



以下字符串均无效:

The following strings are all NOT valid:

"1 < 2"
"<foo>"
"<bar#>"
"Hello <notinfixedlist#1234>"

由于notinfixedlist不是支持的命名标识符最后一个是无效的。

The last one isn't valid because "notinfixedlist" isn't a supported named identifier.

我可以轻松地分析这个使用简单的regex,例如(我省略为简单起见命名组):

I can easily parse this using simple regex, for example (I'm omitting named groups for simplicity sake):

<[a-z]+#\d+>

或直接指定一个固定的列表:

or specifying a fixed list directly:

<(foo|bar|baz|squid)#\d+>



但我想用ANTLR的几个原因:

but I'd like to use antlr for a few reasons:


  • 我要什么,不匹配的格式导致分析错误,因此,如果文本包含<或>,但不匹配模式,它失败。这些字符必须被转义为&放大器; LT;和与& gt;中。分别,如果它不是一个标签

  • 我可能会在将来扩展这个以支持其他类型的模式(例如:{富+ 666}或[[@ 1234]]并且想避免正则表达式语句爆炸。有一个单一的语法文件我可以扩展将是巨大的。

  • 我喜欢antlr4实现访问者模式,我的代码被称为事实上,当特定类型的变量中遇到的而不是砍一起变化的正则表达式。

我如何实现这样使用antlr4语法?大多数我见过的例子是其遵循的整个文本确切规则的语言,而我只想语法应用到任意的文本中匹配模式。

How do I implement such a grammar using antlr4? Most of the examples I've seen are for languages which follow exact rules for the entire text, whereas I only want the grammar to apply to matching patterns within arbitrary text.

我想出了这一点,我相信这是正确的:

I've come up with this, which I believe is correct:

grammar Tags;

parse 
    : ( tag | text )*
    ;

tag 
    : '<' fixedlist '#' ID '>'
    ;

fixedlist 
    : 'foo' 
    | 'bar' 
    | 'baz' 
    | 'squid';

text 
    : ~('<' | '>')+
    ;

ID
    : [0-9]+
    ;



这是正确的?

Is this correct?

推荐答案

在一般来讲,所确定的问题是通常所述的海岛语法问题 - 在那里一个否则单数文档的部分通过两个或更多的不同,常常相互暧昧,规范描述

In general terms, the problem identified is typically described an island grammar problem - where sections of an otherwise singular document are described by two or more different, often mutually ambiguous, specifications.

4 ANTLR通过使用模式取值直接支持海岛语法。注意,模式只适用于分词法/语法分析器文法用。

ANTLR 4 directly supports island grammars through use of modes. Note, modes are only available in split lexer/parser grammars.

分析器

parser grammar TagsParser ;

options {
    tokenVocab = TagsLexer ;
}

parse   : ( tag | text )* EOF ;
tag     : LANGLE fixedlist GRIDLET ID RANGLE ;
text    : . ;
fixedlist
    : FOO
    | BAR
    | BAZ
    | SQUID
    ;



词法分析器

The lexer

lexer grammar TagsLexer ;

LANGLE  : '<' -> pushMode(tag) ;
TEXT    : . ;

mode tag ;
    RANGLE  : '>' -> popMode ;

    FOO     : 'foo' ;
    BAR     : 'bar' ;
    BAZ     : 'baz' ;
    SQUID   : 'squid' ;
    GRIDLET : '#' ;
    ID      : [0-9]+ ;

    NONTAG  : . -> popMode ;

在解析器文本规则将匹配所有标记以前没有它上面的语法规则消耗。这将包括所有的文本令牌以及碰巧被标记模式规则匹配,但不是一个标签的有效组成部分的任何文字。

The text rule in the parser will match all tokens not previously consumed by the parser rules above it. This will include all TEXT tokens as well as any text that happens to be matched by a tag mode rule but is not validly part of a tag.

这篇关于从任意纯文本中扩展特定标记的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆