UNPKG

traindown

Version:

A language to help athletes express their training. Inspired by Markdown.

3 lines (2 loc) 6.09 kB
const e=Object.freeze({EOF:-1,DateTimeToken:"DateTime",FailToken:"Fail",LoadToken:"Load",MetaKeyToken:"Meta Key",MetaValueToken:"Meta Value",MovementToken:"Movement",NoteToken:"Note",RepToken:"Rep",SetToken:"Set",SupersetMovementToken:"Superset Movement"});class t{constructor(e,t){this.chr=e,this.next=t||null}}class s{constructor(e){this.start=e||null}push(e){let s=new t(e);null==this.start||(s.next=this.start),this.start=s}pop(){if(null==this.start)return e.EOF;let t=this.start;return this.start=t.next,t.chr}clear(){this.start=null}}class a{constructor(e,t){this.type=e,this.value=t}toString(){return"["+this.type+"] "+this.value}}class n{constructor(e,t){this.done=!1,this.errorHandler=e=>{throw e},this.position=0,this.src=e,this.start=0,this.state=t||(()=>{}),this.tokens=[],this.vcr=new s,this._output={}}current(){return this.src.slice(this.start,this.position)}emit(e){let t=new a(e,this.current());this.tokens.push(t),this.start=this.position,this.vcr.clear()}error(e){this.errorHandler(e)}ignore(){this.vcr.clear(),this.start=this.position}next(){let t=e.EOF,s=this.src.slice(this.position,this.src.length);return 0!=s.length&&(t=s[0]),this.position+=1,this.vcr.push(t),t}nextToken(){return this.tokens.pop()}peek(){let e=this.next();return this.rewind(),e}rewind(){this.vcr.pop()!=e.EOF&&(this.position-=1,this.position<this.start&&(this.position=this.start))}run(e){for(;null!=this.state;)this.state=this.state.call(e,this);this.done=!0}take(e){let t=this.next();for(;e.includes(t);)t=this.next();this.rewind()}}class r{constructor(e){this.done=!1,this.errors=[],this.tokens=e,this.output={date:null,metadata:{},movements:[],notes:[]},this._process()}_process(){let t=null,s=0;e:for(let a=0;a<this.tokens.length;++a){let n=this.tokens[a];switch(n.type){case e.DateTimeToken:this.output.date=n.value;break;case e.MetaKeyToken:this.output.metadata[n.value]=null,t=n.value;break;case e.MetaValueToken:this.output.metadata[t]=n.value;break;case e.NoteToken:this.output.notes.push(n.value);break;default:s=a;break e}}if(s==this.tokens.length-1)return void(this.done=!0);let a=[this.tokens[0]];for(let t=1;t<this.tokens.length;++t){let s=this.tokens[t];s.type==e.MovementToken||s.type==e.SupersetMovementToken?(this._marshalMovement(a),a=[s]):a.push(s)}a.length>0&&this._marshalMovement(a),this.done=!0}_marshalMovement(t){let s={metadata:{},name:"Unknown Movement",notes:[],performances:[],sequence:this.output.movements.length,superset:!1,touched:!1},a=null,n=0;e:for(let r=0;r<t.length;++r){let i=t[r];switch(i.type){case e.SupersetMovementToken:s.superset=!0,s.name=i.value;break;case e.MovementToken:s.name=i.value;break;case e.MetaKeyToken:s.metadata[i.value]=null,a=i.value;break;case e.MetaValueToken:s.metadata[a]=i.value;break;case e.NoteToken:s.notes.push(i.value);break;default:n=r;break e}s.touched=!0}s.touched&&(delete s.touched,s.performances=this._marshalPerformance(t.slice(n)),this.output.movements.push(s))}_marshalPerformance(t){let s=[],a=null,n={fails:0,load:0,metadata:{},reps:0,notes:[],sets:1,touched:!1},r=e=>{delete n.touched,n.sequence=s.length,s.push(n),n={fails:0,load:0,metadata:{},reps:0,notes:[],sets:1,touched:!1}};for(let s=0;s<t.length;++s){let i=t[s];if(i.type==e.LoadToken){n.touched&&(0==n.reps&&0==n.fails&&(n.reps=1),0!=n.load&&r());let e=parseFloat(i.value);n.load=isNaN(e)?i.value:e}else switch(i.type){case e.FailToken:n.fails=parseFloat(i.value);break;case e.MetaKeyToken:n.metadata[i.value]=null,a=i.value;break;case e.MetaValueToken:n.metadata[a]=i.value;break;case e.NoteToken:n.notes.push(i.value);break;case e.RepToken:n.reps=parseFloat(i.value);break;case e.SetToken:n.sets=parseInt(i.value,10)}n.touched=!0}return 0==n.reps&&0==n.fails&&(n.reps=1),n.fails>0&&0==n.reps&&(n.reps=n.fails),r(),s}}export default class{constructor(e){this.lexer=new n(e,this.idleState)}parse(e){if(this.lexer.run(this),!e)return this.lexer.tokens;switch(e){case"json":let e=new r(this.lexer.tokens);return!e.done||e.errors.length>0?{error:!0}:e.output;default:return this.lexer.tokens}}idleState(t){let s=t.peek();if(s==e.EOF)return null;if(this._isWhitespace(s)||this._isLineTerminator(s))return t.next(),t.ignore(),this.idleState(t);switch(s){case"@":return this.dateTimeState(t);case"#":return this.metaKeyState(t);case"*":return this.noteState(t);default:return this.valueState(t)}}dateTimeState(t){t.take(["@"," "]),t.ignore();let s=t.next();for(;!this._isLineTerminator(s);)s=t.next();return t.rewind(),t.emit(e.DateTimeToken),this.idleState}metaKeyState(t){t.take(["#"," "]),t.ignore();let s=t.next();for(;!this._isColonTerminator(s);)s=t.next();return t.rewind(),t.emit(e.MetaKeyToken),this.metaValueState}metaValueState(t){t.take([":"," "]),t.ignore();let s=t.next();for(;!this._isLineTerminator(s);)s=t.next();return t.rewind(),t.emit(e.MetaValueToken),this.idleState}movementState(t){let s=!1,a=t.next();for("+"==a&&(s=!0,t.take([" "]),t.ignore(),a=t.next()),"'"==a&&(t.ignore(),a=t.next());!this._isColonTerminator(a);)a=t.next();return t.rewind(),t.emit(s?e.SupersetMovementToken:e.MovementToken),t.take(":"),t.ignore(),this.idleState}noteState(t){t.take(["*"," "]),t.ignore();let s=t.next();for(;!this._isLineTerminator(s);)s=t.next();return t.rewind(),t.emit(e.NoteToken),this.idleState}numberState(t){switch(t.take(["0","1","2","3","4","5","6","7","8","9","."]),t.peek()){case"f":case"F":t.emit(e.FailToken);break;case"r":case"R":t.emit(e.RepToken);break;case"s":case"S":t.emit(e.SetToken);break;default:t.emit(e.LoadToken)}return t.take(["f","F","r","R","s","S"]),t.ignore(),this.idleState}valueState(t){let s=t.next();if("+"==s||"'"==s)return t.rewind(),this.movementState(t);if(isNaN(s)){if("b"!=s&&"B"!=s)return t.rewind(),this.movementState(t);let a=t.peek();if("w"!=a&&"W"!=a)return t.rewind(),this.movementState(t);for(;!this._isWhitespace(s);)s=t.next();return t.rewind(),t.emit(e.LoadToken),this.idleState}return this.numberState(t)}_isColonTerminator(t){return t==e.EOF||":"==t}_isLineTerminator(t){return t==e.EOF||";"==t||"\n"==t||"\r"==t}_isWhitespace(e){return/\s/.test(e)}} //# sourceMappingURL=index.modern.js.map