6

次のように、Java言語定義からの「ステートメント」定義があります。

statement
: block
|   ASSERT expression (':' expression)? ';'
|   'if' parExpression statement ('else' statement)?
|   'for' '(' forControl ')' statement
|   'while' parExpression statement
|   'do' statement 'while' parExpression ';'
|   'try' block
    ( catches 'finally' block
    | catches
    | 'finally' block
    )
|   'switch' parExpression switchBlock
|   'synchronized' parExpression block
|   'return' expression? ';'
|   'throw' expression ';'
|   'break' Identifier? ';'
|   'continue' Identifier? ';'
|   ';'
|   statementExpression ';'
|   Identifier ':' statement
;

パーサーを実行するとき、次のような完全なユーザー作成ステートメントも出力したい (ステートメント内のスペースを含む):

Object o = Ma.addToObj(r1);
if(h.isFull() && !h.contains(true)) h.update(o);

しかし、「exitStatement」で関数「getText()」を使用すると、次のようなすべてのスペースが削除されたステートメントしか取得できません。

Objecto=Ma.addToObj(r1);
if(h.isFull()&&!h.contains(true))h.update(o);

ユーザーが作成した完全なステートメント (ステートメント内のスペースを含む) を簡単な方法で取得するにはどうすればよいですか? どうもありがとう!

完全なコードは次のとおりです。

public class PrintStatements {
public static class GetStatements extends sdlParserBaseListener {
    StringBuilder statements = new StringBuilder();
     public void exitStatement(sdlParserParser.StatementContext ctx){               
            statements.append(ctx.getText());
            statements.append("\n");                        
        }
}


public static void main(String[] args) throws Exception{

String inputFile = null;
if ( args.length>0 ) inputFile = args[0];
InputStream is = System.in;
if ( inputFile!=null ) {
    is = new FileInputStream(inputFile);
}
ANTLRInputStream input = new ANTLRInputStream(is);
sdlParserLexer lexer = new sdlParserLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
sdlParserParser parser = new sdlParserParser(tokens);
ParseTree tree = parser.s();

// create a standard ANTLR parse tree walker
ParseTreeWalker walker = new ParseTreeWalker();
// create listener then feed to walker
GetStatements loader = new GetStatements();
walker.walk(loader, tree);        // walk parse tree   

System.out.println(loader.statements.toString());
}
}
4

4 に答える 4

0

私はANTLRにかなり慣れていないので、何か間違っているかもしれません...

これを行う簡単な方法はわかりませんが、このようなことを試すことができます。文法ファイルには、おそらく次のようなものがあります。

WS  :  (' '|'\r'|'\t'|'\u000C'|'\n') 
{   
    if (!preserveWhitespacesAndComments) {
      skip();
    } else {
       $channel = HIDDEN;
    }
}

このレクサー規則は、パーサーに空白を無視するように指示します。より正確には、このトークンは HIDDEN チャネルで送信されます (パーサーはそれらを認識しません)。このコード行にコメントすると

WS  :  (' '|'\r'|'\t'|'\u000C'|'\n') 
{   
    if (!preserveWhitespacesAndComments) {
    //   skip();
    } else {
      //  $channel = HIDDEN;
    }
}

すべての空白はパーサーに送信されますが、パーサーのルールを書き直して、任意の場所で空白を期待できるようにする必要があります。

Object(EXPECT WHITESPACE)o(EXPECT WHITESPACE)=(EXPECT WHITESPACE)Ma.addToObj(r1);

それ以外の場合、パーサーはエラーを報告します。

于 2013-09-25T13:04:01.890 に答える
0

Antlr4 と Python3 に関しては、コードは次のようになります。

def exitSomeDecl(self, ctx: yourParser.SomeDeclContext):
    start_index = ctx.start.tokenIndex
    stop_index = ctx.stop.tokenIndex
    user_text = self.token_stream.getText(interval=(start_index, stop_index))

ここでは、self.token_stream: CommonTokenStreaminit 中に割り当てられます。

    input_stream = FileStream(file_name)
    lexer = sdplLexer(input_stream)
    token_stream = CommonTokenStream(lexer)
于 2016-10-28T17:55:43.043 に答える
0

次の 2 つのいずれかが必要です。

  • ステートメント解析 (語彙素またはツリー ノードのいずれかが行う必要があります) によって受け入れられた最初と最後のトークンのファイル位置データを取得し、ソース ファイルに移動して、テキストを抽出する機能。これにより、元の空白が取得されます。
  • AST からテキストを再生成し、適切な空白を挿入する prettyprinter。ここでかなりプリンターを構築する方法に関する私のSOの回答を参照してください。
于 2013-09-25T14:19:46.483 に答える