tscc-compiler
Version:
An LALR(1) compiler compiler written in Typescript
96 lines (89 loc) • 2.71 kB
text/typescript
export interface Table{
readonly rows: number;
readonly columns: number;
isEmpty(i: number,j: number): boolean;
emptyCount(row: number): number;
}
function sorter(cmp: (a: RowEntry, b: RowEntry) => number){
var a: RowEntry[] = [];
function insert(i,obj){
a.push(null);
for(var j = a.length - 1;j > i;j--){
a[j] = a[j - 1];
}
a[i] = obj;
}
return {
add(b: RowEntry): void{
var i: number;
for(i = 0;i < a.length;i++){
if((i === 0 || cmp(b,a[i - 1]) >= 0) && cmp(b,a[i]) <= 0){
break;
}
}
insert(i,b);
},
done(): RowEntry[]{
return a;
}
};
}
class RowEntry{
public dp: number | null = 0;
constructor(public emptyCount: number, public row: number){}
}
/**
* implementation of double displacement first-fit-decreasing method
*/
export function compress(source: Table): { dps: number[], len: number }{
function empty(i: number, j: number): boolean{
j = j - sorted[i].dp;
return j < 0 || j >= source.columns || source.isEmpty(sorted[i].row,j);
}
function fit(i: number, dp: number): boolean{
for(var j = 0;j < source.columns;j++){
if(!empty(i,j)){
for(var k = 0;k < i;k++){
if(!empty(k,j + dp)){
return false;
}
}
}
}
return true;
}
function getFitdp(i: number): number{
var dp = 0;
while(-dp < source.columns && source.isEmpty(sorted[i].row,-dp)){ dp--; }
while(!fit(i,dp)){ dp++; }
return dp;
}
var tmpsorted = sorter((a, b) => {
return a.emptyCount < b.emptyCount ? -1 :
a.emptyCount > b.emptyCount ? 1 : 0;
});
for(var i = 0;i < source.rows;i++){
tmpsorted.add(new RowEntry(source.emptyCount(i),i));
}
var sorted = tmpsorted.done();
//the row with least empty entries has displacement 0
var maxdp = 0, mindp = 0;
var dps = new Array(source.rows);
let initDp = 0;
while(-initDp < source.columns && source.isEmpty(sorted[0].row, -initDp)){ initDp--; }
dps[sorted[0].row] = sorted[0].dp = initDp;
for(var i = 1;i < sorted.length;i++){
let row = sorted[i].row;
let dp = getFitdp(i);
dps[row] = sorted[i].dp = dp;
dp > maxdp && (maxdp = dp);
dp < mindp && (mindp = dp);
}
// for(var i = 0;i < dps.length;i++){
// dps[i] -= mindp;
// }
return {
dps: dps,
len: maxdp + source.columns// - mindp
};
}