2 This file is part of libmspparser
3 Copyright © 2006 Mikko Rasa, Mikkosoft Productions
4 Distributed under the LGPL
10 #include "statement.h"
18 Parser::Parser(istream &i, const string &s):
24 Statement Parser::parse()
27 throw Exception("Parser is not good");
33 catch(const Exception &e)
40 Statement Parser::parse_(const Token *t)
57 if(result.keyword.empty())
61 else if(token.type!=Token::IDENTIFIER)
62 throw DataError(get_location()+": Syntax error at token '"+token.str+"' (expected an identifier)");
63 result.keyword=token.str;
66 result.line=in.get_line_number();
77 Statement ss=parse_(&token);
78 result.sub.push_back(ss);
84 throw DataError(get_location()+": Syntax error at token '"+token.str+"' (Expected a ';')");
87 else if(token.str=="{")
89 else if(token.str==";")
91 else if(token.type==Token::INTEGER)
92 result.args.push_back(Value(Value::INTEGER, token.str));
93 else if(token.type==Token::FLOAT)
94 result.args.push_back(Value(Value::FLOAT, token.str));
95 else if(token.type==Token::STRING)
96 result.args.push_back(Value(Value::STRING, token.str));
97 else if(token.type==Token::IDENTIFIER)
99 //result.args.push_back(resolve_identifiertoken.str);
101 else if(token.str=="")
102 throw DataError(src+": Unexcepted EOF");
104 throw DataError(get_location()+": Syntax error");
110 Token Parser::parse_token()
119 //cout<<c<<' '<<next<<'\n';
121 if(c=='/' && next=='/')
123 else if(c=='/' && next=='*')
125 else if(c=='\n' && comment==1)
127 else if(c=='*' && next=='/' && comment==2)
129 else if(comment==3) // Skip the second character of block comment end
131 else if(!isspace(c) && !comment)
135 throw DataError(src+": Unfinished comment");
151 static Token::Type token_type[]=
165 ParseState state=INIT;
188 else if(c=='{' || c=='}' || c==';')
189 return Token(Token::SPECIAL, string(1, c));
195 parse_error(c, state);
206 parse_error(c, state);
217 parse_error(c, state);
224 parse_error(c, state);
229 parse_error(c, state);
234 parse_error(c, state);
239 parse_error(c, state);
245 else if(c=='"' && !escape)
246 return Token(Token::STRING, unescape_string(buf));
252 if(!isalpha(c) && !isdigit(c) && c!='_')
253 parse_error(c, state);
257 throw Exception(get_location()+": Internal error (bad state)");
260 if(is_delimiter(next) && state>=ACCEPT)
261 return Token(token_type[state], buf);
264 return Token(Token::SPECIAL, "");
267 bool Parser::is_delimiter(int c)
269 return (isspace(c) || c=='{' || c=='}' || c==';' || c=='/');
272 bool Parser::isodigit(int c)
274 return (c>='0' && c<='7');
277 string Parser::unescape_string(const string &str)
282 for(string::const_iterator i=str.begin()+1; i!=str.end()-1; ++i)
297 throw DataError("Invalid escape");
303 if(*i>='0' && *i<='9')
305 else if(*i>='a' && *i<='f')
307 else if(*i>='A' && *i<='F')
310 throw DataError("Invalid hex digit");
312 hexcape=(hexcape<<4)|digit;
315 result+=hexcape&0xFF;
328 string Parser::get_location()
331 ss<<src<<':'<<in.get_line_number();
335 void Parser::parse_error(int c, int state)
338 ss<<get_location()<<": Parse error at '"<<c<<"' (state "<<state<<')';
339 throw DataError(ss.str());
342 } // namespace Parser