ANTLR을 사용하여 구축된 AST를 출력하는 방법은?
저는 C의 정적 분석기를 만들고 있습니다.저는 자바 코드를 생성하는 ANTLR을 이용하여 렉서와 파서를 해왔습니다.
ANTLR에서 자동으로 AST를 구축합니까?options {output=AST;}
? 아니면 제가 직접 나무를 만들어야 합니까?그렇다면 AST에서 노드를 어떻게 뱉을 수 있습니까?
저는 현재 그 AST의 노드가 SSA를 만드는 데 사용될 것이고, 정적 분석기를 만들기 위해 데이터 플로우 분석을 할 것으로 생각하고 있습니다.제가 가는 길이 맞나요?
라파엘은 이렇게 썼습니다.
antlr에서 옵션 {output=에 의해 자동으로 AST를 구축합니까?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를 만드는 방법은 두 가지가 있습니다.
- 다음과 같은 재작성 규칙을 사용합니다.
foo : A B C D -> ^(D A B);
,어디에foo
는 토큰과 일치하는 파서 규칙입니다.A B C D
. 그래서 그 이후의 모든 것들은->
실제 재작성 규칙입니다.보시다시피 토큰은C
재작성 규칙에는 사용되지 않으므로 AST에서 생략됩니다.다음에 바로 배치된 토큰입니다.^(
나무의 뿌리가 될 것입니다. - 나무를 이용합니다.
^
그리고.!
당신의 파서 규칙 안에 토큰이 있는 후에^
토큰을 뿌리로 만들 것이고,!
트리에서 토큰을 삭제합니다.에 해당하는 것.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 위키 링크:
라파엘은 이렇게 썼습니다.
저는 현재 그 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);
}
}
언급URL : https://stackoverflow.com/questions/4931346/how-to-output-the-ast-built-using-antlr
'programing' 카테고리의 다른 글
Excel에서 OD 데이터 피드의 변경 내용을 게시하는 방법 (0) | 2023.10.24 |
---|---|
EF + ODP.NET + CLOB = 값은 Null일 수 없습니다 - 매개 변수 이름: byteArray? (0) | 2023.10.24 |
정방향 클래스 개체에서 속성을 찾을 수 없습니다. (0) | 2023.10.19 |
Spring MVC에 필요한 String 매개 변수가 없습니다. (0) | 2023.10.19 |
스크립트 클래스의 메서드에서 "함수가 아닙니다" 오류가 발생했습니다. (0) | 2023.10.19 |