IDE 는 어떤식으로 구문 분석을 하나?

박상준·2024년 8월 20일
1
post-custom-banner

의문

  • IDE 는 어떤식으로 구문분석을 하는지 의문이 들었다.
  • IDE가 색인된 파일을 읽어서 일일이 파싱하면 시간이 엄청 오래걸릴 것이라고 생각
  • 분명 다른 방법이 있을 것이라고 생각..

구문 분석법

  • AST 를 알아야 한다.
    • Abstract Syntax Tree 라고 한다.
    • 한국말로는 추상 구문 트리 라고 하는데,
  • Intellij 는 내부적인 소스를 알 수 없어서 오픈된 이클립스 소스상에서는
    import org.eclipse.jdt.core.dom.*;
    import org.eclipse.jdt.core.JavaCore;
    import org.eclipse.core.runtime.NullProgressMonitor;
    
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.util.Map;
    
    public class ASTGenerator {
        public static CompilationUnit generateAST(String filePath) throws Exception {
            // 1. 파일 내용 읽기
            String source = readFileToString(filePath);
            
            // 2. AST 파서 설정
            ASTParser parser = ASTParser.newParser(AST.JLS14); // Java 14 문법 사용
    • 이런식으로 AST 파서를 통해

      package com.example;
      
      public class HelloWorld {
          private String message;
      
          public HelloWorld(String message) {
              this.message = message;
          }
      
          public void sayHello() {
              System.out.println(message);
          }
      }
    • 이런 클래스 파일을 파서를 통해

      CompilationUnit
        PackageDeclaration
          SimpleName: com
          SimpleName: example
        TypeDeclaration: HelloWorld
          Modifier: public
          SimpleName: HelloWorld
          FieldDeclaration
            Modifier: private
            SimpleType
              SimpleName: String
            VariableDeclarationFragment
              SimpleName: message
          MethodDeclaration: HelloWorld
            Modifier: public
            SimpleName: HelloWorld
            SingleVariableDeclaration
              SimpleType
                SimpleName: String
              SimpleName: message
            Block
              ExpressionStatement
                Assignment
                  FieldAccess
                    ThisExpression
                    SimpleName: message
                  SimpleName: message
          MethodDeclaration: sayHello
            Modifier: public
            SimpleName: sayHello
            Block
              ExpressionStatement
                MethodInvocation
                  QualifiedName
                    SimpleName: System
                    SimpleName: out
                  SimpleName: println
                  SimpleName: message
    • 위와 같은 구조로 만든다고 함.

      장점

    1. 언어에 독립적인
      1. 추상화된 구조로서, 어떤 프로그래밍 구조라도, 동일한 구조로 표현이 가능해짐
      2. 언어마다 구문분석 방법을 달리할 가능성을 줄여준다.
    2. IDE 고급 기능 제공가능
      1. IDE 가 AST 구조분석된 내용을 토대로 리팩토링 등의 행위가 가능

이클립스 라이브러리 ASTParser 파싱하면 우에하노

public class Main {
    public static void main(String[] args) {
        ASTParser parser = ASTParser.newParser(AST.JLS20);
        
        try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("src/main/java/com/cor/practice/Calculator.java")));) {
            StringBuilder sb = new StringBuilder();
            String line = br.readLine();
            
            while (line != null) {
                sb.append(line).append("\n");
                line = br.readLine();
            }
            
            parser.setSource(sb.toString().toCharArray());
            
            parser.setKind(ASTParser.K_COMPILATION_UNIT); // 파싱 종류 설정 (전체 컴파일 유닛)
            parser.setResolveBindings(true); // 바인딩 정보 해석 활성화
            parser.setBindingsRecovery(true); // 바인딩 복구 활성화
            
            Map<String, String> options = JavaCore.getOptions();
            JavaCore.setComplianceOptions(JavaCore.VERSION_17, options);
            parser.setCompilerOptions(options);
            
            CompilationUnit compilationUnit = (CompilationUnit) parser.createAST(null);
            
            compilationUnit.accept(new ASTVisitor() {
                @Override
                public boolean visit(MethodDeclaration node) {
                    System.out.println("Method name: " + node.getName().getIdentifier());
                    return true;
                }
            });
            
            String output = compilationUnit.toString();
            System.out.println(output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 출력해보면 메서드 이름이 compilationUnit#visit 안의 print 에 따라 출력된다.
    • 메서드이름, 변수, 클래스 이름등에 대해 해당 라이브러리로 구분이 가능해짐.

라이브러리 추가해야함.
implementation 'org.eclipse.jdt:org.eclipse.jdt.core:3.38.0'

profile
이전 블로그 : https://oth3410.tistory.com/
post-custom-banner

0개의 댓글