import SrlJsonFormat, {NodesType, EdgesType} from './SrlJsonFormat'; class Span { s: number; t: number; constructor(s:number, t:number) { this.s = s; this.t = t; } } class FrameArg { span: Span; label: string; constructor(s:number, t:number, label:string) { this.span = new Span(s, t); this.label = label; } } function doesLabelLookLikePredicate(label:string):boolean { label = label.toLowerCase(); return label === 'target' || label === 'v' || label === 'what' || label==='predicate' || label === 'pred'; } class Frame { predicate: FrameArg; args: FrameArg[]; tokens: string[]; constructor(predicate: FrameArg, args: FrameArg[], tokens:string[]) { this.predicate = predicate; this.args = args; this.tokens = tokens; } static parse(line: string):null|Frame { if(!line.match(/^[0-9]+:\s+/)) return null; let retPredicate : null|FrameArg = null; const retArgs: FrameArg[] = []; const retTokens: string[] = []; // remove the leading sentence number line = line.replace(/^[0-9]+:\s+/,""); // split into tokens const tokens = line.split(' '); // parsing state let isInBracket = false; let frameS: null|number = null; let frameT: null|number = null; let frameLabel: null|string = null; let i=0; const commitFrameArg = (frameS:null|number, frameT:null|number, frameLabel:null|string) => { if(frameS == null || frameT == null || frameLabel == null) return; const frameArg = new FrameArg(frameS, frameT, frameLabel); if(doesLabelLookLikePredicate(frameArg.label)) { retPredicate = frameArg; } else { retArgs.push(frameArg); } isInBracket = false; }; const commitToken = (token:string) => { retTokens.push(token); i++; }; for(const token of tokens) { if(!isInBracket) { if(token.startsWith('[')) { frameS = i; frameLabel = token.length>1?token.substr(1):null; isInBracket = true; } else { commitToken(token); } } else { if(token === ']') { if(frameLabel != null) { frameT = i; commitFrameArg(frameS, frameT, frameLabel); } } else if(token.endsWith(']')) { if(frameLabel != null) { frameT = i+1; commitFrameArg(frameS, frameT, frameLabel); commitToken(token.substr(0, token.length - 1)); } } else if(frameLabel == null) { frameLabel = token; } else { commitToken(token); } } } if(retPredicate == null) return null; return new Frame(retPredicate, retArgs, retTokens); } } function range(start:number, count:number):number[] { return Array.apply(0, Array(count)) .map(function (element:number, index:number) { return index + start; }); } export default function parseAssert(assertStr:string):null|SrlJsonFormat { const lines = assertStr.split("\n"); //$FlowFixMe const frames: Frame[] = lines.map(line=>Frame.parse(line)).filter(frame=>frame!=null) as Frame[]; if(frames.length <= 0) return null; const tokens = frames[0].tokens; let nodes:NodesType = [[0,tokens.length,'&GOAL;'], ...frames.map(frame=><[number,number,string]>[frame.predicate.span.s, frame.predicate.span.t, frame.predicate.label]) ]; let edges:EdgesType = [[range(1, frames.length),[0]]]; frames.forEach((frame, i)=>{ const start = nodes.length; nodes = [...nodes, ...frame.args.map(arg=><[number,number,string]>[arg.span.s, arg.span.t, arg.label])]; const end = nodes.length; edges.push([range(start, end-start),[i+1]]) }); return new SrlJsonFormat(tokens, nodes, edges); }