9

// 전달 된 입력 스트림에서 읽는 스캐너를 만듭니다. CSLexer lexer = new CSLexer (new ANTLRFileStream (f)); tokens.TokenSource = lexer;ANTLR을 사용하여 자체 C# 컴파일러 작성 : 컴파일 단위

// Create a parser that reads from the scanner 
CSParser parser = new CSParser(tokens); 

// start parsing at the compilationUnit rule 
CSParser.compilation_unit_return x = parser.compilation_unit(); 
object ast = x.Tree; 

x는 compilation_unit_return 유형의 루트, 클래스, 메소드 등을 추출하려면 어떻게해야합니까? 어댑터를 추출해야합니까? 어떻게해야합니까? compilation_unit_return가 (자동으로 ANTLR에 의해 생성되는) 내 CSParser에 같은 정의되어 있습니다 :

public class compilation_unit_return : ParserRuleReturnScope 
    { 
     private object tree; 
     override public object Tree 
     { 
      get { return tree; } 
      set { tree = (object) value; } 
     } 
    }; 

내가 무엇입니까 나무가 유형 객체이다 그러나. 디버거를 사용하여 실행하고 BaseTree 형식인지 보였다. 그러나 BaseTree는 인터페이스입니다! 어떻게 BaseTree와 관련이 있으며이 트리에서 세부 사항을 추출하는 방법을 모르겠습니다. 클래스, 메서드, 변수를 방문한 방문자를 작성해야합니다. ParserRuleReturn 클래스는 RuleReturnScope에서 확장되며 시작 및 중지 객체가 있습니다. 어떤 내용인지는 알 수 없습니다 ... , ANTLR이 제공하는 TreeVisitor 클래스가 혼란스러워 보인다. 어댑터가 생성자에 대한 매개 변수로 전달되어야합니다 (기본 CommonTreeAdaptor를 사용하지 않을 경우). 왜 어댑터 earer를 가져 오는 지 abt에게 묻습니다. 다른 문제도 있습니다 ... API에 대해서는 다음을 참조 할 수 있습니다. http://www.antlr.org/api/CSharp/annotated.html

이제 나는 여기에 맞 춥니 다. 대단히 감사합니다.

답변

3

나는 이제까지의 C#에서 ANTLR 함께 일하지 않은,하지만 API로 링크를, BaseTree 명확하지 인터페이스입니다 - 그것은 class, 그리고 그것이 공공 속성이 있습니다 Type를 얻을 수있는 노드의 유형, Text를 얻을 수 (나는 가정) 그것에 대응하는 소스 텍스트, 그리고 Children 자식 노드를 얻을 수 있습니다. 그걸 밟을 필요가 있는게 또 뭐야? 나는 오늘 C# 컴파일러를 만들려고한다면

+0

추상 클래스입니다 ... 공개 추상 클래스 BaseTree : ITree – yeeen

+1

그래, 왜 당신을 막을까요? 트리의 루트 노드가 있습니다. 트리의 루트 노드가 있습니다. 트리의 루트 노드는 자식을 검색하는 데 필요한 모든 메서드를 포함하고 있으므로 트리를 임의의 깊이까지 이동하는 데 필요합니다. –

-2

, 여기에 내가 는 첫 번째 시도로 시도 어떻게 할 것인지의 다음 ANTLR C# 3 타겟

  1. 시작 (물론 내가 여기 편견 해요 - 심각하게 CSharp2 또는 CSharp3 대상을 사용할 수 있음).
  2. .NET Framework 4로 Visual Studio 2010을 구하십시오. 여기에서 핵심은 .NET 4이며 새로운 표현식 트리입니다.
  3. 기본 결합 파서를 작성하십시오. 파서에 가능한 한 적은 로직을 넣으십시오. 몇 가지 조치가 있어야하며 출력은 LL (1) 워커와 함께 걸을 수있는 장식되지 않은 AST이어야합니다.
  4. 트리를 걸어보고 선언 된 모든 유형을 식별하는 트리 문법을 작성하십시오. 또한 나중에 사용할 수 있도록 member_declaration 하위 트리를 유지해야합니다.
  5. member_declaration을 하나 걸어 다니며 TypeBuilder에 구성원을 추가하는 트리 워커를 빌드하십시오. 방법 몸체를 계속 추적하지만 아직 걷지는 마세요.
  6. 메서드 본문을 처리하는 트리 워커를 빌드하십시오. 메서드와 일치하는 Expression<TDelegate>을 생성하고 CompileToMethod 메서드 내 API (Pavel 및 내 의견 참조)를 사용하여 IL 코드를 생성합니다.이 순서대로 일을 할 경우

, 당신은 마지막으로 식 (메소드의 본체, 필드 이니셜)을 파싱 한 후 때, 당신은 일 해결 회원을 저장 Expression 클래스의 string 매개 변수 방법을 like this one를 사용할 수 있습니다.

+0

불행하게도,'CompileToMethod'는이 시나리오에서 그 고유 한 한계 때문에 진정으로 사용될 수 없습니다 - 코드에서 컴파일 할 다른 방법을 컴파일 할 방법이 없으며 타겟'MethodBuilder'는 정적 메소드를위한 것이어야합니다 만. 자세한 내용은 https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?Feedback=473128을 참조하십시오. –

+0

니스. 그럼, 그런 경우에 작동하는'Expression' 컴파일러를 작성한 다음 대신 사용하십시오. :)'Expression' 컴파일러를 독립적 인 모듈로 유지하여 다른 프로젝트와 함께 사용할 수 있습니다. 어쨌든 재미있게 할 것입니다. –

+0

아마도 위의 내 qn에서 조금 벗어나는 것일 수 있습니다. 나는 antlr-3.1.3의 소스 코드를 hv했습니다. 런타임 폴더 아래에 N, 폴더가 두 개 있습니다 - CSharp n CSharp3. u가 abt CSharp3을 언급 한 이래로 왜 2 개의 폴더가 있는지 알 수 있습니까? 그러나 온라인으로 제공되는 API는 CSharp3뿐만 아니라 컴파일 된 dll도 CSharp 용으로 보입니다. 누군가 CSharp3을 사용하고 싶다면 코드를 직접 컴파일해야합니다. 내게는 CSHARP3이 더 고급 기능을 가지고 있지만 내 맥락에서는별로 관련이없는 것처럼 보인다. – yeeen

6

당신과 같이 파일의 상단에 문법 옵션에서 AST 트리 유형을 설정할 수 있습니다

tree grammar CSharpTree; 
options { 
    ASTLabelType = CommonTree 
} 

내가 제 3 문법을 만들거나에 나무를 회전 기존 파서 문법에 그것을 작동합니다 당신이 만드는 수업. 예를 들어, 더하기 연산자와 일치하는 규칙을 갖고 있고 2 개의 인수가 있다고 가정합니다. 당신은 당신이 작성한 클래스를 만들고 그 나무 일치하는 규칙을 정의 할 수 있습니다,의 그것과 같이 PlusExpression 부르 자 :

plusExpr returns [PlusExpression value] 
    : ^(PLUS left=expr right=expr) { $value = new PlusExpression($left.value, $right.value); } 

expr이 문법 일치 표현식에서 다른 규칙이 될 것입니다. 왼쪽과 오른쪽은 트리 값에 주어진 별명입니다. {} 사이의 부분은 변수 참조를 대체하는 것을 제외하고는 거의 C# 코드로 바뀌 었습니다. $ left와 $ right의 .value 속성은 그들이 생성 된 규칙에서 지정한 반환 값에서옵니다.