Mercurial > projects > dil
comparison src/docgen/config/reader.d @ 806:bcb74c9b895c
Moved out files in the trunk folder to the root.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Sun, 09 Mar 2008 00:12:19 +0100 |
parents | trunk/src/docgen/config/reader.d@2949146f2781 |
children |
comparison
equal
deleted
inserted
replaced
805:a3fab8b74a7d | 806:bcb74c9b895c |
---|---|
1 /** | |
2 * Author: Jari-Matti Mäkelä | |
3 * License: GPL3 | |
4 */ | |
5 module docgen.config.reader; | |
6 | |
7 debug import tango.io.Stdout; | |
8 | |
9 /** | |
10 * Lexes a s-exp like input | |
11 */ | |
12 char[][] lex(char[] input) { | |
13 char[][] tokens; | |
14 | |
15 uint state = 0, level = 0; | |
16 size_t sidx = 0; | |
17 | |
18 void err(size_t i, int type = 0) { | |
19 auto b = input[i<20 ? 0 : i-20..i]; | |
20 auto e = input[i+1..i+21>$ ? $ : i+21]; | |
21 | |
22 throw new Exception("Lex: " ~ | |
23 (type == 0 ? "Illegal character" : | |
24 type == 1 ? "Wrong number of parenthesis" : | |
25 "Unexpected end of input") ~ | |
26 ": " ~ b ~ " >>>" ~ input[i] ~ "<<< " ~ e ~ "." | |
27 ); | |
28 } | |
29 void begin(size_t i) { sidx = i; } | |
30 void end(size_t i) { tokens ~= input[sidx..i]; } | |
31 | |
32 foreach(size_t i, c; input) { | |
33 if (sidx > i) continue; | |
34 switch(c) { // states space, token, textEnd | |
35 case '"': // starts a ""-string | |
36 switch(state) { | |
37 case 0: | |
38 char[] buf; | |
39 bool escape; | |
40 char d; | |
41 sidx = i; | |
42 while(!((d = input[++sidx]) == '"' && !escape) && sidx<input.length) | |
43 if (escape) { | |
44 if (d != '"' && d != '\\') buf ~= '\\'; | |
45 buf ~= d; | |
46 escape = false; | |
47 } else if (d == '\\') | |
48 escape = true; | |
49 else | |
50 buf ~= d; | |
51 | |
52 sidx++; | |
53 tokens ~= buf; | |
54 state = 2; | |
55 continue; | |
56 default: err(i); | |
57 } | |
58 case '\\': | |
59 switch(state) { | |
60 case 0: begin(i); state = 1; continue; | |
61 case 1: continue; | |
62 case 2: err(i); | |
63 } | |
64 case '#': // starts a comment | |
65 sidx = i; | |
66 while (++sidx<input.length && input[sidx] != '\n') {} | |
67 continue; | |
68 case ' ': // whitespace | |
69 case '\t': | |
70 case '\n': | |
71 case '(': // begins a block | |
72 case ')': // ends a block | |
73 switch(state) { | |
74 case 1: end(i); | |
75 case 0: | |
76 case 2: | |
77 switch(c) { | |
78 case '(': tokens ~= "("; level++; state = 0; break; | |
79 case ')': tokens ~= ")"; if (!level--) err(i,1); | |
80 default: state = 0; | |
81 } | |
82 } | |
83 break; | |
84 default: | |
85 switch(state) { | |
86 case 0: begin(i); | |
87 case 1: state = 1; continue; | |
88 case 2: err(i); | |
89 } | |
90 } | |
91 } | |
92 | |
93 if (state == 3 || level != 0) err(input.length-1,2); | |
94 if (state > 0) end(input.length); | |
95 | |
96 debug { | |
97 foreach(i, tok; tokens) | |
98 Stdout.format("{}{}", tok, (i != tokens.length-1 ? " " : "")); | |
99 Stdout.newline; | |
100 } | |
101 | |
102 return tokens; | |
103 } | |
104 | |
105 /** | |
106 * Parser a s-exp like input used by the config files. | |
107 */ | |
108 char[][][char[]] parse(char[][] tokens) { | |
109 char[][][char[]] values; | |
110 size_t i = 1; | |
111 | |
112 void err(size_t j) { | |
113 auto b = tokens[j < 5 ? 0 : j-5..j]; | |
114 auto e = tokens[j+1..j+6>$ ? $ : j+6]; | |
115 char[] tmp; | |
116 foreach(t; b) tmp ~= t ~ " "; | |
117 tmp ~= ">>>" ~ tokens[j] ~ "<<< "; | |
118 foreach(t; e) tmp ~= t ~ " "; | |
119 | |
120 throw new Exception( | |
121 "Parse: Illegal token: " ~ tmp ~ "." | |
122 ); | |
123 } | |
124 | |
125 if (tokens[0] != "(") err(0); | |
126 | |
127 void doParse(char[] prefix = null) { | |
128 if (tokens[i] == "(" || | |
129 tokens[i] == ")") err(i); | |
130 if (prefix) prefix ~= "."; | |
131 auto v = prefix ~ tokens[i++]; | |
132 //values[v] = null; | |
133 while (tokens[i] != ")") | |
134 if (tokens[i++] == "(") | |
135 doParse(v); | |
136 else | |
137 values[v] ~= tokens[i-1]; | |
138 i++; | |
139 } | |
140 | |
141 doParse(); | |
142 | |
143 return values; | |
144 } |