org.textmapper.lapg.lex.TablesArchiver Maven / Gradle / Ivy
/**
* Copyright 2002-2018 Evgeny Gryaznov
*
* 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 org.textmapper.lapg.lex;
import java.util.Arrays;
// TODO
public class TablesArchiver {
private final int nstates, nchars;
private final int[][] change;
public TablesArchiver(int nstates, int nchars, int[][] change) {
this.nstates = nstates;
this.nchars = nchars;
this.change = change;
}
public int[] pDefault, pBase, pNext, pCheck;
public void buildPacked() {
pDefault = new int[nstates];
pBase = new int[nstates];
int[][] next = new int[nstates][];
int[][] check = new int[nstates][];
int pstates = 0;
for (int i = 0; i < nstates; i++) {
int bestDefault = -1, minOverrides = Integer.MAX_VALUE;
for (int e = 0; e < i; e++) {
int toOverride = 0;
for (int c = 0; c < nchars && toOverride < minOverrides; c++) {
if (change[e][c] != change[i][c]) {
toOverride++;
}
}
if (toOverride < minOverrides) {
bestDefault = e;
minOverrides = toOverride;
}
}
pDefault[i] = bestDefault;
int bestBase = -1;
if (bestDefault >= 0) {
int[] target = new int[minOverrides];
int targetIndex = 0;
for (int c = 0; c < nchars; c++) {
if (change[bestDefault][c] != change[i][c]) {
target[targetIndex++] = c;
}
}
int y;
targetIndex = pstates;
for (int e = 0; e < pstates; e++) {
for (y = 0; y < minOverrides; y++) {
if (check[e][target[y]] != -1) {
break;
}
}
if (y == minOverrides) {
targetIndex = e;
break;
}
}
if (targetIndex == pstates) {
next[pstates] = new int[nchars];
check[pstates] = new int[nchars];
Arrays.fill(check[pstates], -1);
pstates++;
}
bestBase = targetIndex * nchars;
for (y = 0; y < minOverrides; y++) {
check[targetIndex][target[y]] = i;
next[targetIndex][target[y]] = change[i][target[y]];
}
} else {
bestBase = pstates * nchars;
next[pstates] = new int[nchars];
check[pstates] = new int[nchars];
Arrays.fill(check[pstates], -1);
for (int c = 0; c < nchars; c++) {
check[pstates][c] = i;
next[pstates][c] = change[i][c];
}
pstates++;
}
pBase[i] = bestBase;
}
pNext = new int[pstates * nchars];
pCheck = new int[pstates * nchars];
for (int i = 0; i < pstates; i++) {
System.arraycopy(next[i], 0, pNext, i * nchars, nchars);
System.arraycopy(check[i], 0, pCheck, i * nchars, nchars);
}
System.out.println("compressed - was: " + (nchars * nstates) + ", now: " + (pstates * nchars * 2 + 2 * nstates));
checkIntegrity();
}
private int nextState(int s2, int ch) {
int curr = s2;
while (curr != -1) {
if (pCheck[pBase[curr] + ch] == curr) {
return pNext[pBase[curr] + ch];
}
curr = pDefault[curr];
}
return -1;
}
private void checkIntegrity() {
for (int i = 0; i < nstates; i++) {
for (int e = 0; e < nchars; e++) {
if (nextState(i, e) != change[i][e]) {
System.out.println("integrity problem at " + i + ", " + e);
return;
}
}
}
}
}