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 }