- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
大家好,
这可能是这个问题的后续:Antlr rule priorities
我正在尝试为 reStructuredText markup language 编写 ANTLR 语法.
我面临的主要问题是:“如何在不掩盖其他语法规则的情况下匹配任何字符序列(常规文本)?”
让我们以带有内联标记的段落为例:
In `Figure 17-6`_, we have positioned ``before_ptr`` so that it points to the element
*before* the insert point. The variable ``after_ptr`` points to the element *after* the
insert. In other words, we are going to put our new element **in between** ``before_ptr``
and ``after_ptr``.
我认为编写内联标记文本的规则会很容易。所以我写了一个简单的语法:
grammar Rst;
options {
output=AST;
language=Java;
backtrack=true;
//memoize=true;
}
@members {
boolean inInlineMarkup = false;
}
// PARSER
text
: inline_markup (WS? inline_markup)* WS? EOF
;
inline_markup
@after {
inInlineMarkup = false;
}
: {!inInlineMarkup}? (emphasis|strong|litteral|link)
;
emphasis
@init {
inInlineMarkup = true;
}
: '*' (~'*')+ '*' {System.out.println("emphasis: " + $text);}
;
strong
@init {
inInlineMarkup = true;
}
: '**' (~'*')+ '**' {System.out.println("bold: " + $text);}
;
litteral
@init {
inInlineMarkup = true;
}
: '``' (~'`')+ '``' {System.out.println("litteral: " + $text);}
;
link
@init {
inInlineMarkup = true;
}
: inline_internal_target
| footnote_reference
| hyperlink_reference
;
inline_internal_target
: '_`' (~'`')+ '`' {System.out.println("inline_internal_target: " + $text);}
;
footnote_reference
: '[' (~']')+ ']_' {System.out.println("footnote_reference: " + $text);}
;
hyperlink_reference
: ~(' '|'\t'|'\u000C'|'_')+ '_' {System.out.println("hyperlink_reference: " + $text);}
| '`' (~'`')+ '`_' {System.out.println("hyperlink_reference (long): " + $text);}
;
// LEXER
WS
: (' '|'\t'|'\u000C')+
;
NEWLINE
: '\r'? '\n'
;
这个简单的语法不起作用。我什至没有尝试匹配常规文本...
我的问题:
预先感谢您的帮助:-)
罗宾
<小时/>非常感谢您的帮助!我会很难找出我的错误...我编写该语法(仅)不是为了学习 ANTLR,我正在尝试为 eclipse 编写一个 IDE 插件。为此,我需要语法;)
我设法在语法上更进一步,并编写了一个 text
规则:
grammar Rst;
options {
output=AST;
language=Java;
}
@members {
boolean inInlineMarkup = false;
}
//////////////////
// PARSER RULES //
//////////////////
file
: line* EOF
;
line
: text* NEWLINE
;
text
: inline_markup
| normal_text
;
inline_markup
@after {
inInlineMarkup = false;
}
: {!inInlineMarkup}? {inInlineMarkup = true;}
(
| STRONG
| EMPHASIS
| LITTERAL
| INTERPRETED_TEXT
| SUBSTITUTION_REFERENCE
| link
)
;
link
: INLINE_INTERNAL_TARGET
| FOOTNOTE_REFERENCE
| HYPERLINK_REFERENCE
;
normal_text
: {!inInlineMarkup}?
~(EMPHASIS
|SUBSTITUTION_REFERENCE
|STRONG
|LITTERAL
|INTERPRETED_TEXT
|INLINE_INTERNAL_TARGET
|FOOTNOTE_REFERENCE
|HYPERLINK_REFERENCE
|NEWLINE
)
;
//////////////////
// LEXER TOKENS //
//////////////////
EMPHASIS
: STAR ANY_BUT_STAR+ STAR {System.out.println("EMPHASIS: " + $text);}
;
SUBSTITUTION_REFERENCE
: PIPE ANY_BUT_PIPE+ PIPE {System.out.println("SUBST_REF: " + $text);}
;
STRONG
: STAR STAR ANY_BUT_STAR+ STAR STAR {System.out.println("STRONG: " + $text);}
;
LITTERAL
: BACKTICK BACKTICK ANY_BUT_BACKTICK+ BACKTICK BACKTICK {System.out.println("LITTERAL: " + $text);}
;
INTERPRETED_TEXT
: BACKTICK ANY_BUT_BACKTICK+ BACKTICK {System.out.println("LITTERAL: " + $text);}
;
INLINE_INTERNAL_TARGET
: UNDERSCORE BACKTICK ANY_BUT_BACKTICK+ BACKTICK {System.out.println("INLINE_INTERNAL_TARGET: " + $text);}
;
FOOTNOTE_REFERENCE
: L_BRACKET ANY_BUT_BRACKET+ R_BRACKET UNDERSCORE {System.out.println("FOOTNOTE_REFERENCE: " + $text);}
;
HYPERLINK_REFERENCE
: BACKTICK ANY_BUT_BACKTICK+ BACKTICK UNDERSCORE {System.out.println("HYPERLINK_REFERENCE (long): " + $text);}
| ANY_BUT_ENDLINK+ UNDERSCORE {System.out.println("HYPERLINK_REFERENCE (short): " + $text);}
;
WS
: (' '|'\t')+ {$channel=HIDDEN;}
;
NEWLINE
: '\r'? '\n' {$channel=HIDDEN;}
;
///////////////
// FRAGMENTS //
///////////////
fragment ANY_BUT_PIPE
: ESC PIPE
| ~(PIPE|'\n'|'\r')
;
fragment ANY_BUT_BRACKET
: ESC R_BRACKET
| ~(R_BRACKET|'\n'|'\r')
;
fragment ANY_BUT_STAR
: ESC STAR
| ~(STAR|'\n'|'\r')
;
fragment ANY_BUT_BACKTICK
: ESC BACKTICK
| ~(BACKTICK|'\n'|'\r')
;
fragment ANY_BUT_ENDLINK
: ~(UNDERSCORE|' '|'\t'|'\n'|'\r')
;
fragment ESC
: '\\'
;
fragment STAR
: '*'
;
fragment BACKTICK
: '`'
;
fragment PIPE
: '|'
;
fragment L_BRACKET
: '['
;
fragment R_BRACKET
: ']'
;
fragment UNDERSCORE
: '_'
;
语法对于 inline_markup 工作正常,但 normal_text 不匹配。
这是我的测试类:
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.Tree;
public class Test {
public static void main(String[] args) throws RecognitionException, IOException {
InputStream is = Test.class.getResourceAsStream("test.rst");
Reader r = new InputStreamReader(is);
StringBuilder source = new StringBuilder();
char[] buffer = new char[1024];
int readLenght = 0;
while ((readLenght = r.read(buffer)) > 0) {
if (readLenght < buffer.length) {
source.append(buffer, 0, readLenght);
} else {
source.append(buffer);
}
}
r.close();
System.out.println(source.toString());
ANTLRStringStream in = new ANTLRStringStream(source.toString());
RstLexer lexer = new RstLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
RstParser parser = new RstParser(tokens);
RstParser.file_return out = parser.file();
System.out.println(((Tree)out.getTree()).toStringTree());
}
}
我使用的输入文件:
In `Figure 17-6`_, we have positioned ``before_ptr`` so that it points to the element
*before* the insert point. The variable ``after_ptr`` points to the |element| *after* the
insert. In other words, `we are going`_ to put_ our new element **in between** ``before_ptr``
and ``after_ptr``.
我得到这个输出:
HYPERLINK_REFERENCE (short): 7-6`_
line 1:2 mismatched character ' ' expecting '_'
line 1:10 mismatched character ' ' expecting '_'
line 1:18 mismatched character ' ' expecting '_'
line 1:21 mismatched character ' ' expecting '_'
line 1:26 mismatched character ' ' expecting '_'
line 1:37 mismatched character ' ' expecting '_'
LITTERAL: `before_ptr`
line 1:86 no viable alternative at character '\r'
line 1:55 mismatched character ' ' expecting '_'
line 1:60 mismatched character ' ' expecting '_'
line 1:63 mismatched character ' ' expecting '_'
line 1:70 mismatched character ' ' expecting '_'
line 1:73 mismatched character ' ' expecting '_'
line 1:77 mismatched character ' ' expecting '_'
line 1:85 mismatched character ' ' expecting '_'
EMPHASIS: *before*
line 2:12 mismatched character ' ' expecting '_'
line 2:19 mismatched character ' ' expecting '_'
line 2:26 mismatched character ' ' expecting '_'
LITTERAL: `after_ptr`
line 2:30 mismatched character ' ' expecting '_'
line 2:39 mismatched character ' ' expecting '_'
line 2:90 no viable alternative at character '\r'
line 2:60 mismatched character ' ' expecting '_'
line 2:63 mismatched character ' ' expecting '_'
line 2:67 mismatched character ' ' expecting '_'
line 2:77 mismatched character ' ' expecting '_'
line 2:85 mismatched character ' ' expecting '_'
line 2:89 mismatched character ' ' expecting '_'
line 3:7 mismatched character ' ' expecting '_'
line 3:10 mismatched character ' ' expecting '_'
line 3:16 mismatched character ' ' expecting '_'
line 3:23 mismatched character ' ' expecting '_'
line 3:27 mismatched character ' ' expecting '_'
line 3:31 mismatched character ' ' expecting '_'
line 3:42 mismatched character ' ' expecting '_'
line 3:51 mismatched character ' ' expecting '_'
line 3:55 mismatched character ' ' expecting '_'
line 3:63 mismatched character ' ' expecting '_'
line 3:94 mismatched character '\r' expecting '*'
line 4:3 mismatched character ' ' expecting '_'
line 4:18 no viable alternative at character '\r'
line 4:18 mismatched character '\r' expecting '_'
HYPERLINK_REFERENCE (short): oing`_
HYPERLINK_REFERENCE (short): ut_
EMPHASIS: *in between*
LITTERAL: `after_ptr`
BR.recoverFromMismatchedToken
line 0:-1 mismatched input '<EOF>' expecting NEWLINE
null
你能指出我的错误吗? (当我将 filter=true; 选项添加到语法中时,解析器适用于内联标记,不会出现错误)
罗宾
最佳答案
这是一个快速演示,您可以如何解析此 reStructuredText。请注意,它只处理一小部分可用的标记语法,通过添加更多标记语法,您将影响现有的解析器/词法分析器规则:所以有很多,很多还有更多工作要做!
grammar RST;
options {
output=AST;
backtrack=true;
memoize=true;
}
tokens {
ROOT;
PARAGRAPH;
INDENTATION;
LINE;
WORD;
BOLD;
ITALIC;
INTERPRETED_TEXT;
INLINE_LITERAL;
REFERENCE;
}
parse
: paragraph+ EOF -> ^(ROOT paragraph+)
;
paragraph
: line+ -> ^(PARAGRAPH line+)
| Space* LineBreak -> /* omit line-breaks between paragraphs from AST */
;
line
: indentation text+ LineBreak -> ^(LINE text+)
;
indentation
: Space* -> ^(INDENTATION Space*)
;
text
: styledText
| interpretedText
| inlineLiteral
| reference
| Space
| Star
| EscapeSequence
| Any
;
styledText
: bold
| italic
;
bold
: Star Star boldAtom+ Star Star -> ^(BOLD boldAtom+)
;
italic
: Star italicAtom+ Star -> ^(ITALIC italicAtom+)
;
boldAtom
: ~(Star | LineBreak)
| italic
;
italicAtom
: ~(Star | LineBreak)
| bold
;
interpretedText
: BackTick interpretedTextAtoms BackTick -> ^(INTERPRETED_TEXT interpretedTextAtoms)
;
interpretedTextAtoms
: ~BackTick+
;
inlineLiteral
: BackTick BackTick inlineLiteralAtoms BackTick BackTick -> ^(INLINE_LITERAL inlineLiteralAtoms)
;
inlineLiteralAtoms
: inlineLiteralAtom+
;
inlineLiteralAtom
: ~BackTick
| BackTick ~BackTick
;
reference
: Any+ UnderScore -> ^(REFERENCE Any+)
;
UnderScore
: '_'
;
BackTick
: '`'
;
Star
: '*'
;
Space
: ' '
| '\t'
;
EscapeSequence
: '\\' ('\\' | '*')
;
LineBreak
: '\r'? '\n'
| '\r'
;
Any
: .
;
当您从上面生成解析器和词法分析器时,并让它解析以下输入文件:
***x*** **yyy** *zz* *a b cP2 ``*a*`b`` `q`Python_
(note the trailing line break!)
the parser will produce the following AST:
The graph can be created by running this class:
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;
public class Main {
public static void main(String[] args) throws Exception {
String source =
"***x*** **yyy** *zz* *\n" +
"a b c\n" +
"\n" +
"P2 ``*a*`b`` `q`\n" +
"Python_\n";
RSTLexer lexer = new RSTLexer(new ANTLRStringStream(source));
RSTParser parser = new RSTParser(new CommonTokenStream(lexer));
CommonTree tree = (CommonTree)parser.parse().getTree();
DOTTreeGenerator gen = new DOTTreeGenerator();
StringTemplate st = gen.toDOT(tree);
System.out.println(st);
}
}
或者如果您的源来自文件,请执行以下操作:
RSTLexer lexer = new RSTLexer(new ANTLRFileStream("test.rst"));
或
RSTLexer lexer = new RSTLexer(new ANTLRFileStream("test.rst", "???"));
其中 "???"
是文件的编码。
上面的类会将 AST 作为 DOT 文件打印到控制台。您可以使用 DOT 查看器来显示 AST。在本例中,我发布了由 kgraphviewer 创建的图像。但有many more viewers around 。一个不错的在线是 this one ,它似乎正在使用 kgraphviewer在“引擎盖”下。祝你好运!
关于reStructuredText 的 ANTLR 语法(规则优先级),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6178546/
让我们考虑以下 ANTLR4 语法(最小示例): grammar Foo; expr : a? b? c? ; 我如何指定 a、b 或 c 中的至少一个 必须出现在表达式? 基本上我正在寻
我为字符串变量声明写了下面的语法。字符串的定义类似于单引号之间的任何内容,但必须有一种方法可以通过使用 $ 字母转义将单引号添加到字符串值。 grammar test; options {
我最近创建了一个 ANTLR3 解析器规则 options : foo bar; 它没有编译,我花了一些时间才发现 options是一个保留字(AntlrWorks 指出了错误,但没有指出原因)。 A
我正在从“The Definitive Antlr reference”一书中学习 Antlr。我还处于起步阶段。我喜欢动手做东西,所以我认为做一个好的示例项目会是一个很好的学习经验。 我正在寻找一个
我们有一个为 antlr V2 编写的语法,我想迁移到 antlr v4。有迁移指南吗?我还想知道对现有 V2 语法的修改,以便我们更好地利用 v4 功能。 最佳答案 我通过编写一个新的 Antlr
介绍 查看文档,ANTLR 2 曾经有一个叫做 predicated lexing 的东西。 ,有这样的例子(受 Pascal 启发): RANGE_OR_INT : ( INT ".."
我已经开始学习 ANTLR,并且拥有 2007 年的书《The Definitive ANTLR Reference》和 ANTLRWorks(用于创建语法的交互式工具)。而且,作为这样的人,我从第三
我正在开发 D 语言的解析器,当我尝试添加“切片”运算符规则时遇到了麻烦。你可以找到它的ANTLR语法here 。基本上问题是,如果词法分析器遇到这样的字符串:“1..2”,它就会完全丢失,并且最终成
在 ANTLR 语法中,我们如何区分变量名和标识符? VAR: ('A'..'Z')+ DIGIT* ; IDENT : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'
我想在 ANTLR 语法中解析 ISO 8601 日期。 2001-05-03 我的语法文件中有以下条目: date : FOUR_DIGIT ('-')? TWO_DIGIT ('-')? T
我们有一个为 antlr V3 编写的语法,我想迁移到 antlr v4。有没有迁移指南。我还想知道对现有 V3 语法的修改,以便我们很好地利用 v4 的功能。 最佳答案 如果您在 v3 或更早版本中
我正在尝试在一台新计算机上使用 ANTLR v4 语法插件在 IntelliJ 中运行一个简单的语法文件。我已经按照在线步骤在 IntelliJ 中安装插件,插件看起来安装正确。我在 .g4 语法文件
我正在使用 ANTLR 为旧的专有报告规范编写一个解析器,目前我正在尝试实现生成的解析树的访问者,以扩展自动生成的抽象访问类。 我对 ANTLR(我最近才学会)和一般的访问者模式都没有什么经验,但是如
我知道插入符号后缀在 antlr 中的含义(即 make root)但是当插入符号是我一直在阅读的以下语法中的前缀时呢(该语法是全新的,由学习 antlr 的新团队完成)。 .. selectClau
我不知道这个问题是否有效,因为我对源代码解析不是很熟悉。我的目标是为一种现有的编程语言(语言“X”)编写一个源代码完成函数,以供学习之用。 Antlr(v4) 是否适合这样的任务,还是应该手动完成必要
请查看源代码:https://gist.github.com/1684022 . 我定义了两个 token : ID : ('a'..'z' | 'A'..'Z') ('0'..'9' | 'a
我知道“+”、“?”和 '*'。但是,如果我希望某事重复 5 次,该怎么办?例如,如果标识符必须是长度为 5 的十六进制数字符串? 更具体地说,我正在考虑定义一个无限长度的通用词法分析器规则,然后在解
如何控制切换Antlr来自解析器操作的词法分析器模式? 我扩展了生成的 Parser 和 Lexer,所以我可以调用 pushMode和 popMode从解析器女巫依次调用合适的pushMode和 p
我正在使用 ANTLR 来标记一个简单的语法,并且需要区分一个 ID: ID : LETTER (LETTER | DIGIT)* ; fragment DIGIT : '
我有一个这样的 ANTLR 规则 receive returns[Evaluator e,String message] : RECEIVE FILENAME {$e= new ReceiveEv
我是一名优秀的程序员,十分优秀!