| @@ -1,5 +1,5 | |||||
| 1 | export interface Constructor<T = {}> { |
|
1 | export interface Constructor<T = {}> { | |
| 2 |
new |
|
2 | new(...args: any[]): T; | |
| 3 | prototype: T; |
|
3 | prototype: T; | |
| 4 | } |
|
4 | } | |
| 5 |
|
5 | |||
| @@ -101,6 +101,11 export interface IObserver<T> { | |||||
| 101 | } |
|
101 | } | |
| 102 |
|
102 | |||
| 103 | export interface TextWriter { |
|
103 | export interface TextWriter { | |
| 104 | formatter; |
|
104 | Write(obj: any): void; | |
| 105 |
Write( |
|
105 | Write(format: string, ...args: any[]): void; | |
|
|
106 | ||||
|
|
107 | WriteLine(obj: any): void; | |||
|
|
108 | WriteLine(format: string, ...args: any[]): void; | |||
|
|
109 | ||||
|
|
110 | WriteValue(value: any, spec?: string): void; | |||
| 106 | } |
|
111 | } | |
| @@ -1,53 +1,86 | |||||
| 1 | import { FormatScanner, TokeType } from "./FormatScanner"; |
|
1 | import { FormatScanner, TokeType } from "./FormatScanner"; | |
|
|
2 | import { isNullOrEmptyString } from "../safe"; | |||
|
|
3 | import { TextWriter } from "../interfaces"; | |||
| 2 |
|
4 | |||
| 3 | export class FormatCompiler { |
|
5 | export class FormatCompiler { | |
|
|
6 | _scanner: FormatScanner; | |||
| 4 |
|
7 | |||
| 5 | visitText(scanner: FormatScanner) { |
|
8 | _parts: []; | |
| 6 | while (scanner.next()) { |
|
9 | ||
| 7 | if (scanner.getTokenType() === TokeType.CurlOpen) |
|
10 | compile() { | |
| 8 | this.visitCurlOpen(scanner); |
|
11 | return (writer: TextWriter, args: any) => { | |
|
|
12 | this._parts.forEach(x => writer.WriteValue(x)) | |||
|
|
13 | }; | |||
|
|
14 | } | |||
|
|
15 | ||||
|
|
16 | visitText() { | |||
|
|
17 | while (this._scanner.next()) { | |||
|
|
18 | switch (this._scanner.getTokenType()) { | |||
|
|
19 | case TokeType.CurlOpen: | |||
|
|
20 | this.visitCurlOpen(); | |||
|
|
21 | break; | |||
|
|
22 | case TokeType.CurlClose: | |||
|
|
23 | this.visitCurlClose(); | |||
|
|
24 | break; | |||
|
|
25 | default: | |||
|
|
26 | this.pushText(this._scanner.getTokenValue()); | |||
|
|
27 | } | |||
|
|
28 | if (this._scanner.getTokenType() === TokeType.CurlOpen) | |||
|
|
29 | this.visitCurlOpen(); | |||
| 9 | } |
|
30 | } | |
| 10 | } |
|
31 | } | |
| 11 |
|
32 | |||
| 12 | visitCurlOpen(scanner: FormatScanner) { |
|
33 | visitCurlClose() { | |
| 13 |
if (scanner.next()) |
|
34 | if (!this._scanner.next()) | |
| 14 | if (scanner.getTokenType() === TokeType.CurlOpen) |
|
35 | this.dieUnexpectedEnd("}"); | |
|
|
36 | if (this._scanner.getTokenType() !== TokeType.CurlClose) | |||
|
|
37 | this.dieUnexpectedToken("}"); | |||
|
|
38 | this.pushText("}"); | |||
|
|
39 | } | |||
|
|
40 | ||||
|
|
41 | visitCurlOpen() { | |||
|
|
42 | if (this._scanner.next()) { | |||
|
|
43 | if (this._scanner.getTokenType() === TokeType.CurlOpen) | |||
| 15 | this.pushText("{"); |
|
44 | this.pushText("{"); | |
| 16 | else |
|
45 | else | |
| 17 |
this.visitTemplateSubst( |
|
46 | this.visitTemplateSubst(); | |
| 18 |
|
||||
| 19 | } |
|
47 | } | |
| 20 | } |
|
48 | } | |
| 21 |
|
49 | |||
| 22 |
visitTemplateSubst( |
|
50 | visitTemplateSubst() { | |
| 23 | if (scanner.getTokenType() !== TokeType.Text) |
|
51 | if (this._scanner.getTokenType() !== TokeType.Text) | |
| 24 |
this.dieUnexpectedToken( |
|
52 | this.dieUnexpectedToken("TEXT"); | |
| 25 |
|
53 | |||
| 26 | const fieldName = scanner.getTokenValue(); |
|
54 | const fieldName = this._scanner.getTokenValue(); | |
| 27 | let filedFormat: string; |
|
55 | const filedFormat = this.readColon() && this.readFieldFormat(); | |
| 28 | if (this.readColon(scanner)) { |
|
|||
| 29 | filedFormat = this.readFieldFormat(scanner); |
|
|||
| 30 | } else { |
|
|||
| 31 | if (scanner.getTokenType() !== TokeType.CurlClose) |
|
|||
| 32 | this.dieUnexpectedToken(scanner); |
|
|||
| 33 | } |
|
|||
| 34 |
|
56 | |||
| 35 | this.pushSubst(fieldName, filedFormat); |
|
57 | this.pushSubst(fieldName, filedFormat); | |
| 36 | } |
|
58 | } | |
| 37 |
|
59 | |||
| 38 | pushSubst(fieldName: string, filedFormat: string) { |
|
60 | readFieldFormat() { | |
| 39 | throw new Error("Method not implemented."); |
|
61 | const parts = new Array<string>(); | |
|
|
62 | while (this._scanner.next()) { | |||
|
|
63 | if (this._scanner.getTokenType() === TokeType.CurlClose) { | |||
|
|
64 | return parts.join(""); | |||
|
|
65 | } else { | |||
|
|
66 | parts.push(this._scanner.getTokenValue()); | |||
|
|
67 | } | |||
|
|
68 | } | |||
|
|
69 | ||||
|
|
70 | this.dieUnexpectedEnd("}"); | |||
| 40 | } |
|
71 | } | |
| 41 |
|
72 | |||
| 42 | readFieldFormat(scanner: FormatScanner): string { |
|
73 | readColon() { | |
| 43 | throw new Error("Method not implemented."); |
|
74 | if (!this._scanner.next()) | |
|
|
75 | this.dieUnexpectedEnd(); | |||
|
|
76 | if (this._scanner.getTokenType() !== TokeType.Colon) | |||
|
|
77 | return false; | |||
|
|
78 | if (!this._scanner.next()) | |||
|
|
79 | this.dieUnexpectedEnd(); | |||
|
|
80 | return true; | |||
| 44 | } |
|
81 | } | |
| 45 |
|
82 | |||
| 46 | readColon(scanner: FormatScanner) { |
|
83 | pushSubst(fieldName: string, filedFormat: string) { | |
| 47 | if (!scanner.next()) |
|
|||
| 48 | this.dieUnexpectedEnd(); |
|
|||
| 49 | if (scanner.getTokenType() !== TokeType.Colon) |
|
|||
| 50 | return false; |
|
|||
| 51 |
|
84 | |||
| 52 | } |
|
85 | } | |
| 53 |
|
86 | |||
| @@ -55,11 +88,14 export class FormatCompiler { | |||||
| 55 |
|
88 | |||
| 56 | } |
|
89 | } | |
| 57 |
|
90 | |||
| 58 |
dieUnexpectedToken( |
|
91 | dieUnexpectedToken(expected?: string) { | |
| 59 | throw new Error(`Unexpected token ${scanner.getTokenValue()}`); |
|
92 | throw new Error(isNullOrEmptyString(expected) ? | |
|
|
93 | `Unexpected token ${this._scanner.getTokenValue()}` : | |||
|
|
94 | `Unexpected token ${this._scanner.getTokenValue()}, expected ${expected}` | |||
|
|
95 | ); | |||
| 60 | } |
|
96 | } | |
| 61 |
|
97 | |||
| 62 | dieUnexpectedEnd() { |
|
98 | dieUnexpectedEnd(expected?: string) { | |
| 63 | throw new Error("Unexpected end of string"); |
|
99 | throw new Error(isNullOrEmptyString(expected) ? "Unexpected end of the string" : `Unexpected end of the string, expected ${expected}`); | |
| 64 | } |
|
100 | } | |
| 65 | } |
|
101 | } | |
General Comments 0
You need to be logged in to leave comments.
Login now
