Mercurial > projects > dil
comparison trunk/src/dil/doc/Macro.d @ 718:be887ada3e3e
Added new module dil.doc.Macro.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Fri, 01 Feb 2008 14:16:50 +0100 |
parents | |
children | ceaac6a24258 |
comparison
equal
deleted
inserted
replaced
717:cb8edb09108a | 718:be887ada3e3e |
---|---|
1 /++ | |
2 Author: Aziz Köksal | |
3 License: GPL3 | |
4 +/ | |
5 module dil.doc.Macro; | |
6 | |
7 import dil.lexer.Funcs; | |
8 import dil.Unicode; | |
9 import common; | |
10 | |
11 class Macro | |
12 { | |
13 string name; /// The name of the macro. | |
14 string text; /// Substitution text. | |
15 this (string name, string text) | |
16 { | |
17 this.name = name; | |
18 this.text = text; | |
19 } | |
20 } | |
21 | |
22 class MacroTable | |
23 { | |
24 MacroTable parent; | |
25 Macro[string] table; | |
26 | |
27 this(MacroTable parent = null) | |
28 { | |
29 this.parent = parent; | |
30 } | |
31 | |
32 void insert(Macro macro_) | |
33 { | |
34 table[macro_.name] = macro_; | |
35 } | |
36 | |
37 Macro search(string name) | |
38 { | |
39 auto pmacro = name in table; | |
40 if (pmacro) | |
41 return *pmacro; | |
42 if (parent) | |
43 return parent.search(name); | |
44 return null; | |
45 } | |
46 | |
47 bool isRoot() | |
48 { return parent is null; } | |
49 } | |
50 | |
51 void skipWhitespace(ref char* p) | |
52 { | |
53 while (isspace(*p) || *p == '\n') | |
54 p++; | |
55 } | |
56 | |
57 struct MacroParser | |
58 { | |
59 char* p; | |
60 char* textEnd; | |
61 | |
62 Macro[] parse(string text) | |
63 { | |
64 if (!text.length) | |
65 return null; | |
66 if (text[$-1] != '\0') | |
67 text ~= '\0'; | |
68 p = text.ptr; | |
69 textEnd = p + text.length; | |
70 | |
71 Macro[] macros; | |
72 | |
73 char* idBegin, idEnd, bodyBegin; | |
74 char* nextIdBegin, nextIdEnd, nextBodyBegin; | |
75 | |
76 // Init. | |
77 findNextMacroId(idBegin, idEnd, bodyBegin); | |
78 // Continue. | |
79 while (findNextMacroId(nextIdBegin, nextIdEnd, nextBodyBegin)) | |
80 { | |
81 macros ~= new Macro(makeString(idBegin, idEnd), makeString(bodyBegin, nextIdBegin)); | |
82 idBegin = nextIdBegin; | |
83 idEnd = nextIdEnd; | |
84 bodyBegin = nextBodyBegin; | |
85 } | |
86 // Add last macro. | |
87 macros ~= new Macro(makeString(idBegin, idEnd), makeString(bodyBegin, textEnd)); | |
88 return macros; | |
89 } | |
90 | |
91 bool findNextMacroId(ref char* ref_idBegin, ref char* ref_idEnd, ref char* ref_bodyBegin) | |
92 { | |
93 while (*p != '\0') | |
94 { | |
95 skipWhitespace(p); | |
96 auto idBegin = p; | |
97 if (isidbeg(*p) || isUnicodeAlpha(p)) // IdStart | |
98 { | |
99 do // IdChar* | |
100 p++; | |
101 while (isident(*p) || isUnicodeAlpha(p)) | |
102 auto idEnd = p; | |
103 | |
104 skipWhitespace(p); | |
105 if (*p == '=') | |
106 { | |
107 ref_idBegin = idBegin; | |
108 ref_idEnd = idEnd; | |
109 ref_bodyBegin = p + 1; | |
110 return true; | |
111 } | |
112 } | |
113 skipLine(); | |
114 } | |
115 return false; | |
116 } | |
117 | |
118 void skipLine() | |
119 { | |
120 while (*p != '\n') | |
121 p++; | |
122 p++; | |
123 } | |
124 | |
125 bool isUnicodeAlpha(ref char* ref_p) | |
126 { | |
127 char* p = ref_p; // Copy. | |
128 if (isascii(*p)) | |
129 return false; | |
130 | |
131 dchar d = *p; | |
132 p++; // Move to second byte. | |
133 // Error if second byte is not a trail byte. | |
134 if (!isTrailByte(*p)) | |
135 return false; | |
136 // Check for overlong sequences. | |
137 switch (d) | |
138 { | |
139 case 0xE0, 0xF0, 0xF8, 0xFC: | |
140 if ((*p & d) == 0x80) | |
141 return false; | |
142 default: | |
143 if ((d & 0xFE) == 0xC0) // 1100000x | |
144 return false; | |
145 } | |
146 const char[] checkNextByte = "if (!isTrailByte(*++p))" | |
147 " return false;"; | |
148 const char[] appendSixBits = "d = (d << 6) | *p & 0b0011_1111;"; | |
149 // Decode | |
150 if ((d & 0b1110_0000) == 0b1100_0000) | |
151 { | |
152 d &= 0b0001_1111; | |
153 mixin(appendSixBits); | |
154 } | |
155 else if ((d & 0b1111_0000) == 0b1110_0000) | |
156 { | |
157 d &= 0b0000_1111; | |
158 mixin(appendSixBits ~ | |
159 checkNextByte ~ appendSixBits); | |
160 } | |
161 else if ((d & 0b1111_1000) == 0b1111_0000) | |
162 { | |
163 d &= 0b0000_0111; | |
164 mixin(appendSixBits ~ | |
165 checkNextByte ~ appendSixBits ~ | |
166 checkNextByte ~ appendSixBits); | |
167 } | |
168 else | |
169 return false; | |
170 | |
171 assert(isTrailByte(*p)); | |
172 if (!isValidChar(d) || !isUniAlpha(d)) | |
173 return false; | |
174 // Only advance pointer if this is a Unicode alpha character. | |
175 ref_p = p; | |
176 return true; | |
177 } | |
178 } | |
179 | |
180 char[] makeString(char* begin, char* end) | |
181 { | |
182 return begin[0 .. end - begin]; | |
183 } |