ANTLR:从不同语法调用规则
是否可以从不同的语法调用规则ANTLR:从不同语法调用规则,antlr,grammar,modularity,rule,Antlr,Grammar,Modularity,Rule,是否可以从不同的语法调用规则 目的是在同一个文件中有两种语言,第二种语言以(begin…)开头,其中。。。英语是第二语言。语法应该调用另一个语法来解析第二种语言 例如: grammar A; start_rule : '(' 'begin' B.program ')' //or something like that ; 你的问题可以(至少)用两种方式来解释: 将大语法中的规则分成不同的语法 在“主”语言(孤岛语法)中解析单独的语言 我想这是第一次,在这种情况下,你
目的是在同一个文件中有两种语言,第二种语言以(begin…)开头,其中。。。英语是第二语言。语法应该调用另一个语法来解析第二种语言 例如:
grammar A;
start_rule
: '(' 'begin' B.program ')' //or something like that
;
你的问题可以(至少)用两种方式来解释:
lexer语法L;
数字
: '0'..'9'
;
档案:Sub.g
parser语法子;
数
:位数+
;
文件:Root.g
语法根;
进口分包;
作语法分析
:number EOF{System.out.println(“已解析:+$number.text);}
;
文件:Main.java
import org.antlr.runtime.*;
公共班机{
公共静态void main(字符串[]args)引发异常{
L lexer=新的L(新的AntlStringStream(“42”);
CommonTokenStream令牌=新的CommonTokenStream(lexer);
RootParser=新的RootParser(令牌);
parser.parse();
}
}
运行演示:
bart@hades:~/Programming/ANTLR/Demos/Composite$java-cp ANTLR-3.3.jar org.ANTLR.Tool L.g
bart@hades:~/Programming/ANTLR/Demos/Composite$java-cp ANTLR-3.3.jar org.ANTLR.Tool Root.g
bart@hades:~/Programming/ANTLR/Demos/Composite$javac-cp ANTLR-3.3.jar*.java
bart@hades:~/Programming/ANTLR/Demos/Composite$java-cp.:ANTLR-3.3.jar Main
将打印:
Parsed:42
到控制台
更多信息,请参阅:
选项2的演示:
语言内部语言的一个很好的例子是regex。您有一种带有元字符的“普通”正则表达式语言,但其中还有另一种:描述字符集(或字符类)的语言
<>而不是在ReX语法中对字符集(范围<代码> ->代码>、否定<代码> ^ /代码>等)的元字符进行计算,您可以简单地将字符集看作是一个由“<代码> [< /代码>,然后所有到和包括<代码> > /代码>(可能有<代码> \>代码>)组成的单个令牌。在你的正则表达式语法里面。然后,当您在一个解析器规则中偶然发现CharSet
标记时,您将调用CharSet解析器
文件:Regex.g
语法正则表达式;
选项{
输出=AST;
}
代币{
正则表达式;
原子;
字符集;
INT;
组;
目录
}
@成员{
公共静态CommonTree ast(字符串源)引发识别异常{
RegexLexer lexer=newregexlexer(newantlrstringstream(source));
RegexParser parser=newregexparser(newcommontokenstream(lexer));
return(CommonTree)parser.parse().getTree();
}
}
作语法分析
:atom+EOF->^(REGEX-atom+)
;
原子
:组量词?->^(原子群量词?)
|EscapeSeq量词?->^(原子逃逸量词?)
|其他量词?->^(其他量词?)
|字符集量词?->^(CHARSET{CharSetParser.ast($CHARSET.text)}量词?)
;
组
:“(“原子+”)”->^(原子组+)
;
量词
: '+'
| '*'
;
字符集
: '[' (('\\' .) | ~('\\' | ']'))+ ']'
;
逃逸
: '\\' .
;
其他
: ~('\\' | '(' | ')' | '[' | ']' | '+' | '*')
;
文件:CharSet.g
语法字符集;
选项{
输出=AST;
}
代币{
正常字符集;
否定字符集;
范围
}
@成员{
公共静态CommonTree ast(字符串源)引发识别异常{
CharSetLexer lexer=新的CharSetLexer(新的AntlStringStream(源));
CharSetParser=newcharsetparser(newcommontokenstream(lexer));
return(CommonTree)parser.parse().getTree();
}
}
作语法分析
:OSqBr(正常->^(正常字符设置正常)
|否定->^(否定字符集否定)
)
CSqBr
;
正常的
:(EscapeSeq |连字符|其他)原子*连字符?
;
否定
:插入符号正常->正常
;
原子
:EscapeSeq
|插入符号
|其他
|射程
;
范围
:from=Other连字符to=Other->^(范围$from$to)
;
OSqBr
: '['
;
CSqBr
: ']'
;
逃逸
: '\\' .
;
插入符号
: '^'
;
连字符
: '-'
;
其他
: ~('-' | '\\' | '[' | ']')
;
文件:Main.java
import org.antlr.runtime.*;
导入org.antlr.runtime.tree.*;
导入org.antlr.stringtemplate.*;
公共班机{
公共静态void main(字符串[]args)引发异常{
CommonTree-tree=RegexParser.ast(((xyz)*[^\\da-f])foo);
DOTTreeGenerator gen=新的DOTTreeGenerator();
StringTemplate st=gen.toDOT(树);
系统输出打印LN(st);
}
}
如果运行main类,您将看到regex((xyz)*[^\\da-f])foo的
神奇之处在于atom
规则中的Regex.g
语法中,我通过调用CharSetParser
类中的staticast
方法,在重写规则中插入了一个树节点:
CharSet ... -> ^(... {CharSetParser.ast($CharSet.text)} ...)
请注意,在这样的重写规则中,不能有分号!所以,这是错误的:{CharSetParser.ast($CharSet.text);}
编辑
下面是如何为这两种语法创建树漫游器:
文件:RegexWalker.g
树语法RegexWalker;
选择权{
tokenVocab=Regex;
ASTLabelType=CommonTree;
}
步行
:^(REGEX-atom+{System.out.println(“REGEX:+$start.toStringTree());}
;
原子
:^(原子群量词?)
|^(原子逃逸量词?)
|^(其他量词?)
|^(charsett=.quantifier?{CharSetWalker.walk($t);}
;
组
:^(组原子+)
;
量词
: '+'
| '*'
;
文件:CharSetWalker.g
树语法CharSetWalker;
选择权{
tokenVocab=字符集;
ASTLabelType=CommonTree;
}
@成员{
公共静态虚步道(CommonTree树){
试一试{
CommonTreeNodesTeam节点=新的CommonTreeNodesTeam(树);
查塞沃克沃尔酒店
CharSet ... -> ^(... {CharSetParser.ast($CharSet.text)} ...)