如何获取从默认通道和隐藏通道读取的Antlr解析器规则
我在隐藏通道中使用了正常的空格分隔,但是我有一个规则,我希望在后面的处理中包含任何空格,但是我发现的任何示例都需要一些非常奇怪的手动编码 没有一个简单的选项可以从多个通道读取,比如从一开始就把空白放在那里 这是空格lexer规则如何获取从默认通道和隐藏通道读取的Antlr解析器规则,antlr,antlr3,lexer,parser-generator,Antlr,Antlr3,Lexer,Parser Generator,我在隐藏通道中使用了正常的空格分隔,但是我有一个规则,我希望在后面的处理中包含任何空格,但是我发现的任何示例都需要一些非常奇怪的手动编码 没有一个简单的选项可以从多个通道读取,比如从一开始就把空白放在那里 这是空格lexer规则 WS : ( ' ' | '\t' | '\r' | '\n' ) {$channel=HIDDEN;} ; 这是我的规则,我想包括空格 raw : '{'? (~('{'))*; 基
WS : ( ' '
| '\t'
| '\r'
| '\n'
) {$channel=HIDDEN;}
;
这是我的规则,我想包括空格
raw : '{'? (~('{'))*;
基本上,它是一个“一网打尽”的规则,用于捕获与其他模式处理的其他规则不匹配的任何内容,因此我需要原始流
我希望有一个{$channel==DEFAULT | |$channel==HIDDEN}
语法示例,但找不到任何语法示例
我的目标是C#,但如果需要,我可以重写Java示例。AFAIK,这是不可能的。但是,您可以扩展
无缓冲的TokenStream
,以在解析期间更改通道。您不能使用CommonTokenStream
,因为它缓冲了可变数量的令牌(并且缓冲区中可能有位于错误通道上的令牌!)。请注意,您至少需要ANTLR 3.3:在以前的版本中,未缓冲的TokenStream
尚未包括在内
假设您想要解析(并显示)小写或大写字母。大写字母放在隐藏的通道上,因此通过deafult,只解析小写字母。然而,当解析器偶然发现小写的“q”
时,我们希望切换到隐藏的通道。一旦对隐藏的频道进行解析,我们希望的“Q”
再次将我们带回默认频道
因此,在解析源代码时,首先打印“a”
,“b”
和“c”
,然后更改频道,然后打印“c”
和“D”
,然后再次更改频道,最后将“e”
打印到控制台
下面是一个ANTLR语法,它可以做到这一点:
ChannelDemo.g
下面是自定义令牌流类:
ChangeableChannelTokenStream.java
还有一个小的主类来测试这一切:
主类
最后,生成一个lexer/parser(1),编译所有源文件(2)并运行主类(3):
1.
根据上述语法生成的解析器将在遇到“*”
时启用从所有通道读取。因此,在解析“aAbB*cCdDeE”时:
将打印以下内容:
a
b
c
C
d
D
e
E
A.
B
C
C
D
D
E
E
也许你应该考虑把空白当作你的Gracar的一部分。但是为什么要用这些不重要的信息把你的gramar搞得乱七八糟呢?嗯,因为这不是不重要的。这条新线在某些情况下有意义。当您需要IDE支持时,例如从visual studio语言服务器获得IDE支持时,您需要指定一个语言语法,而不需要低级别ANTLR定制的所有细节。在Antler 4
中,我使用的是一个简单的解决方案。我没有在antlr3
中测试它。它是C#,但您可以轻松地将其转换为Java
将parser1.g4更改为下一步:
parser grammar Parser1;
options { tokenVocab=Lexer1; }
startRule
@init { SetWhiteSpacesAcceptence(false); }
: (componentWithWhiteSpaces | componentWithoutWhiteSpaces)* EOF
;
componentWithWhiteSpaces : { SetWhiteSpacesAcceptence(true); }
component1 component2 component3
{ SetWhiteSpacesAcceptence(false); }
;
componentWithoutWhiteSpaces : component4 component5 component6
lexer grammar Lexer1;
WS : [ \t\r\n] { if( this.IsWhiteSpacesAccepted() ) Skip(); };
将lexer1.g4更改为下一步:
parser grammar Parser1;
options { tokenVocab=Lexer1; }
startRule
@init { SetWhiteSpacesAcceptence(false); }
: (componentWithWhiteSpaces | componentWithoutWhiteSpaces)* EOF
;
componentWithWhiteSpaces : { SetWhiteSpacesAcceptence(true); }
component1 component2 component3
{ SetWhiteSpacesAcceptence(false); }
;
componentWithoutWhiteSpaces : component4 component5 component6
lexer grammar Lexer1;
WS : [ \t\r\n] { if( this.IsWhiteSpacesAccepted() ) Skip(); };
将Parser1
类扩展为下一个:
class MyParser : Parser1
{
public void SetWhiteSpacesAcceptence(bool isAccept)
{
if (_input != null && _input.TokenSource != null)
{
if (_input.TokenSource is MyLexer)
{
MyLexer lexer = _input.TokenSource as MyLexer;
if (lexer != null)
lexer.SetWhiteSpacesAcceptence(isAccept);
}
}
}
public bool IsWhiteSpacesAccepted()
{
if (_input != null && _input.TokenSource != null)
{
if (_input.TokenSource is MyLexer)
{
MyLexer lexer = _input.TokenSource as MyLexer;
if (lexer != null)
return lexer.IsWhiteSpacesAccepted();
}
}
return false;
}
}
class MyLexer : Lexer1
{
private bool isWhiteSpacesAccepted;
public void SetWhiteSpacesAcceptence(bool isAccept) { isWhiteSpacesAccepted = isAccept }
public bool IsWhiteSpacesAccepted() { return isWhiteSpacesAccepted; }
}
将Lexer1
类扩展为下一个:
class MyParser : Parser1
{
public void SetWhiteSpacesAcceptence(bool isAccept)
{
if (_input != null && _input.TokenSource != null)
{
if (_input.TokenSource is MyLexer)
{
MyLexer lexer = _input.TokenSource as MyLexer;
if (lexer != null)
lexer.SetWhiteSpacesAcceptence(isAccept);
}
}
}
public bool IsWhiteSpacesAccepted()
{
if (_input != null && _input.TokenSource != null)
{
if (_input.TokenSource is MyLexer)
{
MyLexer lexer = _input.TokenSource as MyLexer;
if (lexer != null)
return lexer.IsWhiteSpacesAccepted();
}
}
return false;
}
}
class MyLexer : Lexer1
{
private bool isWhiteSpacesAccepted;
public void SetWhiteSpacesAcceptence(bool isAccept) { isWhiteSpacesAccepted = isAccept }
public bool IsWhiteSpacesAccepted() { return isWhiteSpacesAccepted; }
}
现在,Main
功能如下:
static void Main()
{
AntlrFileStream input = new AntlrFileStream("pathToInputFile");
MyLexer lexer = new MyLexer(input);
UnbufferedTokenStream tokens = new UnbufferedTokenStream(lexer);
MyParser parser = new MyParser(tokens);
parser.startRule();
}
我将尝试从任何通道读取解决方案,因为这正是我想要的:)在使用AntlrWorks进行开发时,是否可以在.g文件中包含该类,而不必在外部编译和运行?如何在C#中实现?在Antlr.Runtime或Antlr.Runtime中没有“UnbufferedTokenStream”。Misc@Tizz,我不知道,不幸的是,C#不是我的强项。@BartKiers和Java不是我的强项。嗯,这里有一些好的方面,我希望我能翻译,但进展不太顺利。谢谢你的回答,我自己使用C语言,但我放弃了Antler,转而使用手工编码的lexel/解析器,部分原因是Antler在一段时间内与C语言目标有太多问题,但也因为Antler在我们的“语言”中遇到了问题嵌入在原始文本中,如html或javascript。Antler(或者至少据我所知)最适合于更严格的语法。
a
b
c
C
d
D
e
E
parser grammar Parser1;
options { tokenVocab=Lexer1; }
startRule
@init { SetWhiteSpacesAcceptence(false); }
: (componentWithWhiteSpaces | componentWithoutWhiteSpaces)* EOF
;
componentWithWhiteSpaces : { SetWhiteSpacesAcceptence(true); }
component1 component2 component3
{ SetWhiteSpacesAcceptence(false); }
;
componentWithoutWhiteSpaces : component4 component5 component6
lexer grammar Lexer1;
WS : [ \t\r\n] { if( this.IsWhiteSpacesAccepted() ) Skip(); };
class MyParser : Parser1
{
public void SetWhiteSpacesAcceptence(bool isAccept)
{
if (_input != null && _input.TokenSource != null)
{
if (_input.TokenSource is MyLexer)
{
MyLexer lexer = _input.TokenSource as MyLexer;
if (lexer != null)
lexer.SetWhiteSpacesAcceptence(isAccept);
}
}
}
public bool IsWhiteSpacesAccepted()
{
if (_input != null && _input.TokenSource != null)
{
if (_input.TokenSource is MyLexer)
{
MyLexer lexer = _input.TokenSource as MyLexer;
if (lexer != null)
return lexer.IsWhiteSpacesAccepted();
}
}
return false;
}
}
class MyLexer : Lexer1
{
private bool isWhiteSpacesAccepted;
public void SetWhiteSpacesAcceptence(bool isAccept) { isWhiteSpacesAccepted = isAccept }
public bool IsWhiteSpacesAccepted() { return isWhiteSpacesAccepted; }
}
static void Main()
{
AntlrFileStream input = new AntlrFileStream("pathToInputFile");
MyLexer lexer = new MyLexer(input);
UnbufferedTokenStream tokens = new UnbufferedTokenStream(lexer);
MyParser parser = new MyParser(tokens);
parser.startRule();
}