1 |
/* ANTLR Translator Generator |
2 |
* Project led by Terence Parr at http://www.jGuru.com |
3 |
* Software rights: http://www.antlr.org/license.html |
4 |
* |
5 |
* $Id$ |
6 |
*/ |
7 |
|
8 |
#include <antlr/config.hpp> |
9 |
#include <antlr/IOException.hpp> |
10 |
|
11 |
#include <iostream> |
12 |
#include <cctype> |
13 |
#include <string> |
14 |
|
15 |
#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE |
16 |
namespace antlr { |
17 |
#endif |
18 |
|
19 |
/** Eat whitespace from the input stream |
20 |
* @param is the stream to read from |
21 |
*/ |
22 |
ANTLR_USE_NAMESPACE(std)istream& eatwhite( ANTLR_USE_NAMESPACE(std)istream& is ) |
23 |
{ |
24 |
char c; |
25 |
while( is.get(c) ) |
26 |
{ |
27 |
#ifdef ANTLR_CCTYPE_NEEDS_STD |
28 |
if( !ANTLR_USE_NAMESPACE(std)isspace(c) ) |
29 |
#else |
30 |
if( !isspace(c) ) |
31 |
#endif |
32 |
{ |
33 |
is.putback(c); |
34 |
break; |
35 |
} |
36 |
} |
37 |
return is; |
38 |
} |
39 |
|
40 |
/** Read a string enclosed by '"' from a stream. Also handles escaping of \". |
41 |
* Skips leading whitespace. |
42 |
* @param in the istream to read from. |
43 |
* @returns the string read from file exclusive the '"' |
44 |
* @throws IOException if string is badly formatted |
45 |
*/ |
46 |
ANTLR_USE_NAMESPACE(std)string read_string( ANTLR_USE_NAMESPACE(std)istream& in ) |
47 |
{ |
48 |
char ch; |
49 |
ANTLR_USE_NAMESPACE(std)string ret(""); |
50 |
// States for a simple state machine... |
51 |
enum { START, READING, ESCAPE, FINISHED }; |
52 |
int state = START; |
53 |
|
54 |
eatwhite(in); |
55 |
|
56 |
while( state != FINISHED && in.get(ch) ) |
57 |
{ |
58 |
switch( state ) |
59 |
{ |
60 |
case START: |
61 |
// start state: check wether starting with " then switch to READING |
62 |
if( ch != '"' ) |
63 |
throw IOException("string must start with '\"'"); |
64 |
state = READING; |
65 |
continue; |
66 |
case READING: |
67 |
// reading state: look out for escape sequences and closing " |
68 |
if( ch == '\\' ) // got escape sequence |
69 |
{ |
70 |
state = ESCAPE; |
71 |
continue; |
72 |
} |
73 |
if( ch == '"' ) // close quote -> stop |
74 |
{ |
75 |
state = FINISHED; |
76 |
continue; |
77 |
} |
78 |
ret += ch; // else append... |
79 |
continue; |
80 |
case ESCAPE: |
81 |
switch(ch) |
82 |
{ |
83 |
case '\\': |
84 |
ret += ch; |
85 |
state = READING; |
86 |
continue; |
87 |
case '"': |
88 |
ret += ch; |
89 |
state = READING; |
90 |
continue; |
91 |
case '0': |
92 |
ret += '\0'; |
93 |
state = READING; |
94 |
continue; |
95 |
default: // unrecognized escape is not mapped |
96 |
ret += '\\'; |
97 |
ret += ch; |
98 |
state = READING; |
99 |
continue; |
100 |
} |
101 |
} |
102 |
} |
103 |
if( state != FINISHED ) |
104 |
throw IOException("badly formatted string: "+ret); |
105 |
|
106 |
return ret; |
107 |
} |
108 |
|
109 |
/* Read a ([A-Z][0-9][a-z]_)* kindoff thing. Skips leading whitespace. |
110 |
* @param in the istream to read from. |
111 |
*/ |
112 |
ANTLR_USE_NAMESPACE(std)string read_identifier( ANTLR_USE_NAMESPACE(std)istream& in ) |
113 |
{ |
114 |
char ch; |
115 |
ANTLR_USE_NAMESPACE(std)string ret(""); |
116 |
|
117 |
eatwhite(in); |
118 |
|
119 |
while( in.get(ch) ) |
120 |
{ |
121 |
#ifdef ANTLR_CCTYPE_NEEDS_STD |
122 |
if( ANTLR_USE_NAMESPACE(std)isupper(ch) || |
123 |
ANTLR_USE_NAMESPACE(std)islower(ch) || |
124 |
ANTLR_USE_NAMESPACE(std)isdigit(ch) || |
125 |
ch == '_' ) |
126 |
#else |
127 |
if( isupper(ch) || islower(ch) || isdigit(ch) || ch == '_' ) |
128 |
#endif |
129 |
ret += ch; |
130 |
else |
131 |
{ |
132 |
in.putback(ch); |
133 |
break; |
134 |
} |
135 |
} |
136 |
return ret; |
137 |
} |
138 |
|
139 |
/** Read a attribute="value" thing. Leading whitespace is skipped. |
140 |
* Between attribute and '=' no whitespace is allowed. After the '=' it is |
141 |
* permitted. |
142 |
* @param in the istream to read from. |
143 |
* @param attribute string the attribute name is put in |
144 |
* @param value string the value of the attribute is put in |
145 |
* @throws IOException if something is fishy. E.g. malformed quoting |
146 |
* or missing '=' |
147 |
*/ |
148 |
void read_AttributeNValue( ANTLR_USE_NAMESPACE(std)istream& in, |
149 |
ANTLR_USE_NAMESPACE(std)string& attribute, |
150 |
ANTLR_USE_NAMESPACE(std)string& value ) |
151 |
{ |
152 |
attribute = read_identifier(in); |
153 |
|
154 |
char ch; |
155 |
if( in.get(ch) && ch == '=' ) |
156 |
value = read_string(in); |
157 |
else |
158 |
throw IOException("invalid attribute=value thing "+attribute); |
159 |
} |
160 |
|
161 |
#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE |
162 |
} |
163 |
#endif |