1 #include <msp/strings/format.h>
2 #include <msp/strings/utils.h>
5 #include "textparser.h"
13 TextParser::TextParser(Input &i, const string &s):
17 Statement TextParser::parse()
19 return parse_statement(0);
22 Statement TextParser::parse_statement(const Token *t)
37 token = parse_token();
39 if(result.keyword.empty())
43 else if(token.type!=Token::IDENTIFIER)
44 throw syntax_error(token.str);
45 result.keyword = token.str;
48 result.line = in.get_line_number();
59 Statement ss = parse_statement(&token);
60 result.sub.push_back(ss);
66 throw syntax_error(token.str);
69 else if(token.str=="{")
71 else if(token.str==";")
73 else if(token.type==Token::INTEGER)
74 result.append(lexical_cast<IntType::Store>(token.str));
75 else if(token.type==Token::FLOAT)
76 result.append(lexical_cast<FloatType::Store>(token.str));
77 else if(token.type==Token::STRING)
78 result.append(token.str);
79 else if(token.type==Token::IDENTIFIER)
83 else if(token.str=="false")
86 result.append(Symbol(token.str));
89 throw syntax_error(token.str);
95 Token TextParser::parse_token()
100 // Skip over comments and whitespace
101 while(in && comment>=0)
104 int next = in.peek();
106 if(c=='/' && next=='/' && !comment)
108 else if(c=='/' && next=='*' && !comment)
110 else if(c=='\n' && comment==1)
112 else if(c=='*' && next=='/' && comment==2)
114 else if(comment==3) // Skip the second character of block comment end
116 else if(c!=-1 && !isspace(c) && !comment)
120 if(comment>0) // EOF while in comment
121 throw parse_error(string());
122 else if(comment==0) // Didn't hit any non-whitespace
123 return Token(Token::SPECIAL, "");
143 static Token::Type token_type[]=
161 ParseState state = INIT;
165 while(in || state==INIT)
169 int next = in.peek();
178 else if(c=='-' || c=='+')
184 else if(c=='{' || c=='}' || c==';')
185 return Token(Token::SPECIAL, string(1, c));
188 else if(isalpha(c) || c=='_' || c=='\\')
191 throw parse_error(buf);
202 throw parse_error(buf);
213 throw parse_error(buf);
219 else if(c=='e' || c=='E')
220 state = FLOATEXPINIT;
222 throw parse_error(buf);
227 throw parse_error(buf);
232 throw parse_error(buf);
237 state = FLOATEXPINIT;
239 throw parse_error(buf);
244 state = FLOATEXPSIGN;
248 throw parse_error(buf);
255 throw parse_error(buf);
260 throw parse_error(buf);
266 else if(c=='"' && !escape)
273 if(!isalpha(c) && !isdigit(c) && c!='_' && c!='-' && c!='/')
274 throw parse_error(buf);
278 throw parse_error(buf);
281 throw logic_error("bad parser state");
284 if(is_delimiter(next) && state>=ACCEPT)
286 if(state==IDENTIFIER && buf[0]=='\\')
287 return Token(Token::IDENTIFIER, buf.substr(1));
288 else if(state==STRING_END)
289 return Token(Token::STRING, c_unescape(buf.substr(1, buf.size()-2)));
291 return Token(token_type[state], buf);
295 return Token(Token::SPECIAL, "");
298 bool TextParser::is_delimiter(int c)
300 return (isspace(c) || c=='{' || c=='}' || c==';' || c=='/');
303 bool TextParser::isodigit(int c)
305 return (c>='0' && c<='7');
308 } // namespace DataFile