X-Git-Url: http://git.tdb.fi/?p=libs%2Fdatafile.git;a=blobdiff_plain;f=source%2Fparser.cpp;h=5972e2d98f832d312afa4373bfe66d4204d10f8f;hp=7b9af11d60ca292a860ae346cebcb813220e5469;hb=ed78b585cfc4ecb44972e346857e887b183fd7a7;hpb=36e888dd1208822ae6df13b63f32c97d36b0a616 diff --git a/source/parser.cpp b/source/parser.cpp index 7b9af11..5972e2d 100644 --- a/source/parser.cpp +++ b/source/parser.cpp @@ -1,349 +1,111 @@ -/* -This file is part of libmspparser -Copyright © 2006 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ -#include -#include -#include +#include +#include "binaryparser.h" +#include "except.h" #include "parser.h" #include "statement.h" -#include "token.h" +#include "textparser.h" using namespace std; namespace Msp { -namespace Parser { +namespace DataFile { -Parser::Parser(istream &i, const string &s): +Parser::Parser(IO::Base &i, const string &s): in(i), + main_src(s), src(s), - good(true) + good(true), + mode(new TextParser(in, src)) { } -Statement Parser::parse() +Parser::~Parser() { - if(!good) - throw Exception("Parser is not good"); - - try - { - return parse_(0); - } - catch(const Exception &e) - { - good=false; - throw; - } + delete mode; } -Statement Parser::parse_(const Token *t) +Statement Parser::parse(bool raw) { - Statement result; - bool sub=false; - bool finish=false; - - while(in) + if(!good) + throw logic_error("Parser::parse() !good"); + + try { - Token token; - if(t) - { - token=*t; - t=0; - } - else - token=parse_token(); - - if(result.keyword.empty()) + while(1) { - if(token.str.empty()) - break; - else if(token.type!=Token::IDENTIFIER) - throw DataError(get_location()+": Syntax error at token '"+token.str+"' (expected an identifier)"); - result.keyword=token.str; - result.valid=true; - result.source=src; - result.line=in.get_line_number(); - } - else if(sub) - { - if(token.str=="}") - { - sub=false; - finish=true; - } - else + Statement st = mode->parse(); + if(!st.keyword.compare(0, 2, "__")) { - Statement ss=parse_(&token); - result.sub.push_back(ss); + st.control = true; + process_control_statement(st); } + + if(raw || !st.control) + return st; + else if(!good) // This will occur with an __end statement + return Statement(); } - else if(finish) - { - if(token.str!=";") - throw DataError(get_location()+": Syntax error at token '"+token.str+"' (Expected a ';')"); - break; - } - else if(token.str=="{") - sub=true; - else if(token.str==";") - break; - else if(token.type==Token::INTEGER) - result.args.push_back(Value(Value::INTEGER, token.str)); - else if(token.type==Token::FLOAT) - result.args.push_back(Value(Value::FLOAT, token.str)); - else if(token.type==Token::STRING) - result.args.push_back(Value(Value::STRING, token.str)); - else if(token.type==Token::IDENTIFIER) - { - if(token.str=="true") - result.args.push_back(Value(Value::BOOLEAN, "1")); - else if(token.str=="false") - result.args.push_back(Value(Value::BOOLEAN, "0")); - else - result.args.push_back(Value(Value::ENUM, token.str)); - //result.args.push_back(resolve_identifiertoken.str); - } - else if(token.str=="") - throw DataError(src+": Unexcepted EOF"); + } + catch(const exception &e) + { + good = false; + if(dynamic_cast(&e)) + throw; else - throw DataError(get_location()+": Syntax error"); + throw data_error(src, in.get_line_number(), e); } - - return result; } -Token Parser::parse_token() +void Parser::process_control_statement(const Statement &st) { - int c; - unsigned comment=0; - while(in) + if(st.keyword=="__bin") { - c=in.get(); - int next=in.peek(); - - //cout<=ACCEPT) - return Token(token_type[state], buf); + string s = st.args[0].get(); + if(s.empty()) + src = main_src; + else + src = format("%s[%s]", main_src, s); } - - return Token(Token::SPECIAL, ""); + else if(st.keyword=="__end") + good = false; + else + mode->process_control_statement(st); } -bool Parser::is_delimiter(int c) +const StatementKey *Parser::peek(unsigned level) { - return (isspace(c) || c=='{' || c=='}' || c==';' || c=='/'); -} - -bool Parser::isodigit(int c) -{ - return (c>='0' && c<='7'); -} - -string Parser::unescape_string(const string &str) -{ - string result; - bool escape=false; - unsigned hexcape=0; - for(string::const_iterator i=str.begin()+1; i!=str.end()-1; ++i) + while(good) { - if(escape) - { - if(*i=='n') - result+='\n'; - else if(*i=='t') - result+='\t'; - else if(*i=='\\') - result+='\\'; - else if(*i=='"') - result+='"'; - else if(*i=='x') - hexcape=0x100; - else - throw DataError("Invalid escape"); - escape=false; - } - else if(hexcape) - { - unsigned digit=0; - if(*i>='0' && *i<='9') - digit=*i-'0'; - else if(*i>='a' && *i<='f') - digit=*i-'a'+10; - else if(*i>='A' && *i<='F') - digit=*i-'A'+10; - else - throw DataError("Invalid hex digit"); - - hexcape=(hexcape<<4)|digit; - if(hexcape&0x10000) - { - result+=hexcape&0xFF; - hexcape=0; - } - } - else if(*i=='\\') - escape=true; + const StatementKey *key = mode->peek(level); + if(key && !key->keyword.compare(0, 2, "__")) + process_control_statement(mode->parse()); else - result+=*i; + return key; } - return result; -} - -string Parser::get_location() -{ - ostringstream ss; - ss<parse_and_load(level, ldr, act); } -} // namespace Parser +} // namespace DataFile } // namespace Msp