ANTLR4 — цели без вложенных классов

Я пытаюсь расширить ANTLR4 новой целью PHP и столкнулся с проблемой с файлом StringTemplate (.stg):

В файле StringTemplate синтаксический анализатор определяется шаблоном Parser_. Parser_ содержит следующее правило:

    <funcs; separator="\n">

Это правило выдает определения классов и функции. Правило находится внутри класса парсера, но PHP не поддерживает вложенные классы.

Есть ли возможность разделить определения классов и функции в файле StringTemplate? Я хочу установить определения класса шаблона funcs перед классом синтаксического анализатора и функциями шаблона funcs внутри класса синтаксического анализатора.

Весь парсер-Шаблон:

Parser_(parser, funcs, atn, sempredFuncs, ctor, superClass) ::= <<    

// funcs beinhaltet die Klasse und dann die Funktion

class <parser.name> extends <if(superClass)><superClass><else>\antlr4\php7_runtime\Parser<endif>    {

    public $grammarFileName = "<parser.grammarFileName>";
    public $atn = null;
    public $decisionsToDFA = array( );
    public $sharedContextCache = null;


    public $literalNames = [ <parser.literalNames:{t | <t>}; null="'\<INVALID>'", separator=", ", wrap, anchor> ];

    public $symbolicNames = [ <parser.symbolicNames:{t | <t>}; null="'\<INVALID>'", separator=", ", wrap, anchor> ];

    <parser.rules:{r | const RULE_<r.name> = <r.index>;}; separator="\n", wrap, anchor>

    public $ruleNames =  [ <parser.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ];

    public $EOF = <PathRuntime()><TokenLabelType()>::EOF;

    <if(parser.tokens)>
    <parser.tokens:{k | const <k>=<parser.tokens.(k)>;}; separator="\n", wrap, anchor>
    <endif>    

    <atn>    

    <parser:(ctor)()>

    <namedActions.members>

// funcs -- Start
    <funcs; separator="\n">
// funcs -- Ende        

} // class <parser.name>    



<if(sempredFuncs)>
    function sempred( $localctx, int $ruleIndex, int $predIndex){
        if ($this->_predicates == null) {
            $this->_predicates = py_dict();
        }
<parser.sempredFuncs.values:{ f |
        $this->predicates[<f.ruleIndex>] = $this-><f.name>_sempred}; separator="\n">
        $pred = $this->_predicates->get($ruleIndex, null);
        if ( $pred == null) {
            throw Exception("No predicate with index:" . (string) $ruleIndex );
        } else {
            return pred( $localctx, $predIndex)
        }


    <sempredFuncs.values; separator="\n">
    }
<endif>

>>

Спасибо за ваше время!


person Rainer Stötter    schedule 12.11.2017    source источник


Ответы (1)


Решением было пройтись по parser.funcs.ruleCtx и исключить из шаблона RuleFunction :-)

Parser_(parser, funcs, atn, sempredFuncs, ctor, superClass ) ::= <<

<funcs :{ func | <func.ruleCtx> }; separator="\n"> // here the Comtext classes

class <parser.name> extends <if(superClass)><superClass><else>\antlr4\php7_runtime\Parser<endif>    {

    public $grammarFileName = "<parser.grammarFileName>";
    public $atn = null;
    public $decisionsToDFA = array( );
    public $sharedContextCache = null;


    public $literalNames = [ <parser.literalNames:{t | <t>}; null="'\<INVALID>'", separator=", ", wrap, anchor> ];

    public $symbolicNames = [ <parser.symbolicNames:{t | <t>}; null="'\<INVALID>'", separator=", ", wrap, anchor> ];

    <parser.rules:{r | const RULE_<r.name> = <r.index>;}; separator="\n", wrap, anchor>

    public $ruleNames =  [ <parser.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ];

    public $EOF = <PathRuntime()><TokenLabelType()>::EOF;

    <if(parser.tokens)>
    <parser.tokens:{k | const <k>=<parser.tokens.(k)>;}; separator="\n", wrap, anchor>
    <endif>    


<atn>    


    <parser:(ctor)()>

   <funcs; separator="\n"> // here RuleFunction is emitted


} // class <parser.name>    


<namedActions.members>

<if(sempredFuncs)>
    function sempred( $localctx, int $ruleIndex, int $predIndex){
        if ($this->_predicates == null) {
            $this->_predicates = py_dict();
        }
<parser.sempredFuncs.values:{ f |
        $this->predicates[<f.ruleIndex>] = $this-><f.name>_sempred}; separator="\n">
        $pred = $this->_predicates->get($ruleIndex, null);
        if ( $pred == null) {
            throw Exception("No predicate with index:" . (string) $ruleIndex );
        } else {
            return pred( $localctx, $predIndex)
        }


    <sempredFuncs.values; separator="\n">
    }
<endif>
>>
person Rainer Stötter    schedule 18.11.2017