Я пытаюсь создать таблицу символов из моей грамматики (выполняется с помощью antlr) с помощью eclipse. Однако я не знаю, с чего начать. Думаю, я где-то читал, что для этого вам понадобятся парсер и лексер, сгенерированные antlr. Кто-нибудь знает простой пример, чтобы я мог понять, как он работает, пожалуйста?
Создание таблицы символов на основе грамматики
comment
Прочтите любой стандартный текст о таблицах символов компилятора. После этого это просто (пачка) пота. ANTLR не предлагает вам никакой конкретной помощи; это генератор парсеров, и он действительно хорошо работает, а затем останавливается.
- person Ira Baxter   schedule 24.03.2013
comment
Да, сейчас проверяю их. Похоже, вы можете выполнить getTree в лексере, сгенерированном antlr, и поработать над ним.
- person Exia0890   schedule 28.03.2013
Ответы (1)
Таблица символов - это просто версионная карта идентификаторов и значений. Это одно из решений, использующее push и pop областей в качестве механизма управления версиями - push область при входе в правило, определяющее область, и pop при выходе.
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();
}
}
person
GRosenberg
schedule
24.03.2013
Таблица символов на самом деле является отображением каждого экземпляра идентификатора на дескриптор экземпляра типа для этого идентификатора. Области видимости - это способ организовать отображение символов в одной части кода на известные объявления символов в области. Этот ответ верен простым способом: многие старые языки могут обрабатываться простым стеком областей видимости. Более современные языки с пространствами имен и обобщениями не так просты, хотя идея карты остается.
- person Ira Baxter; 24.03.2013
Не уверен, что вы читаете слишком быстро или что, но ответ вполне правильный в том виде, в котором он представлен. Код представлен как одно из решений для иллюстрации механизмов работы с таблицей символов, что является прямым ответом на вопрос ОП. Любые экзистенциальные квалификации могут быть реализованы при отображении идентификаторов в значения, но это не было элементом вопроса OP. Кроме того, существуют языки без типа / с одним типом, что, согласно грамматике OP, может иметь место для OP. Пространства имен и обобщенные типы, которые обрабатываются формами управления версиями, не участвуют в грамматике OP.
- person GRosenberg; 25.03.2013
Я не жаловался на ваше решение как на набросок (примечание: никакого звонка!), Просто заметил, что для построения таблиц символов для реальных языков, вероятно, потребуется больше, чем это. Может, его язык прост. Ему лучше решить, прежде чем он приступит к реализации, что было моей первоначальной точкой зрения о подробном чтении таблиц символов, прежде чем спешить что-то делать.
- person Ira Baxter; 25.03.2013
Извините за поздний ответ, спасибо вам обоим за ответы. @GRosenberg, спасибо за ваш код, я все еще работаю над ним, чтобы понять его и посмотреть, будет ли он работать с моей грамматикой. Однако есть несколько импортированных классов, откуда я не мог видеть :( util.Strings; util.Log; ValueType;).
- person Exia0890; 28.03.2013
Strings.asString применяет правило (что вы хотите) для нормализации представления имени переменной. Например, преобразование сложной схемы именования переменных в более простое строковое представление в кодировке свойств (a.b.c) с соответствующей уникальностью. ValueType может быть простым перечислением, определяющим формальный тип переменной. BaseDescriptor может быть классом, содержащим любые расширенные данные, которые вы хотите связать с переменной.
- person GRosenberg; 29.03.2013
Если ответ оказался полезным, отметьте его как принятый.
- person GRosenberg; 14.04.2013