私はC用の静的アナライザーを作成しています。Javaコードを生成するANTLRを使用して、レクサーとパーサーを実行しました。
ANTLRはASTをoptions {output=AST;}
によって自動的に構築しますか?または、ツリーを自分で作成する必要がありますか?作成する場合、そのASTのノードを吐き出す方法は?
私は現在、そのAST上のノードがSSAを作成するために使用され、続いて静的フローアナライザーを作成するためにデータフロー分析が使用されると考えています。正しいパスにいますか?
ラファエルは書きました:
AntlrはASTをオプション{output = AST;}によって自動的に構築しますか?または、自分でツリーを作成する必要がありますか?作成する場合は、そのASTのノードを吐き出す方法?
いいえ、パーサーはパーサールールごとにルートおよびリーフとして何が必要かわからないため、文法に_options { output=AST; }
_を置くだけではなく、もう少し多くのことを行う必要があります。
たとえば、文法から生成されたパーサーを使用してソース"true && (false || true && (true || false))"
を解析する場合:
_grammar ASTDemo;
options {
output=AST;
}
parse
: orExp
;
orExp
: andExp ('||' andExp)*
;
andExp
: atom ('&&' atom)*
;
atom
: 'true'
| 'false'
| '(' orExp ')'
;
// ignore white space characters
Space
: (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;}
;
_
次の解析ツリー が生成されます:
(つまり、トークンのフラットな1次元リスト)
ANTLRに、文法のどのトークンがルートになるか、リーフになるか、または単にツリーから除外されるかを伝えます。
ASTの作成は、次の2つの方法で実行できます。
foo : A B C D -> ^(D A B);
。ここで、foo
はトークン_A B C D
_に一致するパーサールールです。したがって、_->
_の後のすべてが実際の書き換えルールです。ご覧のとおり、トークンC
は書き換えルールで使用されていません。つまり、ASTからは省略されています。 _^(
_の直後に配置されたトークンがツリーのルートになります。^
_および_!
_after内のトークンを使用する_^
_がトークンをルートにし、_!
_がツリーからトークンを削除するパーサー規則。 foo : A B C D -> ^(D A B);
と同等のものは_foo : A B C! D^;
_になります。foo : A B C D -> ^(D A B);
と_foo : A B C! D^;
_はどちらも次のASTを生成します。
これで、次のように文法を書き直すことができます。
_grammar ASTDemo;
options {
output=AST;
}
parse
: orExp
;
orExp
: andExp ('||'^ andExp)* // Make `||` root
;
andExp
: atom ('&&'^ atom)* // Make `&&` root
;
atom
: 'true'
| 'false'
| '(' orExp ')' -> orExp // Just a single token, no need to do `^(...)`,
// we're removing the parenthesis. Note that
// `'('! orExp ')'!` will do exactly the same.
;
// ignore white space characters
Space
: (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;}
;
_
これは 次のAST をソースから作成します"true && (false || true && (true || false))"
:
関連ANTLR wikiリンク:
ラファエルは書きました:
私は現在、そのAST上のノードがSSAを作成するために使用され、続いて静的フローアナライザーを作成するためにデータフロー分析が使用されると考えています。正しいパスにいますか?
そのようなことをしたことは一度もありませんが、IMOあなたが最初に望むのはASTソースからのものなので、そうです、そうです、あなたは正しい道を進んでいると思います!:)
生成されたレクサーとパーサーを使用する方法は次のとおりです。
_import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;
public class Main {
public static void main(String[] args) throws Exception {
String src = "true && (false || true && (true || false))";
ASTDemoLexer lexer = new ASTDemoLexer(new ANTLRStringStream(src));
ASTDemoParser parser = new ASTDemoParser(new CommonTokenStream(lexer));
CommonTree tree = (CommonTree)parser.parse().getTree();
DOTTreeGenerator gen = new DOTTreeGenerator();
StringTemplate st = gen.toDOT(tree);
System.out.println(st);
}
}
_