2013-03-23 2 views
2

이클립스를 사용하여 내 grammar (antlr 완료)에서 심볼 테이블을 작성하려고합니다. 그러나 나는 무엇을 시작해야할지 모른다. 필자는 어딘가에서 antlr이 생성 한 파서와 렉서가 필요하다고 생각한다. 누군가가 쉬운 예를 알고 있으므로 그것이 어떻게 작동하는지 이해할 수 있습니까?문법에서 심볼 테이블 빌드

+0

컴파일러 기호 표에 대한 표준 텍스트를 읽으십시오. 그 후, 그것의 단지 (잔뜩) 땀. ANTLR은 도움이되는 특별한 것을 제공하지 않습니다. 그것은 파서 생성기 *이며, 거기에서 정말로 좋은 일을 한 다음 멈추게됩니다. –

+0

예, 현재 체크 아웃 중입니다. antlr에 의해 생성 된 렉서에게 getTree를 할 수있는 것처럼 보입니다. – Exia0890

답변

5

심볼 테이블은 ID와 값의 버전 매핑 된지도 일뿐입니다. 이는 하나의 솔루션으로, 스코어의 푸시 및 팝을 버전 관리 메커니즘으로 사용합니다. 범위 정의 규칙을 입력 할 때 범위를 누르고 종료 할 때 팝업하십시오.

package net.certiv.metal.symbol; 

import java.util.ArrayList; 
import java.util.LinkedHashMap; 
import java.util.Map; 

import net.certiv.metal.types.ScopeType; 
import net.certiv.metal.util.Strings; 

public class Scope { 

    public final int genId; 

    public ScopeType type; 
    public Scope enclosingScope; 
    protected Map<String, Symbol> symbolMap = new LinkedHashMap<String, Symbol>(); 

    public Scope(ScopeType type, final int genId, Scope enclosingScope) { 
     this.type = type; 
     this.genId = genId; 
     this.enclosingScope = enclosingScope; 
    } 

    /** 
    * Define a new variable in the current scope 
    * This is the entry point for adding new variables 
    */ 
    public void define(String name, ArrayList<String> parameters) { 
     String params = Strings.asString(parameters, true, "."); 
     Symbol symbol = new Symbol(null, name + params, null); 
     define(symbol); 
    } 

    /** Define a symbol in the current scope */ 
    private void define(Symbol symbol) { 
     symbol.setScope(this); 
     symbolMap.put(symbol.name, symbol); 
    } 

    /** 
    * Look up the symbol name in this scope and, if not found, 
    * progressively search the enclosing scopes. 
    * Return null if not found in any applicable scope. 
    */ 
    private Symbol resolve(String name) { 
     Symbol symbol = symbolMap.get(name); 
     if (symbol != null) return symbol; 
     if (enclosingScope != null) return enclosingScope.resolve(name); 
     return null; // not found 
    } 
    /** 
    * Lookup a variable starting in the current scope. 
    * This is the entry point for lookups 
    */ 
    public Symbol resolve(String name, ArrayList<String> parameters) { 
     String params = Strings.asString(parameters, true, "."); 
     return resolve(name + params); 
    } 

    /** Where to look next for symbols */ 
    public Scope enclosingScope() { 
     return enclosingScope; 
    } 

    public String toString() { 
     return symbolMap.keySet().toString(); 
    } 
} 


package net.certiv.metal.types; 

public enum ScopeType { 
    GLOBAL, 
    LOCAL; 
} 



package net.certiv.metal.symbol; 

import net.certiv.metal.converter.BaseDescriptor; 
import net.certiv.metal.types.ValueType; 

public class Symbol { 

    protected Scope scope; // the owning scope 
    protected BaseDescriptor descriptor; 
    protected String name; 
    protected ValueType type; 

    public Symbol(BaseDescriptor descriptor, String name, ValueType type) { 
     this.descriptor = descriptor; 
     this.name = name; 
     this.type = type; 
    } 

    public BaseDescriptor getDescriptor() { 
     return descriptor; 
    } 

    public String getName() { 
     return name; 
    } 

    public ValueType getType() { 
     return type; 
    } 

    public void setScope(Scope scope) { 
     this.scope = scope; 
    } 

    public Scope getScope() { 
     return scope; 
    } 

    public int genId() { 
     return scope.genId; 
    } 

    public String toString() { 
     if (type != null) return '<' + getName() + ":" + type + '>'; 
     return getName(); 
    } 
} 

package net.certiv.metal.symbol; 

import java.util.ArrayList; 
import java.util.Stack; 

import net.certiv.metal.types.ScopeType; 
import net.certiv.metal.util.Log; 

public class SymbolTable { 

    protected Stack<Scope> scopeStack; 
    protected ArrayList<Scope> allScopes; 
    protected int genId; 

    public SymbolTable() { 
     init(); 
    } 

    protected void init() { 
     scopeStack = new Stack<>(); 
     allScopes = new ArrayList<>(); 
     genId = 0; 

     Scope globals = new Scope(ScopeType.GLOBAL, nextGenId(), null); 
     scopeStack.push(globals); 
     allScopes.add(globals); 
    } 

    public Scope pushScope() { 
     Scope enclosingScope = scopeStack.peek(); 
     Scope scope = new Scope(ScopeType.LOCAL, nextGenId(), enclosingScope); 
     scopeStack.push(scope); 
     allScopes.add(scope); 
     return scope; 
    } 

    public void popScope() { 
     scopeStack.pop(); 
    } 

    public Scope currentScope() { 
     if (scopeStack.size() > 0) { 
      return scopeStack.peek(); 
     } 
     Log.error(this, "Unbalanced scope stack."); 
     return allScopes.get(0); 
    } 

    public Scope getScope(int genId) { 
     for (Scope scope : scopeStack) { 
      if (scope.genId == genId) return scope; 
     } 
     return null; 
    } 

    private int nextGenId() { 
     genId++; 
     return genId; 
    } 

    public String toString() { 
     StringBuilder sb = new StringBuilder(); 
     for (Scope scope : scopeStack.subList(0, scopeStack.size() - 1)) { 
      sb.append(scope.toString()); 
     } 
     return sb.toString(); 
    } 
} 
+1

심볼 테이블은 실제로 모든 식별자 인스턴스와 해당 식별자에 대한 유형 인스턴스의 설명 자의 맵입니다. 범위는 코드의 한 부분에있는 기호를 범위의 알려진 기호 선언에 매핑하는 방법을 구성하는 방법입니다. 이 대답은 간단합니다. 많은 오래된 언어가 간단한 범위의 스택으로 처리 될 수 있습니다. 네임 스페이스와 제네릭을 사용하는보다 현대적인 언어는 맵 아이디어가 남아 있지만 거의 단순하지 않습니다. –

+0

너무 빨리 읽었을 때 또는 무엇을 대답하지만 제시된대로 답이 맞는지 확실하지 않습니다. 이 코드는 OP 질문에 직접 응답하는 기호 테이블 작업의 메커니즘을 설명하는 "하나의 솔루션"으로 제공됩니다. 모든 실존 ​​적 자격은 ID와 값의 매핑에 구현 될 수 있지만 OP의 질문의 요소는 아닙니다. 게다가, 형식이없는/단독으로 형식화 된 언어가 있으며, OP의 문법에서 OP와 관련 될 수 있습니다. 네임 스페이스와 제네릭 모두 버전 관리의 형태로 처리되며 OP의 문법과 관련이 없습니다. – GRosenberg

+1

나는 진짜 langauges에 대한 기호 테이블을 작성하는 것이 이보다 더 많은 것을 요구할 것이라는 것을 관찰하면서, 당신의 솔루션을 스케치 (불평 : no ding!)로 불평하지 않았습니다. 어쩌면 그의 언어는 간단 할 것입니다. 그는 구현을 시작하기 전에 더 잘 결정합니다. 이것은 무엇인가를하기 위해 서두르 기 전에 상세하게 기호 테이블에 대해 읽는 것에 대한 본래의 요점이었습니다. –

관련 문제