FormatCompiler.ts
126 lines
| 3.9 KiB
| video/mp2t
|
TypeScriptLexer
|
|
r79 | import { FormatScanner, TokeType } from "./FormatScanner"; | ||
|
|
r82 | import { isNullOrEmptyString, isPrimitive, get } from "../safe"; | ||
| import { TextWriter, MapOf } from "../interfaces"; | ||||
| type CompiledPattern = (writer: TextWriter, args: any) => void; | ||||
|
|
r79 | |||
| export class FormatCompiler { | ||||
|
|
r81 | _scanner: FormatScanner; | ||
|
|
r82 | _cache: MapOf<CompiledPattern> = {}; | ||
|
|
r79 | |||
|
|
r82 | _parts: Array<string | { name: string; format: string; }>; | ||
| compile(pattern: string) { | ||||
| let compiledPattern = this._cache && this._cache[pattern]; | ||||
| if (!compiledPattern) { | ||||
| this._scanner = new FormatScanner(pattern); | ||||
| this._parts = []; | ||||
| this.visitText(); | ||||
| const parts = this._parts; | ||||
|
|
r81 | |||
|
|
r82 | compiledPattern = (writer: TextWriter, args: any) => { | ||
| parts.forEach(x => { | ||||
| if (isPrimitive(x)) | ||||
| writer.writeValue(x); | ||||
| else | ||||
| writer.writeValue(get(x.name, args), x.format); | ||||
| }); | ||||
| }; | ||||
| if (this._cache) | ||||
| this._cache[pattern] = compiledPattern; | ||||
| } | ||||
| return compiledPattern; | ||||
|
|
r81 | } | ||
| visitText() { | ||||
| while (this._scanner.next()) { | ||||
|
|
r82 | // console.log(this._scanner.getTokenType(), this._scanner.getTokenValue()); | ||
|
|
r81 | switch (this._scanner.getTokenType()) { | ||
| case TokeType.CurlOpen: | ||||
| this.visitCurlOpen(); | ||||
| break; | ||||
| case TokeType.CurlClose: | ||||
| this.visitCurlClose(); | ||||
| break; | ||||
| default: | ||||
| this.pushText(this._scanner.getTokenValue()); | ||||
| } | ||||
|
|
r79 | } | ||
| } | ||||
|
|
r81 | visitCurlClose() { | ||
| if (!this._scanner.next()) | ||||
| this.dieUnexpectedEnd("}"); | ||||
| if (this._scanner.getTokenType() !== TokeType.CurlClose) | ||||
| this.dieUnexpectedToken("}"); | ||||
| this.pushText("}"); | ||||
| } | ||||
| visitCurlOpen() { | ||||
|
|
r82 | if (!this._scanner.next()) | ||
| this.dieUnexpectedEnd("{ | TEXT"); | ||||
| if (this._scanner.getTokenType() === TokeType.CurlOpen) | ||||
| this.pushText("{"); | ||||
| else | ||||
| this.visitTemplateSubst(); | ||||
|
|
r79 | } | ||
|
|
r81 | visitTemplateSubst() { | ||
| if (this._scanner.getTokenType() !== TokeType.Text) | ||||
| this.dieUnexpectedToken("TEXT"); | ||||
|
|
r79 | |||
|
|
r81 | const fieldName = this._scanner.getTokenValue(); | ||
|
|
r82 | const filedFormat = this.readColon() ? this.readFieldFormat() : null; | ||
| if (this._scanner.getTokenType() !== TokeType.CurlClose) | ||||
| this.dieUnexpectedToken("}"); | ||||
|
|
r79 | |||
| this.pushSubst(fieldName, filedFormat); | ||||
| } | ||||
|
|
r80 | |||
|
|
r81 | readFieldFormat() { | ||
| const parts = new Array<string>(); | ||||
|
|
r82 | do { | ||
|
|
r81 | if (this._scanner.getTokenType() === TokeType.CurlClose) { | ||
| return parts.join(""); | ||||
| } else { | ||||
| parts.push(this._scanner.getTokenValue()); | ||||
| } | ||||
|
|
r82 | } while (this._scanner.next()); | ||
|
|
r81 | |||
| this.dieUnexpectedEnd("}"); | ||||
|
|
r79 | } | ||
|
|
r80 | |||
|
|
r81 | readColon() { | ||
| if (!this._scanner.next()) | ||||
| this.dieUnexpectedEnd(); | ||||
| if (this._scanner.getTokenType() !== TokeType.Colon) | ||||
| return false; | ||||
| if (!this._scanner.next()) | ||||
| this.dieUnexpectedEnd(); | ||||
| return true; | ||||
|
|
r79 | } | ||
|
|
r80 | |||
|
|
r81 | pushSubst(fieldName: string, filedFormat: string) { | ||
|
|
r82 | // console.log("pushSubst ", fieldName, filedFormat); | ||
| this._parts.push({ name: fieldName, format: filedFormat }); | ||||
|
|
r79 | } | ||
| pushText(text: string) { | ||||
|
|
r82 | this._parts.push(text); | ||
|
|
r79 | } | ||
|
|
r81 | dieUnexpectedToken(expected?: string) { | ||
| throw new Error(isNullOrEmptyString(expected) ? | ||||
| `Unexpected token ${this._scanner.getTokenValue()}` : | ||||
| `Unexpected token ${this._scanner.getTokenValue()}, expected ${expected}` | ||||
| ); | ||||
|
|
r79 | } | ||
|
|
r81 | dieUnexpectedEnd(expected?: string) { | ||
| throw new Error(isNullOrEmptyString(expected) ? "Unexpected end of the string" : `Unexpected end of the string, expected ${expected}`); | ||||
|
|
r79 | } | ||
| } | ||||
