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 ParseError(get_location()+": Syntax error at token '"+token.str+"' (expected an identifier)", src, in.get_line_number());
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 ParseError(get_location()+": Syntax error at token '"+token.str+"' (Expected a ';')", src, in.get_line_number());
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)
100 result.args.push_back(Value(Value::BOOLEAN, "1"));
101 else if(token.str=="false")
102 result.args.push_back(Value(Value::BOOLEAN, "0"));
104 result.args.push_back(Value(Value::ENUM, token.str));
105 //result.args.push_back(resolve_identifiertoken.str);
107 else if(token.str=="")
108 throw ParseError(src+": Unexcepted EOF", src, in.get_line_number());
110 throw ParseError(get_location()+": Syntax error", src, in.get_line_number());
116 Token Parser::parse_token()
121 // Skip over comments and whitespace
127 if(c=='/' && next=='/')
129 else if(c=='/' && next=='*')
131 else if(c=='\n' && comment==1)
133 else if(c=='*' && next=='/' && comment==2)
135 else if(comment==3) // Skip the second character of block comment end
137 else if(!isspace(c) && !comment)
141 if(comment) // Didn't hit any non-whitespace
142 throw ParseError(src+": Unfinished comment", src, in.get_line_number());
161 static Token::Type token_type[]=
178 ParseState state=INIT;
195 else if(c=='-' || c=='+')
201 else if(c=='{' || c=='}' || c==';')
202 return Token(Token::SPECIAL, string(1, c));
208 parse_error(c, state);
219 parse_error(c, state);
230 parse_error(c, state);
237 parse_error(c, state);
242 parse_error(c, state);
247 parse_error(c, state);
254 parse_error(c, state);
263 parse_error(c, state);
270 parse_error(c, state);
275 parse_error(c, state);
281 else if(c=='"' && !escape)
282 return Token(Token::STRING, unescape_string(buf));
288 if(!isalpha(c) && !isdigit(c) && c!='_')
289 parse_error(c, state);
293 throw Exception(get_location()+": Internal error (bad state)");
296 if(is_delimiter(next) && state>=ACCEPT)
297 return Token(token_type[state], buf);
300 return Token(Token::SPECIAL, "");
303 bool Parser::is_delimiter(int c)
305 return (isspace(c) || c=='{' || c=='}' || c==';' || c=='/');
308 bool Parser::isodigit(int c)
310 return (c>='0' && c<='7');
313 string Parser::unescape_string(const string &str)
318 for(string::const_iterator i=str.begin()+1; i!=str.end()-1; ++i)
333 throw ParseError("Invalid escape", src, in.get_line_number());
339 if(*i>='0' && *i<='9')
341 else if(*i>='a' && *i<='f')
343 else if(*i>='A' && *i<='F')
346 throw ParseError("Invalid hex digit", src, in.get_line_number());
348 hexcape=(hexcape<<4)|digit;
351 result+=hexcape&0xFF;
364 string Parser::get_location()
367 ss<<src<<':'<<in.get_line_number();
371 void Parser::parse_error(int c, int state)
374 ss<<get_location()<<": Parse error at '"<<(char)c<<"' (state "<<state<<')';
375 throw ParseError(ss.str(), src, in.get_line_number());
378 } // namespace Parser