int main( int argc, const char* argv[]) { int rt = 0; std::auto_ptr<strus::ErrorBufferInterface> errorBuffer( strus::createErrorBuffer_standard( 0, 2)); if (!errorBuffer.get()) { std::cerr << _TXT("failed to create error buffer") << std::endl; return -1; } strus::ProgramOptions opt; bool printUsageAndExit = false; try { opt = strus::ProgramOptions( argc, argv, 11, "h,help", "v,version", "license", "t,tokenizer:", "n,normalizer:", "m,module:", "M,moduledir:", "q,quot:", "p,plain", "R,resourcedir:", "T,trace:"); if (opt( "help")) printUsageAndExit = true; std::auto_ptr<strus::ModuleLoaderInterface> moduleLoader( strus::createModuleLoader( errorBuffer.get())); if (!moduleLoader.get()) throw strus::runtime_error(_TXT("failed to create module loader")); if (opt("moduledir")) { std::vector<std::string> modirlist( opt.list("moduledir")); std::vector<std::string>::const_iterator mi = modirlist.begin(), me = modirlist.end(); for (; mi != me; ++mi) { moduleLoader->addModulePath( *mi); } moduleLoader->addSystemModulePath(); } if (opt("module")) { std::vector<std::string> modlist( opt.list("module")); std::vector<std::string>::const_iterator mi = modlist.begin(), me = modlist.end(); for (; mi != me; ++mi) { if (!moduleLoader->loadModule( *mi)) { throw strus::runtime_error(_TXT("error failed to load module %s"), mi->c_str()); } } } if (opt("license")) { std::vector<std::string> licenses_3rdParty = moduleLoader->get3rdPartyLicenseTexts(); std::vector<std::string>::const_iterator ti = licenses_3rdParty.begin(), te = licenses_3rdParty.end(); if (ti != te) std::cout << _TXT("3rd party licenses:") << std::endl; for (; ti != te; ++ti) { std::cout << *ti << std::endl; } std::cerr << std::endl; if (!printUsageAndExit) return 0; } if (opt( "version")) { std::cout << _TXT("Strus utilities version ") << STRUS_UTILITIES_VERSION_STRING << std::endl; std::cout << _TXT("Strus module version ") << STRUS_MODULE_VERSION_STRING << std::endl; std::cout << _TXT("Strus rpc version ") << STRUS_RPC_VERSION_STRING << std::endl; std::cout << _TXT("Strus trace version ") << STRUS_TRACE_VERSION_STRING << std::endl; std::cout << _TXT("Strus analyzer version ") << STRUS_ANALYZER_VERSION_STRING << std::endl; std::cout << _TXT("Strus base version ") << STRUS_BASE_VERSION_STRING << std::endl; std::vector<std::string> versions_3rdParty = moduleLoader->get3rdPartyVersionTexts(); std::vector<std::string>::const_iterator vi = versions_3rdParty.begin(), ve = versions_3rdParty.end(); if (vi != ve) std::cout << _TXT("3rd party versions:") << std::endl; for (; vi != ve; ++vi) { std::cout << *vi << std::endl; } if (!printUsageAndExit) return 0; } else if (!printUsageAndExit) { if (opt.nofargs() > 1) { std::cerr << _TXT("too many arguments") << std::endl; printUsageAndExit = true; rt = 1; } if (opt.nofargs() < 1) { std::cerr << _TXT("too few arguments") << std::endl; printUsageAndExit = true; rt = 2; } } if (printUsageAndExit) { std::cout << _TXT("usage:") << " strusAnalyze [options] <phrasepath>" << std::endl; std::cout << "<phrasepath> = " << _TXT("path to phrase to analyze ('-' for stdin)") << std::endl; std::cout << "description: " << _TXT("tokenizes and normalizes a text segment") << std::endl; std::cout << " " << _TXT("and prints the result to stdout.") << std::endl; std::cout << _TXT("options:") << std::endl; std::cout << "-h|--help" << std::endl; std::cout << " " << _TXT("Print this usage and do nothing else") << std::endl; std::cout << "-v|--version" << std::endl; std::cout << " " << _TXT("Print the program version and do nothing else") << std::endl; std::cout << "--license" << std::endl; std::cout << " " << _TXT("Print 3rd party licences requiring reference") << std::endl; std::cout << "-m|--module <MOD>" << std::endl; std::cout << " " << _TXT("Load components from module <MOD>") << std::endl; std::cout << "-M|--moduledir <DIR>" << std::endl; std::cout << " " << _TXT("Search modules to load first in <DIR>") << std::endl; std::cout << "-R|--resourcedir <DIR>" << std::endl; std::cout << " " << _TXT("Search resource files for analyzer first in <DIR>") << std::endl; std::cout << "-t|--tokenizer <CALL>" << std::endl; std::cout << " " << _TXT("Use the tokenizer <CALL> (default 'content')") << std::endl; std::cout << "-n|--normalizer <CALL>" << std::endl; std::cout << " " << _TXT("Use the normalizer <CALL> (default 'orig')") << std::endl; std::cout << "-q|--quot <STR>" << std::endl; std::cout << " " << _TXT("Use the string <STR> as quote for the result (default \"\'\")") << std::endl; std::cout << "-p|--plain" << std::endl; std::cout << " " << _TXT("Do not print position and define default quotes as empty") << std::endl; std::cout << "-T|--trace <CONFIG>" << std::endl; std::cout << " " << _TXT("Print method call traces configured with <CONFIG>") << std::endl; std::cout << " " << strus::string_format( _TXT("Example: %s"), "-T \"log=dump;file=stdout\"") << std::endl; return rt; } // Declare trace proxy objects: typedef strus::Reference<strus::TraceProxy> TraceReference; std::vector<TraceReference> trace; if (opt("trace")) { std::vector<std::string> tracecfglist( opt.list("trace")); std::vector<std::string>::const_iterator ti = tracecfglist.begin(), te = tracecfglist.end(); for (; ti != te; ++ti) { trace.push_back( new strus::TraceProxy( moduleLoader.get(), *ti, errorBuffer.get())); } } std::string resultQuot = "'"; bool resultPlain = false; if (opt( "plain")) { resultPlain = true; resultQuot.clear(); } if (opt( "quot")) { resultQuot = opt[ "quot"]; } std::string docpath = opt[0]; std::string tokenizer( "content"); if (opt( "tokenizer")) { tokenizer = opt[ "tokenizer"]; } std::string normalizer( "orig"); if (opt( "normalizer")) { normalizer = opt[ "normalizer"]; } // Set paths for locating resources: if (opt("resourcedir")) { std::vector<std::string> pathlist( opt.list("resourcedir")); std::vector<std::string>::const_iterator pi = pathlist.begin(), pe = pathlist.end(); for (; pi != pe; ++pi) { moduleLoader->addResourcePath( *pi); } } // Create root object for analyzer: std::auto_ptr<strus::AnalyzerObjectBuilderInterface> analyzerBuilder( moduleLoader->createAnalyzerObjectBuilder()); if (!analyzerBuilder.get()) throw strus::runtime_error(_TXT("failed to create analyzer object builder")); // Create proxy objects if tracing enabled: { std::vector<TraceReference>::const_iterator ti = trace.begin(), te = trace.end(); for (; ti != te; ++ti) { strus::AnalyzerObjectBuilderInterface* proxy = (*ti)->createProxy( analyzerBuilder.get()); analyzerBuilder.release(); analyzerBuilder.reset( proxy); } } // Create objects for analyzer: std::auto_ptr<strus::QueryAnalyzerInterface> analyzer( analyzerBuilder->createQueryAnalyzer()); if (!analyzer.get()) throw strus::runtime_error(_TXT("failed to create analyzer")); const strus::TextProcessorInterface* textproc = analyzerBuilder->getTextProcessor(); if (!textproc) throw strus::runtime_error(_TXT("failed to get text processor")); // Create phrase type (tokenizer and normalizer): std::string phraseType; if (!strus::loadQueryAnalyzerPhraseType( *analyzer, textproc, phraseType, "", normalizer, tokenizer, errorBuffer.get())) { throw strus::runtime_error(_TXT("failed to load analyze phrase type")); } // Load the phrase: std::string phrase; if (docpath == "-") { unsigned int ec = strus::readStdin( phrase); if (ec) throw strus::runtime_error( _TXT( "error reading input from stdin (errno %u)"), ec); } else { unsigned int ec = strus::readFile( docpath, phrase); if (ec) throw strus::runtime_error( _TXT( "error reading input file '%s' (errno %u)"), docpath.c_str(), ec); } // Analyze the phrase and print the result: std::vector<strus::analyzer::Term> terms = analyzer->analyzePhrase( phraseType, phrase); std::sort( terms.begin(), terms.end(), TermOrder()); std::vector<strus::analyzer::Term>::const_iterator ti = terms.begin(), te = terms.end(); for (; ti != te; ++ti) { if (!resultPlain) { std::cout << ti->pos() << " "; } std::cout << resultQuot << ti->value() << resultQuot << std::endl; } if (errorBuffer->hasError()) { throw strus::runtime_error(_TXT("error in analyze phrase")); } return 0; } catch (const std::bad_alloc&) { std::cerr << _TXT("ERROR ") << _TXT("out of memory") << std::endl; } catch (const std::runtime_error& e) { const char* errormsg = errorBuffer->fetchError(); if (errormsg) { std::cerr << _TXT("ERROR ") << e.what() << ": " << errormsg << std::endl; } else { std::cerr << _TXT("ERROR ") << e.what() << std::endl; } } catch (const std::exception& e) { std::cerr << _TXT("EXCEPTION ") << e.what() << std::endl; } return -1; }
// This doesn't rewrite changes through properly so needs to have a substitution // applied to its output. ASTNode PropagateEqualities::propagate(const ASTNode& a, ArrayTransformer* at) { ASTNode output; // if the variable has been solved for, then simply return it if (simp->InsideSubstitutionMap(a, output)) return output; if (!alreadyVisited.insert(a.GetNodeNum()).second) { return a; } output = a; // traverse a and populate the SubstitutionMap const Kind k = a.GetKind(); if (SYMBOL == k && BOOLEAN_TYPE == a.GetType()) { bool updated = simp->UpdateSubstitutionMap(a, ASTTrue); output = updated ? ASTTrue : a; } else if (NOT == k) { bool updated = searchXOR(a[0], ASTFalse); output = updated ? ASTTrue : a; } else if (IFF == k || EQ == k) { const ASTVec& c = a.GetChildren(); if (c[0] == c[1]) return ASTTrue; bool updated = simp->UpdateSubstitutionMap(c[0], c[1]); if (updated) { // fill the arrayname readindices vector if e0 is a // READ(Arr,index) and index is a BVCONST int to; if ((to = TermOrder(c[0], c[1])) == 1 && c[0].GetKind() == READ) at->FillUp_ArrReadIndex_Vec(c[0], c[1]); else if (to == -1 && c[1].GetKind() == READ) at->FillUp_ArrReadIndex_Vec(c[1], c[0]); } if (!updated) updated = searchTerm(c[0], c[1]); if (!updated) updated = searchTerm(c[1], c[0]); output = updated ? ASTTrue : a; } else if (XOR == k) { bool updated = searchXOR(a, ASTTrue); output = updated ? ASTTrue : a; if (updated) return output; // The below block should be subsumed by the searchXOR function which // generalises it. // So the below block should never do anything.. #ifndef NDEBUG if (a.Degree() != 2) return output; int to = TermOrder(a[0], a[1]); if (0 == to) { if (a[0].GetKind() == NOT && a[0][0].GetKind() == EQ && a[0][0][0].GetValueWidth() == 1 && a[0][0][1].GetKind() == SYMBOL) { // (XOR (NOT(= (1 v))) ... ) const ASTNode& symbol = a[0][0][1]; const ASTNode newN = nf->CreateTerm( ITE, 1, a[1], a[0][0][0], nf->CreateTerm(BVNEG, 1, a[0][0][0])); if (simp->UpdateSolverMap(symbol, newN)) { assert(false); output = ASTTrue; } } else if (a[1].GetKind() == NOT && a[1][0].GetKind() == EQ && a[1][0][0].GetValueWidth() == 1 && a[1][0][1].GetKind() == SYMBOL) { const ASTNode& symbol = a[1][0][1]; const ASTNode newN = nf->CreateTerm( ITE, 1, a[0], a[1][0][0], nf->CreateTerm(BVNEG, 1, a[1][0][0])); if (simp->UpdateSolverMap(symbol, newN)) { assert(false); output = ASTTrue; } } else if (a[0].GetKind() == EQ && a[0][0].GetValueWidth() == 1 && a[0][1].GetKind() == SYMBOL) { // XOR ((= 1 v) ... ) const ASTNode& symbol = a[0][1]; const ASTNode newN = nf->CreateTerm( ITE, 1, a[1], nf->CreateTerm(BVNEG, 1, a[0][0]), a[0][0]); if (simp->UpdateSolverMap(symbol, newN)) { assert(false); output = ASTTrue; } } else if (a[1].GetKind() == EQ && a[1][0].GetValueWidth() == 1 && a[1][1].GetKind() == SYMBOL) { const ASTNode& symbol = a[1][1]; const ASTNode newN = nf->CreateTerm( ITE, 1, a[0], nf->CreateTerm(BVNEG, 1, a[1][0]), a[1][0]); if (simp->UpdateSolverMap(symbol, newN)) { assert(false); output = ASTTrue; } } else return output; } else { ASTNode symbol, rhs; if (to == 1) { symbol = a[0]; rhs = a[1]; } else { symbol = a[1]; rhs = a[0]; } assert(symbol.GetKind() == SYMBOL); if (simp->UpdateSolverMap(symbol, nf->CreateNode(NOT, rhs))) { assert(false); output = ASTTrue; } } #endif } else if (AND == k) { const ASTVec& c = a.GetChildren(); ASTVec o; o.reserve(c.size()); for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend; it++) { if (always_true) simp->UpdateAlwaysTrueFormSet(*it); ASTNode aaa = propagate(*it, at); if (ASTTrue != aaa) { if (ASTFalse == aaa) return ASTFalse; else o.push_back(aaa); } } if (o.size() == 0) output = ASTTrue; else if (o.size() == 1) output = o[0]; else if (o != c) output = nf->CreateNode(AND, o); else output = a; } return output; }