static bool newInputStream(const std::string& filename, pANTLR3_LEXER lexer) { Debug("parser") << "Including " << filename << std::endl; // Create a new input stream and take advantage of built in stream stacking // in C target runtime. // pANTLR3_INPUT_STREAM in; #ifdef CVC4_ANTLR3_OLD_INPUT_STREAM in = antlr3AsciiFileStreamNew((pANTLR3_UINT8) filename.c_str()); #else /* CVC4_ANTLR3_OLD_INPUT_STREAM */ in = antlr3FileStreamNew((pANTLR3_UINT8) filename.c_str(), ANTLR3_ENC_8BIT); #endif /* CVC4_ANTLR3_OLD_INPUT_STREAM */ if( in == NULL ) { Debug("parser") << "Can't open " << filename << std::endl; return false; } // Same thing as the predefined PUSHSTREAM(in); lexer->pushCharStream(lexer, in); // restart it //lexer->rec->state->tokenStartCharIndex = -10; //lexer->emit(lexer); // Note that the input stream is not closed when it EOFs, I don't bother // to do it here, but it is up to you to track streams created like this // and destroy them when the whole parse session is complete. Remember that you // don't want to do this until all tokens have been manipulated all the way through // your tree parsers etc as the token does not store the text it just refers // back to the input stream and trying to get the text for it will abort if you // close the input stream too early. //TODO what said before return true; }
/*! Read expressions from file or memory and Evaluate */ int EvaluateExpressions(const char *buffer, int buf_length, int is_filename) { pANTLR3_INPUT_STREAM input_stream = NULL; pEvaLexer lxr = NULL; pANTLR3_COMMON_TOKEN_STREAM token_stream = NULL; pEvaParser psr = NULL; pEvaTree treeParser = NULL; pANTLR3_COMMON_TREE_NODE_STREAM nodes = NULL; EvaParser_program_return eva_ast; int error = 0; ResetErrorString(); /*Is it a file or memory*/ if (is_filename) { input_stream = antlr3AsciiFileStreamNew((pANTLR3_UINT8)buffer); } else { input_stream = antlr3NewAsciiStringCopyStream((pANTLR3_UINT8)buffer, (ANTLR3_UINT32)buf_length, NULL); } ABORT_IF(input_stream == NULL); /*Invoke lexer and tokenzie*/ lxr = EvaLexerNew(input_stream); ABORT_IF(lxr == NULL); token_stream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr)); ABORT_IF(token_stream == NULL); /*Parse the expression*/ psr = EvaParserNew(token_stream); ABORT_IF(psr == NULL); //psr->pParser->rec->recoverFromMismatchedElement = recoverFromMismatchedElement; psr->pParser->rec->displayRecognitionError = DisplayRecognitionError; /*create ast from the parser*/ eva_ast = psr->program(psr); /*check if there is parsing error*/ ABORT_IF(psr->pParser->rec->state->errorCount > 0); nodes = antlr3CommonTreeNodeStreamNewTree(eva_ast.tree, ANTLR3_SIZE_HINT); ABORT_IF(nodes == NULL); /*Walk the tree and evaluate the expression*/ treeParser = EvaTreeNew(nodes); ABORT_IF(treeParser == NULL); /*Take action*/ treeParser->program(treeParser); /*All done lets cleanup*/ clean_up: FREE(treeParser); FREE(nodes); FREE(psr); FREE(token_stream); FREE(lxr); FREE(input_stream); return error; }
int main(int argc, char *argv[]) { pANTLR3_INPUT_STREAM input; pANTLR3_COMMON_TOKEN_STREAM tstream; pGNUCaLexer lxr; pGNUCaParser psr; int ret = 1; if (argc != 2) goto err; ret++; input = antlr3AsciiFileStreamNew((unsigned char *)argv[1]); if (!input) goto err; ret++; lxr = GNUCaLexerNew(input); if (!lxr) goto err_input; ret++; tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr)); if (!tstream) goto err_lxr; ret++; psr = GNUCaParserNew(tstream); if (!psr) goto err_tstream; psr->translationUnit(psr); ret = 0; psr->free(psr); err_tstream: tstream->free(tstream); err_lxr: lxr->free(lxr); err_input: input->close(input); err: return ret; }
// Main entry point for this example // int ANTLR3_CDECL main (int argc, char *argv[]) { // Now we declare the ANTLR related local variables we need. // Note that unless you are convinced you will never need thread safe // versions for your project, then you should always create such things // as instance variables for each invocation. // ------------------- // Name of the input file. Note that we always use the abstract type pANTLR3_UINT8 // for ASCII/8 bit strings - the runtime library guarantees that this will be // good on all platforms. This is a general rule - always use the ANTLR3 supplied // typedefs for pointers/types/etc. // pANTLR3_UINT8 fName; // The ANTLR3 character input stream, which abstracts the input source such that // it is easy to provide input from different sources such as files, or // memory strings. // // For an ASCII/latin-1 memory string use: // input = antlr3NewAsciiStringInPlaceStream (stringtouse, (ANTLR3_UINT64) length, NULL); // // For a UCS2 (16 bit) memory string use: // input = antlr3NewUCS2StringInPlaceStream (stringtouse, (ANTLR3_UINT64) length, NULL); // // For input from a file, see code below // // Note that this is essentially a pointer to a structure containing pointers to functions. // You can create your own input stream type (copy one of the existing ones) and override any // individual function by installing your own pointer after you have created the standard // version. // pANTLR3_INPUT_STREAM input; // The lexer is of course generated by ANTLR, and so the lexer type is not upper case. // The lexer is supplied with a pANTLR3_INPUT_STREAM from whence it consumes its // input and generates a token stream as output. // pCLexer lxr; // The token stream is produced by the ANTLR3 generated lexer. Again it is a structure based // API/Object, which you can customise and override methods of as you wish. a Token stream is // supplied to the generated parser, and you can write your own token stream and pass this in // if you wish. // pANTLR3_COMMON_TOKEN_STREAM tstream; // The C parser is also generated by ANTLR and accepts a token stream as explained // above. The token stream can be any source in fact, so long as it implements the // ANTLR3_TOKEN_SOURCE interface. In this case the parser does not return anything // but it can of course specify any kind of return type from the rule you invoke // when calling it. // pCParser psr; // Create the input stream based upon the argument supplied to us on the command line // for this example, the input will always default to ./input if there is no explicit // argument. // if (argc < 2 || argv[1] == NULL) { fName =(pANTLR3_UINT8)"./input"; // Note in VS2005 debug, working directory must be configured } else { fName = (pANTLR3_UINT8)argv[1]; } // Create the input stream using the supplied file name // (Use antlr3AsciiFileStreamNew for UCS2/16bit input). // input = antlr3AsciiFileStreamNew(fName); // The input will be created successfully, providing that there is enough // memory and the file exists etc // if ( input == NULL) { fprintf(stderr, "Failed to open file %s\n", (char *)fName); exit(1); } // Our input stream is now open and all set to go, so we can create a new instance of our // lexer and set the lexer input to our input stream: // (file | memory | ?) --> inputstream -> lexer --> tokenstream --> parser ( --> treeparser )? // lxr = CLexerNew(input); // CLexerNew is generated by ANTLR // Need to check for errors // if ( lxr == NULL ) { fprintf(stderr, "Unable to create the lexer due to malloc() failure1\n"); exit(1); } // Our lexer is in place, so we can create the token stream from it // NB: Nothing happens yet other than the file has been read. We are just // connecting all these things together and they will be invoked when we // call the parser rule. ANTLR3_SIZE_HINT can be left at the default usually // unless you have a very large token stream/input. Each generated lexer // provides a token source interface, which is the second argument to the // token stream creator. // Note that even if you implement your own token structure, it will always // contain a standard common token within it and this is the pointer that // you pass around to everything else. A common token as a pointer within // it that should point to your own outer token structure. // tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr)); if (tstream == NULL) { fprintf(stderr, "Out of memory trying to allocate token stream\n"); exit(1); } // Finally, now that we have our lexer constructed, we can create the parser // psr = CParserNew(tstream); // CParserNew is generated by ANTLR3 if (psr == NULL) { fprintf(stderr, "Out of memory trying to allocate parser\n"); exit(ANTLR3_ERR_NOMEM); } // We are all ready to go. Though that looked complicated at first glance, // I am sure, you will see that in fact most of the code above is dealing // with errors and there isn't really that much to do (isn't this always the // case in C? ;-). // // So, we now invoke the parser. All elements of ANTLR3 generated C components // as well as the ANTLR C runtime library itself are pseudo objects. This means // that they are represented as pointers to structures, which contain any // instance data they need, and a set of pointers to other interfaces or // 'methods'. Note that in general, these few pointers we have created here are // the only things you will ever explicitly free() as everything else is created // via factories, that allocated memory efficiently and free() everything they use // automatically when you close the parser/lexer/etc. // // Note that this means only that the methods are always called via the object // pointer and the first argument to any method, is a pointer to the structure itself. // It also has the side advantage, if you are using an IDE such as VS2005 that can do it // that when you type ->, you will see a list of tall the methods the object supports. // psr->translation_unit(psr); // We did not return anything from this parser rule, so we can finish. It only remains // to close down our open objects, in the reverse order we created them // psr ->free (psr); psr = NULL; tstream ->free (tstream); tstream = NULL; lxr ->free (lxr); lxr = NULL; input ->close (input); input = NULL; return 0; }
jalParser_program_return ParseSource(pANTLR3_UINT8 fName) { // The ANTLR3 character input stream, which abstracts the input source such that // it is easy to provide input from different sources such as files, or // memory strings. pANTLR3_INPUT_STREAM input; // The lexer (ANTLR generated) is supplied with a pANTLR3_INPUT_STREAM from whence it consumes its // input and generates a token stream as output. // (moved to global) pjalLexer lxr; // The token stream (ANTLR generated) pANTLR3_COMMON_TOKEN_STREAM tstream; // The C parser (ANTLR generated) // (moved to global) pjalParser psr; // Create the input stream using the supplied file name input = antlr3AsciiFileStreamNew(fName); if ( input == NULL) { CodeOutput(VERBOSE_M, "Failed to open file %s\n", (char *)fName); fprintf(stderr, "Failed to open file %s\n", (char *)fName); exit(1); } // Our input stream is now open and all set to go, so we can create a new instance of our // lexer and set the lexer input to our input stream: // (file | memory | ?) --> inputstream -> lexer --> tokenstream --> parser ( --> treeparser )? // lxr = jalLexerNew(input); // CLexerNew is generated by ANTLR assert(lxr != NULL) ; // Unable to create the lexer due to malloc() failure1 // Our lexer is in place, so we can create the token stream from it // NB: Nothing happens yet other than the file has been read. We are just // connecting all these things together and they will be invoked when we // call the parser rule. ANTLR3_SIZE_HINT can be left at the default usually // unless you have a very large token stream/input. Each generated lexer // provides a token source interface, which is the second argument to the // token stream creator. // Note that even if you implement your own token structure, it will always // contain a standard common token within it and this is the pointer that // you pass around to everything else. A common token as a pointer within // it that should point to your own outer token structure. // tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr)); assert (tstream != NULL); // Out of memory trying to allocate token stream // Finally, now that we have our lexer constructed, we can create the parser // psr = jalParserNew(tstream); // CParserNew is generated by ANTLR3 assert (psr != NULL); // Out of memory trying to allocate parser // We are all ready to go. Though that looked complicated at first glance, // I am sure, you will see that in fact most of the code above is dealing // with errors and there isn't really that much to do (isn't this always the // case in C? ;-). // // So, we now invoke the parser. All elements of ANTLR3 generated C components // as well as the ANTLR C runtime library itself are pseudo objects. This means // that they are represented as pointers to structures, which contain any // instance data they need, and a set of pointers to other interfaces or // 'methods'. Note that in general, these few pointers we have created here are // the only things you will ever explicitly free() as everything else is created // via factories, that allocated memory efficiently and free() everything they use // automatically when you close the parser/lexer/etc. // // Note that this means only that the methods are always called via the object // pointer and the first argument to any method, is a pointer to the structure itself. // It also has the side advantage, if you are using an IDE such as VS2005 that can do it // that when you type ->, you will see a list of tall the methods the object supports. // jalParser_program_return r = psr->program(psr); // js 'program' is the root element of our language grammar // If the parser ran correctly, we will have a tree to parse. In general I recommend // keeping your own flags as part of the error trapping, but here is how you can // work out if there were errors if you are using the generic error messages // if (psr->pParser->rec->state->errorCount > 0) { fprintf(stderr, "The parser returned %d errors, tree walking aborted.\n", psr->pParser->rec->state->errorCount); exit(1); } return r; }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- pANTLR3_INPUT_STREAM JalOpenInclude(char *Line) { int State, i; char *BaseName; char FileName[MAX_FILENAME_SIZE]; char FilePath[MAX_FILENAME_SIZE]; IncludeNameList *Inl; pANTLR3_INPUT_STREAM in; if (NoInclude) { CodeOutput(VERBOSE_M, "// Ignore include line %s\n", Line); return NULL; } // printf("// JalInclude line: %s\n", Line); //--------------------------------------------- // extract filename from include statement line //--------------------------------------------- State = 0; for (i=0; ((Line[i] != 0)&(State != 3)); i++) { switch(State) { case 0 : { // search for first whitespace if ((Line[i] == ' ') | (Line[i] == '\t')) { State = 1; } break; } case 1 : { // search for non-whitespace, which is start of filename/path if ((Line[i] != ' ') & (Line[i] != '\t')) { BaseName = &Line[i]; State = 2; } break; } case 2 : { // search for first whitespace, which is end of filename/path if ((Line[i] == ' ') | (Line[i] == '\t') | (Line[i] == '\r') | (Line[i] == '\n')) { Line[i] = 0; // terminate string State = 3; } break; } default : { CodeOutput(VERBOSE_ALL, "Error state: %d, i: %d\n", State, i); break; } } } CodeOutput(VERBOSE_M, "// include BaseName: _%s_\n", BaseName); // base filename retrieved. sprintf(FileName, "%s.jal", BaseName); //------------------------------------------ // check if file is already included //------------------------------------------ Inl = InlRoot; while (Inl) { if (strcmp(BaseName, Inl->FileName) == 0) { // file found CodeOutput(VERBOSE_M, "// File '%s' already included, so ignore now\n", BaseName); return NULL; } Inl = Inl->Next; } // not found, so add Inl = malloc(sizeof(IncludeNameList)); Inl->Next = InlRoot; Inl->FileName = CreateName(BaseName); InlRoot = Inl; //------------------------------------------ // try to open filename at current location. //------------------------------------------ strcpy(FilePath, FileName); CodeOutput(VERBOSE_L, "// Try first %s \n", FilePath); in = antlr3AsciiFileStreamNew(FilePath); if (in == NULL) { //------------------------------------------ // file not at current location, so // walk include path to find file. //------------------------------------------ GetIncludePath(NULL, 1); // reset include path for (;;) { if (GetIncludePath(FilePath, 0)) { // got a path. strcat(FilePath, FileName); CodeOutput(VERBOSE_L, "// Try path %s \n", FilePath); in = antlr3AsciiFileStreamNew(FilePath); if (in != NULL) break; // found the file! // else next file continue; } CodeOutput(VERBOSE_L, "// Path done without succes...\n"); break; } } if (in == NULL) { CodeOutput(VERBOSE_ERROR, "Error opening include file %s\n", FileName); exit(1); } // note: PUSHSTREAM macro only works in LEX context (not in this code, nor PARSER context). // So leave PUSHSTREAM in the gramar-file. return in; }
bool parseProto (const char*filename, const char *outputFilename,const char * outputInternalNamespace, const char*outputExternalNamespace, char**package,pANTLR3_HASH_TABLE typeTable, bool cleanUp,ProtoJSParser_protocol_return*retval, pProtoJSLexer*ret_lxr, pProtoJSParser*ret_psr,pANTLR3_COMMON_TOKEN_STREAM*ret_tstream, pANTLR3_INPUT_STREAM* ret_stream) { pANTLR3_INPUT_STREAM input = antlr3AsciiFileStreamNew((pANTLR3_UINT8)filename); if ( input == NULL ) { fprintf(stderr, "Failed to open file %s\n", (char *)filename); exit(1); } pProtoJSLexer lxr = ProtoJSLexerNew(input); if ( lxr == NULL ) { fprintf(stderr, "Unable to create the lexer due to malloc() failure1\n"); exit(1); } pANTLR3_COMMON_TOKEN_STREAM tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr)); if (tstream == NULL) { fprintf(stderr, "Out of memory trying to allocate token stream\n"); exit(1); } pProtoJSParser ctx; pProtoJSParser psr = ctx = ProtoJSParserNew(tstream); if (psr == NULL) { fprintf(stderr, "Out of memory trying to allocate parser\n"); exit(ANTLR3_ERR_NOMEM); } SCOPE_TYPE(NameSpace) ns=NameSpacePush(ctx); ctx->pProtoJSParser_NameSpaceTop=ns; ns->filename=tstream->tstream->tokenSource->strFactory->newRaw(tstream->tstream->tokenSource->strFactory); ns->filename->append8(SCOPE_TOP(NameSpace)->filename,(const char*)outputFilename); ns->internalNamespace=tstream->tstream->tokenSource->strFactory->newRaw(tstream->tstream->tokenSource->strFactory); ns->internalNamespace->append8(ns->internalNamespace,(const char*)outputInternalNamespace); ns->externalNamespace=tstream->tstream->tokenSource->strFactory->newRaw(tstream->tstream->tokenSource->strFactory); ns->externalNamespace->append8(SCOPE_TOP(NameSpace)->externalNamespace,(const char*)outputExternalNamespace); if (strlen(outputExternalNamespace)) { ns->externalNamespace->append8(ns->externalNamespace,"."); } initNameSpace(ctx,ns); pANTLR3_HASH_TABLE tempTable=ns->qualifiedTypes; if (*package){ ns->package->set8(ns->package,*package); ns->packageDot->set8(ns->packageDot,*package); ns->packageDot->append8(ns->packageDot,"."); } if (typeTable) { ns->qualifiedTypes=typeTable; } ProtoJSParser_protocol_return pbjAST=psr->protocol(psr); if (!*package) { *package=strdup((const char*)ns->package->chars); } ns->qualifiedTypes=tempTable; bool success=true; if (psr->pParser->rec->getNumberOfSyntaxErrors(psr->pParser->rec) > 0) { success=false; ANTLR3_FPRINTF(stderr, "The parser returned %d errors, tree walking aborted.\n", psr->pParser->rec->getNumberOfSyntaxErrors(psr->pParser->rec)); }else { } if (cleanUp) { NameSpacePop(ctx); psr->free(psr); psr = NULL; tstream->free(tstream); tstream = NULL; lxr->free(lxr); lxr = NULL; input->close(input); input = NULL; }else { *retval=pbjAST; *ret_lxr=lxr; *ret_psr=psr; *ret_tstream=tstream; *ret_stream=input; } return success; }
int main(int argc, char *argv[]) { try { if(argc < 2) { std::cerr << "Input file not specified!!!" << std::endl; return EXIT_FAILURE; } // check if input file exist std::ifstream inFile(argv[1]); if(!inFile.is_open()) { std::cerr << "Input file '" << argv[1] << "' not found!!!" << std::endl; return EXIT_FAILURE; } // create file name std::string filePath(argv[1]); size_t nameStart = filePath.find_last_of("/\\"); size_t extStart = filePath.find_last_of("."); std::string fileName(filePath, nameStart + 1, extStart - nameStart); fileName += "cpp"; // prepare output stream std::ofstream outFile(fileName.c_str()); if(!outFile.is_open()) { std::cerr << "Cannot create output file '" << fileName << "'!!!" << std::endl; return EXIT_FAILURE; } // create logger & translator freettcn::translator::CLogger logger; freettcn::translator::CDumper dumper(outFile); freettcn::translator::CTranslator translator(argv[1], logger); // create input stream pANTLR3_UINT8 fName((pANTLR3_UINT8)argv[1]); pANTLR3_INPUT_STREAM input = antlr3AsciiFileStreamNew(fName); if(!input) std::cerr << "Unable to open file " << (char *)fName << " due to malloc() failure1" << std::endl; // create lexer pttcn3Lexer lexer = ttcn3LexerNew(input); if(!lexer) { std::cerr << "Unable to create the lexer due to malloc() failure1" << std::endl; return EXIT_FAILURE; } // override warning messages for lexer lexer->pLexer->rec->displayRecognitionError = freettcn::translator::DisplayRecognitionError; // create tokens stream from input file pANTLR3_COMMON_TOKEN_STREAM tokens = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lexer)); if(!tokens) { std::cerr << "Out of memory trying to allocate token stream" << std::endl; return EXIT_FAILURE; } // create parser pttcn3Parser parser = ttcn3ParserNew(tokens); if(!parser) { std::cerr << "Out of memory trying to allocate parser" << std::endl; return EXIT_FAILURE; } // override warning messages for parser parser->pParser->rec->displayRecognitionError = freettcn::translator::DisplayRecognitionError; if(argc >= 3 && std::string(argv[2]) == "-t") { // print tokens stream pANTLR3_UINT8 *tokenNames = parser->pParser->rec->state->tokenNames; if(!tokenNames) { std::cerr << "Token names not initiated!!!" << std::endl; return EXIT_FAILURE; } // estimate the longest token name size_t maxTokenLength = 0; pANTLR3_VECTOR vector = tokens->getTokens(tokens); for(unsigned i=0; i<vector->size(vector); i++) { pANTLR3_COMMON_TOKEN token = (pANTLR3_COMMON_TOKEN)vector->get(vector, i); maxTokenLength = std::max(maxTokenLength, std::string((char *)tokenNames[token->getType(token)]).size()); } // print tokens for(unsigned i=0; i<vector->size(vector); i++) { pANTLR3_COMMON_TOKEN token = (pANTLR3_COMMON_TOKEN)vector->get(vector, i); std::cout << "Token[" << std::setw(3) << std::right << token->getType(token) << "] - " << std::setw(maxTokenLength) << std::left << tokenNames[token->getType(token)] << " = " << token->getText(token)->chars << std::endl; } return EXIT_SUCCESS; } // parse tokes stream parser->ttcn3Module(parser); if(translator.WarningNum() || translator.ErrorNum()) { std::cerr << filePath << ": Errors: " << translator.ErrorNum() << "; Warnings: " << translator.WarningNum() << std::endl; return EXIT_FAILURE; } // dump to output file translator.Dump(dumper); // must manually clean up // parser->free(parser); tokens->free(tokens); lexer->free(lexer); input->close(input); } catch(freettcn::Exception &ex) { std::cerr << "Error: Unhandled freettcn exception caught:" << std::endl; std::cerr << ex.what() << std::endl; return EXIT_FAILURE; } catch(std::exception &ex) { std::cerr << "Error: Unhandled system exception caught:" << std::endl;; std::cerr << ex.what() << std::endl;; return EXIT_FAILURE; } catch(...) { std::cerr << "Unknown exception caught!!!" << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }
static int smartpl_parse_file(const char *file, struct playlist_info *pli) { pANTLR3_INPUT_STREAM input; pSMARTPLLexer lxr; pANTLR3_COMMON_TOKEN_STREAM tstream; pSMARTPLParser psr; SMARTPLParser_playlist_return qtree; pANTLR3_COMMON_TREE_NODE_STREAM nodes; pSMARTPL2SQL sqlconv; SMARTPL2SQL_playlist_return plreturn; int ret; #if ANTLR3C_NEW_INPUT input = antlr3FileStreamNew((pANTLR3_UINT8) file, ANTLR3_ENC_8BIT); #else input = antlr3AsciiFileStreamNew((pANTLR3_UINT8) file); #endif // The input will be created successfully, providing that there is enough memory and the file exists etc if (input == NULL) { DPRINTF(E_LOG, L_SCAN, "Unable to open smart playlist file %s\n", file); return -1; } lxr = SMARTPLLexerNew(input); // Need to check for errors if (lxr == NULL) { DPRINTF(E_LOG, L_SCAN, "Could not create SMARTPL lexer\n"); ret = -1; goto lxr_fail; } tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr)); if (tstream == NULL) { DPRINTF(E_LOG, L_SCAN, "Could not create SMARTPL token stream\n"); ret = -1; goto tkstream_fail; } // Finally, now that we have our lexer constructed, we can create the parser psr = SMARTPLParserNew(tstream); // CParserNew is generated by ANTLR3 if (tstream == NULL) { DPRINTF(E_LOG, L_SCAN, "Could not create SMARTPL parser\n"); ret = -1; goto psr_fail; } qtree = psr->playlist(psr); /* Check for parser errors */ if (psr->pParser->rec->state->errorCount > 0) { DPRINTF(E_LOG, L_SCAN, "SMARTPL query parser terminated with %d errors\n", psr->pParser->rec->state->errorCount); ret = -1; goto psr_error; } DPRINTF(E_DBG, L_SCAN, "SMARTPL query AST:\n\t%s\n", qtree.tree->toStringTree(qtree.tree)->chars); nodes = antlr3CommonTreeNodeStreamNewTree(qtree.tree, ANTLR3_SIZE_HINT); if (!nodes) { DPRINTF(E_LOG, L_SCAN, "Could not create node stream\n"); ret = -1; goto psr_error; } sqlconv = SMARTPL2SQLNew(nodes); if (!sqlconv) { DPRINTF(E_LOG, L_SCAN, "Could not create SQL converter\n"); ret = -1; goto sql_fail; } plreturn = sqlconv->playlist(sqlconv); /* Check for tree parser errors */ if (sqlconv->pTreeParser->rec->state->errorCount > 0) { DPRINTF(E_LOG, L_SCAN, "SMARTPL query tree parser terminated with %d errors\n", sqlconv->pTreeParser->rec->state->errorCount); ret = -1; goto sql_error; } if (plreturn.title && plreturn.query) { DPRINTF(E_DBG, L_SCAN, "SMARTPL SQL title '%s' query: -%s-\n", plreturn.title->chars, plreturn.query->chars); if (pli->title) free(pli->title); pli->title = strdup((char *)plreturn.title->chars); if (pli->query) free(pli->query); pli->query = strdup((char *)plreturn.query->chars); ret = 0; } else { DPRINTF(E_LOG, L_SCAN, "Invalid SMARTPL query\n"); ret = -1; } sql_error: sqlconv->free(sqlconv); sql_fail: nodes->free(nodes); psr_error: psr->free(psr); psr_fail: tstream->free(tstream); tkstream_fail: lxr->free(lxr); lxr_fail: input->close(input); return ret; }