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)
36 token = parse_token();
38 if(result.keyword.empty())
42 else if(token.type!=Token::IDENTIFIER)
43 throw syntax_error(token.str);
44 result.keyword = token.str;
47 result.line = in.get_line_number();
55 Statement ss = parse_statement(&token);
56 result.sub.push_back(ss);
62 throw syntax_error(token.str);
65 else if(token.str=="{")
67 else if(token.str==";")
69 else if(token.type==Token::INTEGER)
70 result.append(lexical_cast<IntType::Store>(token.str));
71 else if(token.type==Token::FLOAT)
72 result.append(lexical_cast<FloatType::Store>(token.str));
73 else if(token.type==Token::STRING)
74 result.append(token.str);
75 else if(token.type==Token::IDENTIFIER)
79 else if(token.str=="false")
82 result.append(Symbol(token.str));
85 throw syntax_error(token.str);
91 Token TextParser::parse_token()
96 // Skip over comments and whitespace
97 while(in && comment>=0)
100 int next = in.peek();
102 if(c=='/' && next=='/' && !comment)
104 else if(c=='/' && next=='*' && !comment)
106 else if(c=='\n' && comment==1)
108 else if(c=='*' && next=='/' && comment==2)
110 else if(comment==3) // Skip the second character of block comment end
112 else if(c!=-1 && !isspace(c) && !comment)
116 if(comment>0) // EOF while in comment
117 throw parse_error(string());
118 else if(comment==0) // Didn't hit any non-whitespace
119 return Token(Token::SPECIAL, "");
140 static Token::Type token_type[]=
159 ParseState state = INIT;
162 while(in || state==INIT)
166 int next = in.peek();
175 else if(c=='-' || c=='+')
181 else if(c=='{' || c=='}' || c==';')
182 return Token(Token::SPECIAL, string(1, c));
185 else if(isalpha(c) || c=='_' || c=='\\')
188 throw parse_error(buf);
199 throw parse_error(buf);
210 throw parse_error(buf);
216 else if(c=='e' || c=='E')
217 state = FLOATEXPINIT;
219 throw parse_error(buf);
224 throw parse_error(buf);
229 throw parse_error(buf);
234 state = FLOATEXPINIT;
236 throw parse_error(buf);
241 state = FLOATEXPSIGN;
245 throw parse_error(buf);
252 throw parse_error(buf);
257 throw parse_error(buf);
262 state = STRING_ESCAPE;
272 if(!isalpha(c) && !isdigit(c) && c!='_' && c!='-' && c!='/')
273 throw parse_error(buf);
277 throw parse_error(buf);
280 throw logic_error("bad parser state");
283 if(is_delimiter(next) && state>=ACCEPT)
285 if(state==IDENTIFIER && buf[0]=='\\')
286 return Token(Token::IDENTIFIER, buf.substr(1));
287 else if(state==STRING_END)
288 return Token(Token::STRING, c_unescape(buf.substr(1, buf.size()-2)));
290 return Token(token_type[state], buf);
294 return Token(Token::SPECIAL, "");
297 bool TextParser::is_delimiter(int c)
299 return (isspace(c) || c=='{' || c=='}' || c==';' || c=='/');
302 bool TextParser::isodigit(int c)
304 return (c>='0' && c<='7');
307 } // namespace DataFile