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 }