Support for pre in gflib.ts. Some type annotation fixes.

This commit is contained in:
John J. Camilleri
2019-06-07 21:17:41 +02:00
parent ffcdaa921f
commit d6a1e87f4a

View File

@@ -415,7 +415,8 @@ class GFConcrete {
private syms2toks(syms: Sym[]): string[] { private syms2toks(syms: Sym[]): string[] {
let ts: string[] = [] let ts: string[] = []
syms.forEach((sym0: Sym): void => { for (let i = 0; i < syms.length; i++) {
let sym0 = syms[i]
switch (sym0.id) { switch (sym0.id) {
case 'KS': { case 'KS': {
let sym = sym0 as SymKS let sym = sym0 as SymKS
@@ -426,18 +427,41 @@ class GFConcrete {
} }
case 'KP': { case 'KP': {
let sym = sym0 as SymKP let sym = sym0 as SymKP
for (let j in sym.tokens) { let addedAlt = false
ts.push(sym.tokens[j].tagWith(sym.tag)) if (i < syms.length-1) {
let nextSym = syms[i+1]
if (nextSym.id == 'KS') {
let nextToken = (nextSym as SymKS).tokens[0]
sym.alts.forEach((alt: Alt): void => {
// consider alts here (for handling pre)
if (alt.prefixes.some((p: string): boolean => nextToken.startsWith(p))) {
alt.tokens.forEach((symks: SymKS): void => {
symks.tokens.forEach((t: string): void => {
ts.push(t.tagWith(sym.tag))
})
})
addedAlt = true
return
} }
})
}
}
if (addedAlt) break
// Fall through here when no alts (or none apply)
sym.tokens.forEach((symks: SymKS): void => {
symks.tokens.forEach((t: string): void => {
ts.push(t.tagWith(sym.tag))
})
})
break break
} }
} }
}) }
return ts return ts
} }
public linearizeAll(tree: Fun): string[] { public linearizeAll(tree: Fun): string[] {
return this.linearizeSyms(tree,'0').map(function(r): string { return this.linearizeSyms(tree,'0').map((r): string => {
return this.unlex(this.syms2toks(r.table[0])) return this.unlex(this.syms2toks(r.table[0]))
}) })
} }
@@ -462,12 +486,13 @@ class GFConcrete {
let s = '' let s = ''
for (let i = 0; i < ts.length; i++) { for (let i = 0; i < ts.length; i++) {
let t = ts[i] let t: string = ts[i]
let after = i < ts.length-1 ? ts[i+1] : null let after: string | null = i < ts.length-1 ? ts[i+1] : null
s += t s += t
// TODO handle pre construct if (after != null
if (after != null && !t.match(noSpaceAfter) && !t.match(noSpaceAfter)
&& !after.match(noSpaceBefore)) { && !after.match(noSpaceBefore)
) {
s += ' ' s += ' '
} }
} }
@@ -591,15 +616,27 @@ class GFConcrete {
let acc = ps.complete(current) let acc = ps.complete(current)
// Format into just a list of strings & return // Format into just a list of strings & return
// (I know the multiple nesting looks horrible)
let suggs: string[] = [] let suggs: string[] = []
if (acc.value) { if (acc.value) {
acc.value.forEach((a: ActiveItem): void =>{ acc.value.forEach((a: ActiveItem): void =>{
a.seq.forEach((s: SymKS | SymKP): void => { a.seq.forEach((s: SymKS | SymKP): void => {
if (s.tokens == null) return if (s.tokens == null) return
s.tokens.forEach((t: string): void => { switch (s.id) {
case 'KS': {
(s as SymKS).tokens.forEach((t: string): void => {
suggs.push(t) suggs.push(t)
}) })
break
}
case 'KP': {
(s as SymKP).tokens.forEach((symks: SymKS): void => {
symks.tokens.forEach((t: string): void => {
suggs.push(t)
})
})
break
}
}
}) })
}) })
} }
@@ -796,6 +833,7 @@ class SymKS implements Taggable {
return terminalStr.join('') return terminalStr.join('')
} }
// TODO magic numbering fails here
public tagWith(tag: string): SymKS { public tagWith(tag: string): SymKS {
this.tag = tag this.tag = tag
return this return this
@@ -807,11 +845,11 @@ class SymKS implements Taggable {
*/ */
class SymKP implements Taggable { class SymKP implements Taggable {
public id: string public id: string
public tokens: string[] public tokens: SymKS[]
public alts: Alt[] public alts: Alt[]
public tag?: string public tag?: string
public constructor(tokens: string[], alts: Alt[]) { public constructor(tokens: SymKS[], alts: Alt[]) {
this.id = 'KP' this.id = 'KP'
this.tokens = tokens this.tokens = tokens
this.alts = alts this.alts = alts
@@ -823,7 +861,8 @@ class SymKP implements Taggable {
return terminalStr.join('') return terminalStr.join('')
} }
public tagWith(tag: string): SymKS { // TODO magic numbering fails here
public tagWith(tag: string): SymKP {
this.tag = tag this.tag = tag
return this return this
} }
@@ -833,10 +872,10 @@ class SymKP implements Taggable {
* Alt * Alt
*/ */
class Alt { class Alt {
public tokens: string[] public tokens: SymKS[]
public prefixes: string[] public prefixes: string[]
public constructor(tokens: string[], prefixes: string[]) { public constructor(tokens: SymKS[], prefixes: string[]) {
this.tokens = tokens this.tokens = tokens
this.prefixes = prefixes this.prefixes = prefixes
} }
@@ -1211,9 +1250,14 @@ class ParseState {
case 'KP': { case 'KP': {
let sym = sym0 as SymKP let sym = sym0 as SymKP
let pitem = item.shiftOverTokn() let pitem = item.shiftOverTokn()
tokenCallback(sym.tokens, pitem) sym.tokens.forEach((symks: SymKS): void => { // TODO not sure if this is right
tokenCallback(symks.tokens, pitem)
})
sym.alts.forEach((alt: Alt): void => { sym.alts.forEach((alt: Alt): void => {
tokenCallback(alt.tokens, pitem) // tokenCallback(alt.tokens, pitem)
alt.tokens.forEach((symks: SymKS): void => { // TODO not sure if this is right
tokenCallback(symks.tokens, pitem)
})
}) })
break break
} }
@@ -1448,9 +1492,9 @@ class ActiveItem {
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* from Remedial JavaScript by Douglas Crockford, http://javascript.crockford.com/remedial.html */ /* from Remedial JavaScript by Douglas Crockford, http://javascript.crockford.com/remedial.html */
// function isString(a: any): boolean { function isString(a: any): boolean {
// return typeof a == 'string' return typeof a == 'string' || a instanceof String
// } }
// function isArray(a: any): boolean { // function isArray(a: any): boolean {
// return a && typeof a == 'object' && a.constructor == Array // return a && typeof a == 'object' && a.constructor == Array
// } // }
@@ -1490,3 +1534,16 @@ function isUndefined(a: any): boolean {
// return x + '}' // return x + '}'
// } // }
// } // }
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith#Polyfill
// if (!String.prototype.startsWith) {
interface String {
startsWith: (search: string, pos?: number) => boolean;
}
Object.defineProperty(String.prototype, 'startsWith', {
value: function(search: string, pos?: number): boolean {
pos = !pos || pos < 0 ? 0 : +pos
return this.substring(pos, pos + search.length) === search
}
})
// }