All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.oneandone.mork.grammar.GrammarBase Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 1&1 Internet AG, https://github.com/1and1/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.oneandone.mork.grammar;

import net.oneandone.sushi.util.IntArrayList;

import java.util.ArrayList;
import java.util.List;

/**
 * Helper class for Grammar. Make sure that data derived from productions (aka symbols) is
 * recomputed if the productions change.
 */
public class GrammarBase {
    /** List of int[] */
    private final List productions;

    private Symbol[] symbols;

    public GrammarBase() {
        this.productions = new ArrayList();
        this.symbols = null;
    }

    /**
     * @return number of productions.
     */
    public int getProductionCount() {
        return productions.size();
    }

    protected int[] getProduction(int prod) {
        return productions.get(prod);
    }

    protected void addProduction(int[] prod) {
        productions.add(prod);
        symbols = null;
    }

    protected void addProduction(int ofs, int[] prod) {
        productions.add(ofs, prod);
        symbols = null;
    }

    protected void removeProduction(int idx) {
        productions.remove(idx);
        symbols = null;
    }

    protected Symbol[] getSymbols() {
        if (symbols == null) {
            calcSymbols();
        }
        return symbols;
    }

    protected Symbol getSymbol(int sym) {
        return getSymbols()[sym];
    }

    private void calcSymbols() {
        List pre;  // list of PreSymbols
        int prod, maxProd, ofs, sym;
        PreSymbol ps;
        int[] current;

        maxProd = productions.size();
        pre = new ArrayList();
        for (prod = 0; prod < maxProd; prod++) {
            current = getProduction(prod);
            for (ofs = 0; ofs < current.length; ofs++) {
                sym = current[ofs];
                while (pre.size() <= sym) {
                    pre.add(new PreSymbol());
                }
                ps = pre.get(sym);
                if (ofs == 0) {
                    ps.addAlternative(prod);
                } else {
                    ps.addUser(prod, ofs - 1);
                }
            }
        }
        symbols = new Symbol[pre.size()];
        for (sym = 0; sym < symbols.length; sym++) {
            symbols[sym] = pre.get(sym).createSymbol();
        }
    }

    //--

    /**
     * Helper class to instantiate symbols.
     */
    public static class PreSymbol {
        /** productions for this symbol */
        private final IntArrayList alternatives;

        /** productions using this symbol. */
        private final IntArrayList users;

        /** ofsets in the using productions. List of IntArrayLists. */
        private final List userOfs;

        public PreSymbol() {
            alternatives = new IntArrayList();
            users = new IntArrayList();
            userOfs = new ArrayList();
        }

        public void addAlternative(int prod) {
            alternatives.add(prod);
        }

        public void addUser(int prod, int ofs) {
            int i;
            IntArrayList ofsArray;

            i = users.indexOf(prod);
            if (i == -1) {
                i = users.size();
                users.add(prod);
                userOfs.add(new IntArrayList());
            }

            ofsArray = userOfs.get(i);
            ofsArray.add(ofs);
        }

        public Symbol createSymbol() {
            int[][] ofss;
            int i;
            IntArrayList ofsArray;

            ofss = new int[users.size()][];
            for (i = 0; i < ofss.length; i++) {
                ofsArray = userOfs.get(i);
                ofss[i] = ofsArray.toArray();
            }

            return new Symbol(alternatives.toArray(), users.toArray(), ofss);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy