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
    ;


你的问题可以(至少)用两种方式来解释:

  • 将大语法中的规则分成不同的语法
  • 在“主”语言(孤岛语法)中解析单独的语言
  • 我想这是第一次,在这种情况下,你可以导入语法

    选项1的演示: 档案:L.g
    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
    类中的static
    ast
    方法,在重写规则中插入了一个树节点:

    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)} ...)