X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbinaryparser.cpp;fp=source%2Fbinaryparser.cpp;h=051133f79a32cecb540c021f87b6930f5e168566;hb=3b78eeb8b92dc3524d6a0456b4daf0a0f3dbf813;hp=098a5fd4f96c936cad7aae6bfba31b0627c357ef;hpb=a82776d980239e48d2b509d33b56e77a1ea44dda;p=libs%2Fdatafile.git diff --git a/source/binaryparser.cpp b/source/binaryparser.cpp index 098a5fd..051133f 100644 --- a/source/binaryparser.cpp +++ b/source/binaryparser.cpp @@ -2,9 +2,11 @@ #include #include #include +#include "argumentstore.h" #include "binaryparser.h" #include "binfloat.h" #include "input.h" +#include "loaderaction.h" using namespace std; @@ -21,31 +23,48 @@ public: virtual ~bad_definition() throw() { } }; +class nesting_error: public logic_error +{ +public: + nesting_error(const std::string &w): + logic_error(w) + { } + + virtual ~nesting_error() throw() { } +}; + BinaryParser::BinaryParser(Input &i, const string &s): ParserMode(i, s), - float_precision(32) + float_precision(32), + cur_info(0) { - dict[-1] = StatementKey("__kwd", "iss"); - dict[-2] = StatementKey("__str", "is"); - dict[-3] = StatementKey("__flt", "i"); + dict[-1] = StatementInfo("__kwd", "iss"); + dict[-2] = StatementInfo("__str", "is"); + dict[-3] = StatementInfo("__flt", "i"); } Statement BinaryParser::parse() { - int id = parse_int(); - if(!in) - return Statement(); + const StatementKey *key; + if(cur_info) + key = &cur_info->key; + else + { + int id = parse_int(); + if(!in) + return Statement(); - const StatementKey &key = get_item(dict, id); + key = &get_item(dict, id).key; + } Statement result; - result.keyword = key.keyword; + result.keyword = key->keyword; result.source = src; - for(unsigned j=0; jsignature.size(); ++j) { - switch(key.signature[j]) + switch(key->signature[j]) { case IntType::signature: result.args.push_back(parse_int()); @@ -65,11 +84,15 @@ Statement BinaryParser::parse() } } + if(!sub_remaining.empty()) + --sub_remaining.back(); + unsigned nsub = parse_int(); for(unsigned j = 0; j(); } +const StatementKey *BinaryParser::peek(unsigned level) +{ + if(level>sub_remaining.size()) + throw nesting_error("bad level"); + while(level0; ) + parse(); + sub_remaining.pop_back(); + cur_info = 0; + } + + if(!sub_remaining.empty() && sub_remaining.back()==0) + { + // No more substatements on this level + cur_info = 0; + return 0; + } + + if(cur_info) + return &cur_info->key; + + int id = parse_int(); + if(!in) + return 0; + + cur_info = &get_item(dict, id); + return &cur_info->key; +} + +bool BinaryParser::parse_and_load(unsigned level, Loader &ldr, const LoaderAction &act) +{ + if(!cur_info && !peek(level)) + return false; + + ArgumentStore args(*cur_info); + for(unsigned i=0; ikey.signature.size(); ++i) + switch(cur_info->key.signature[i]) + { + case IntType::signature: + args.set(i, parse_int()); + break; + case FloatType::signature: + args.set(i, parse_float()); + break; + case BoolType::signature: + args.set(i, parse_bool()); + break; + case StringType::signature: + args.set(i, parse_string()); + break; + case SymbolType::signature: + args.set(i, parse_symbol()); + break; + } + + if(!sub_remaining.empty()) + --sub_remaining.back(); + sub_remaining.push_back(parse_int()); + cur_info = 0; + + act.execute(ldr, args); + + return true; +} + IntType::Store BinaryParser::parse_int() { IntType::Store result = 0;