ruke.vrj.SymbolTable.java Source code

Java tutorial

Introduction

Here is the source code for ruke.vrj.SymbolTable.java

Source

package ruke.vrj;

import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import java.util.List;

/**
 * MIT License
 *
 * Copyright (c) 2017 Franco Montenegro
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
public class SymbolTable {

    public final SymbolTable parent;
    public final Symbol owner;
    private ImmutableMap<String, Symbol> symbols;

    /**
     * Create symbol table.
     *
     * @param parent Parent of the symbol table
     * @param owner Symbol owning symbol table (for example, an struct)
     */
    public SymbolTable(final SymbolTable parent, final Symbol owner) {
        this.parent = parent;
        this.owner = owner;
        this.symbols = ImmutableMap.of();

        if (owner != null) {
            this.define(owner);
        }
    }

    /**
     * Create symbol table without parent & owner.
     */
    public SymbolTable() {
        this(null, null);
    }

    /**
     * Copy only the symbols of a SymbolTable (ignore parent & owner).
     *
     * @param copy Which symbol table to copy
     * @return Copied symbol table
     */
    public static SymbolTable copyOf(final SymbolTable copy) {
        final SymbolTable result = new SymbolTable();
        result.symbols = ImmutableMap.copyOf(copy.symbols);
        return result;
    }

    public final void define(final String name, final Symbol symbol) {
        this.symbols = ImmutableMap.<String, Symbol>builder().putAll(this.symbols).put(name, symbol).build();
    }

    public final void define(final Symbol symbol) {
        this.define(symbol.name, symbol);
    }

    /**
     * Find symbol in symbol table.
     *
     * @param name Name to search for
     * @return Symbol (Symbol.NOTHING is returned if the symbol wasn't found)
     */
    public final Symbol resolve(final String name) {
        if (name.contains(".")) {
            // ( 1 ) some.chain.expression
            // ( 2 ) search "some" in the current symbol table
            // ( 3 ) make a copy of the symbol table of "some" so we can't search in parents
            // ( 4 ) repeat
            final List<String> names = Splitter.on(".").splitToList(name);
            final List<String> restChain = names.subList(1, names.size());
            final Symbol firstInChain = this.resolve(names.get(0));

            return SymbolTable.copyOf(firstInChain.children).resolve(String.join(".", restChain));
        }

        Symbol result = this.symbols.getOrDefault(name, Symbol.NOTHING);

        if (result.equals(Symbol.NOTHING) && this.parent != null) {
            result = this.parent.resolve(name);
        }

        return result;
    }
}