From: <ibr...@us...> - 2013-04-06 22:20:44
|
Revision: 4609 http://sourceforge.net/p/tora/code/4609 Author: ibre5041 Date: 2013-04-06 22:20:41 +0000 (Sat, 06 Apr 2013) Log Message: ----------- Modified Paths: -------------- branches/tora3/src/parsing/tsqllexer.h branches/tora3/src/parsing/tsqllexer.inl branches/tora3/src/parsing/tsqllexeroracle2.cc Modified: branches/tora3/src/parsing/tsqllexer.h =================================================================== --- branches/tora3/src/parsing/tsqllexer.h 2013-04-05 23:06:44 UTC (rev 4608) +++ branches/tora3/src/parsing/tsqllexer.h 2013-04-06 22:20:41 UTC (rev 4609) @@ -79,12 +79,16 @@ inline const TokenType& getTokenType() const; inline unsigned getOrigTokenType() const; + inline const QString& getText() const; + inline void setText(const QString&); + inline Token& operator=(const Token& other); inline operator const Position&() const; protected: Position _mPosition; unsigned _mLength, _mOrigType; + QString _mText; TokenType _mTokenType; }; Modified: branches/tora3/src/parsing/tsqllexer.inl =================================================================== --- branches/tora3/src/parsing/tsqllexer.inl 2013-04-05 23:06:44 UTC (rev 4608) +++ branches/tora3/src/parsing/tsqllexer.inl 2013-04-06 22:20:41 UTC (rev 4609) @@ -96,12 +96,23 @@ return _mOrigType; }; + inline const QString& Token::getText() const + { + return _mText; + }; + + inline void Token::setText(const QString &t) + { + _mText = t; + }; + inline Token& Token::operator=(const Token& other) { _mPosition = other._mPosition; _mLength = other._mLength; _mTokenType = other._mTokenType; _mOrigType = other._mOrigType; + _mText = other._mText; return *this; }; Modified: branches/tora3/src/parsing/tsqllexeroracle2.cc =================================================================== --- branches/tora3/src/parsing/tsqllexeroracle2.cc 2013-04-05 23:06:44 UTC (rev 4608) +++ branches/tora3/src/parsing/tsqllexeroracle2.cc 2013-04-06 22:20:41 UTC (rev 4609) @@ -138,6 +138,7 @@ else return 0; } + const Token& OracleGuiLexer::LA(int pos) const { PLSQLGuiLexerTraits::CommonTokenType const* token = tstream->_LT(pos); @@ -205,6 +206,7 @@ } retvalLA = Token(Position(line, column), length, token->getType(), type); + retvalLA.setText(QString::fromUtf8(token->getText().c_str())); return retvalLA; } else throw Exception(); @@ -270,8 +272,8 @@ Lexer::token_const_iterator OracleGuiLexer::findEndToken( Lexer::token_const_iterator const &start) { - token_const_iterator i( start); - switch( i->getTokenType()) + token_const_iterator i(start); + switch( start->getTokenType()) { case Token::L_PL_INTRODUCER: { @@ -283,9 +285,19 @@ } break; } + /** + * Pseudo parser for: INSERT, SELECT, WITH, UPDATE, DELETE, MERGE, COMMIT, ROLLBACK, EXPLAIN statement + * - some of those words(SELECT, UPDATE, DELETE, WITH, SET) can also be inside other statement + * - SELECT can only follow LEFT_PAREN or RIGHT_PAREN + * - in case of MERGE statement DELETE can follow anything, SELECT/UPDATE follow 'THEN' + * - MERGE can not be in the middle of any statement + * - statement can end with: SOLIDUS('/'), SEMICOLON(';') or other introducer(SELECT, UPDATE, ...) + */ case Token::L_DML_INTRODUCER: { bool parenFound = false; + bool mergeFound = start->getText().compare("MERGE", Qt::CaseInsensitive) == 0; + bool explainFound = start->getText().compare("EXPLAIN", Qt::CaseInsensitive) == 0; bool exitLoop = false; while(true) { @@ -294,47 +306,60 @@ { case PLSQLGuiLexer::LEFT_PAREN: case PLSQLGuiLexer::RIGHT_PAREN: - // TODO this fails for merge stmt: see merge01.sql parenFound = true; break; case PLSQLGuiLexer::SQL_COMMAND_INTRODUCER: - case PLSQLGuiLexer::SOLIDUS: - case PLSQLGuiLexer::SEMICOLON: - if( !parenFound) + if( !parenFound && !mergeFound) exitLoop = true; + else if( i->getText().compare("MERGE", Qt::CaseInsensitive) == 0) + exitLoop = true; break; - case PLSQLGuiLexer::NEWLINE: + case PLSQLGuiLexer::NEWLINE: // white chars do not clear parenFound case PLSQLGuiLexer::SPACE: case PLSQLGuiLexer::COMMENT_ML: case PLSQLGuiLexer::COMMENT_SL: break; + case PLSQLGuiLexer::SOLIDUS: // TODO SOLIDUS must follow NEWLINE or NEWLINE+SPACE + case PLSQLGuiLexer::SEMICOLON: + case PLSQLGuiLexer::OTHER_COMMAND_INTRODUCER: // ALTER, GRANT, TRUNCATE, SET, ... + // EXPLAIN PLAN SET STATEMENT - do not end this stmt + //if(explainFound && i->getText().compare("SET", Qt::CaseInsensitive) == 0) + // break; + case PLSQLGuiLexer::PLSQL_COMMAND_INTRODUCER: // DECLARE, BEGIN, CREATE, ... case PLSQLGuiLexer::EOF_TOKEN: case PLSQLGuiLexerTraits::CommonTokenType::TOKEN_INVALID: exitLoop = true; break; - default: + default: // any other word clear parenFound parenFound = false; - } if( exitLoop) break; } break; } + /** + * Pseudo parser for: ALTER, ANALYZE, TRUNCATE, FLASHBACK, ... statement + * - GRANT statement can contain SELECT, UPDATE, DELETE, INSERT + * - statement can end with: SOLIDUS('/'), SEMICOLON(';') or other introducer(SELECT, UPDATE, ...) + */ case Token::L_OTHER_INTRODUCER: { + bool grantFound = start->getText().compare("GRANT", Qt::CaseInsensitive) == 0; + bool exitLoop = false; while(true) { i++; - if( i->getTokenType() == Token::X_EOF) + switch( i->getOrigTokenType()) + { + case PLSQLGuiLexer::EOF_TOKEN: + case PLSQLGuiLexer::SEMICOLON: + case PLSQLGuiLexer::SOLIDUS:// TODO + exitLoop = true; + break; + } + if( exitLoop) break; - if( i->getTokenType() == Token::X_UNASSIGNED && i->getOrigTokenType() == PLSQLGuiLexer::SOLIDUS) - break; - if( i->getTokenType() == Token::X_UNASSIGNED && i->getOrigTokenType() == PLSQLGuiLexer::SEMICOLON) - break; - //GRANT SELECT ON .. - //if( i->getTokenType() == Token::L_DML_INTRODUCER) - // break; } break; } @@ -343,7 +368,7 @@ } return i; -} + } }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ibr...@us...> - 2013-06-30 17:35:47
|
Revision: 4665 http://sourceforge.net/p/tora/code/4665 Author: ibre5041 Date: 2013-06-30 17:35:41 +0000 (Sun, 30 Jun 2013) Log Message: ----------- Fix for "FOR UPDATE", SQLPLUS statements Modified Paths: -------------- branches/tora3/src/parsing/PLSQLGuiLexer.cc branches/tora3/src/parsing/PLSQLGuiLexer.hpp branches/tora3/src/parsing/tsqllexeroracle2.cc Modified: branches/tora3/src/parsing/PLSQLGuiLexer.cc =================================================================== (Binary files differ) Modified: branches/tora3/src/parsing/PLSQLGuiLexer.hpp =================================================================== (Binary files differ) Modified: branches/tora3/src/parsing/tsqllexeroracle2.cc =================================================================== --- branches/tora3/src/parsing/tsqllexeroracle2.cc 2013-06-30 12:34:30 UTC (rev 4664) +++ branches/tora3/src/parsing/tsqllexeroracle2.cc 2013-06-30 17:35:41 UTC (rev 4665) @@ -386,6 +386,7 @@ * - SELECT can only follow LEFT_PAREN, RIGHT_PAREN or UNION (ALL), MINUS, INTERSECT * - in case of MERGE statement DELETE can follow anything, SELECT/UPDATE follow 'THEN' * - MERGE can not be in the middle of any statement + * - UPDATE can be part of FOR UPDATE OF statement * - SELECT statement can start with LPAREN ('(') i.e " (SELECT * FROM DUAL ) UNION ALL (SELECT * FROM DUAL) " * - statement can end with: SOLIDUS('/'), SEMICOLON(';') or other introducer(SELECT, UPDATE, ...) */ @@ -395,6 +396,7 @@ bool parenFound = start->getTokenType() == Token::L_LPAREN; bool mergeFound = start->getText().compare("MERGE", Qt::CaseInsensitive) == 0; bool explainFound = start->getText().compare("EXPLAIN", Qt::CaseInsensitive) == 0; + bool forFound = false; bool exitLoop = false; while(!exitLoop) { @@ -407,15 +409,19 @@ parenFound = true; break; case PLSQLGuiLexer::SQL_COMMAND_INTRODUCER: - if( !parenFound && !mergeFound) + if( forFound && i->getText().compare("UPDATE", Qt::CaseInsensitive) == 0) // FOR UPDATE continue parsing + exitLoop = false; + else if( !parenFound && !mergeFound) // No PARENS no MERGE but 'SELECT' was found exitLoop = true; - else if( i->getText().compare("MERGE", Qt::CaseInsensitive) == 0) + else if( i->getText().compare("MERGE", Qt::CaseInsensitive) == 0) // New MERGE statement begins exitLoop = true; break; case PLSQLGuiLexer::PLSQL_RESERVED: + if( i->getText().compare("FOR", Qt::CaseInsensitive) == 0) + forFound = true; if( i->getText().compare("UNION", Qt::CaseInsensitive) == 0 - || i->getText().compare("INTERSECT", Qt::CaseInsensitive) == 0 - || i->getText().compare("MINUS", Qt::CaseInsensitive) == 0) + || i->getText().compare("INTERSECT", Qt::CaseInsensitive) == 0 + || i->getText().compare("MINUS", Qt::CaseInsensitive) == 0) parenFound = true; else if( parenFound && i->getText().compare("ALL", Qt::CaseInsensitive) == 0) parenFound = true; @@ -429,10 +435,11 @@ break; case PLSQLGuiLexer::SQLPLUS_COMMAND: case PLSQLGuiLexer::SQLPLUS_COMMAND_INTRODUCER: + case PLSQLGuiLexer::SQLPLUS_SOLIDUS: + case PLSQLGuiLexer::SEMICOLON: exitLoop = true; + i--; break; - case PLSQLGuiLexer::SQLPLUS_SOLIDUS: // TODO SOLIDUS must follow NEWLINE or NEWLINE+SPACE - case PLSQLGuiLexer::SEMICOLON: case PLSQLGuiLexer::OTHER_COMMAND_INTRODUCER: // ALTER, GRANT, TRUNCATE, SET, ... // EXPLAIN PLAN SET STATEMENT - do not end this stmt //if(explainFound && i->getText().compare("SET", Qt::CaseInsensitive) == 0) @@ -481,6 +488,7 @@ case Token::X_ONE_LINE: { i = i.consumeUntil(PLSQLGuiLexer::NEWLINE); + break; } default: throw Exception(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ibr...@us...> - 2013-06-30 20:31:44
|
Revision: 4666 http://sourceforge.net/p/tora/code/4666 Author: ibre5041 Date: 2013-06-30 20:31:41 +0000 (Sun, 30 Jun 2013) Log Message: ----------- PLSQL Modified Paths: -------------- branches/tora3/src/parsing/PLSQLGuiLexer.cc branches/tora3/src/parsing/PLSQLGuiLexer.hpp branches/tora3/src/parsing/tsqllexeroracle2.cc Modified: branches/tora3/src/parsing/PLSQLGuiLexer.cc =================================================================== (Binary files differ) Modified: branches/tora3/src/parsing/PLSQLGuiLexer.hpp =================================================================== (Binary files differ) Modified: branches/tora3/src/parsing/tsqllexeroracle2.cc =================================================================== --- branches/tora3/src/parsing/tsqllexeroracle2.cc 2013-06-30 17:35:41 UTC (rev 4665) +++ branches/tora3/src/parsing/tsqllexeroracle2.cc 2013-06-30 20:31:41 UTC (rev 4666) @@ -4,6 +4,8 @@ #include "parsing/PLSQLParser.hpp" #include "parsing/tsqllexer.h" +#include <QVector> + namespace SQLLexer { @@ -41,6 +43,15 @@ unsigned lastLine, lastColumn, lastIndex; mutable Token retvalLA; + + enum Context { + CREATE = 1, + PACKAGE, // or TYPE or TRIGGER + PROCEDURE, // or function + DECLARE, // or IS or AS + BEGIN, + LOOP // or CASE + }; }; OracleGuiLexer::OracleGuiLexer(const QString &statement, const QString &name) @@ -105,7 +116,7 @@ exit(ANTLR_ERR_NOMEM); } //_mState = P_LEXER; -}; +} void OracleGuiLexer::setStatement(const char *s, unsigned len) { @@ -313,13 +324,26 @@ //User::PLSQLParser::seq_of_statements_return r = psr->seq_of_statements(); //delete psr; - /* + QVector<Context> stack; bool exitLoop = false; bool createFound = start->getText().compare("CREATE", Qt::CaseInsensitive) == 0; bool functionFound = start->getText().compare("FUNCTION", Qt::CaseInsensitive) == 0; bool procedureFound = start->getText().compare("PROCEDURE", Qt::CaseInsensitive) == 0; bool declareFound = start->getText().compare("DECLARE", Qt::CaseInsensitive) == 0; bool beginFound = start->getText().compare("BEGIN", Qt::CaseInsensitive) == 0; + + if ( createFound ) + stack << CREATE; + else if ( start->getText().compare("PACKAGE", Qt::CaseInsensitive) == 0 || + start->getText().compare("TRIGGER", Qt::CaseInsensitive) == 0 ) + stack << PACKAGE; + else if ( declareFound ) + stack << DECLARE; + else if ( beginFound) + stack << BEGIN; + else + throw Exception(); + unsigned blockDepth = 1; unsigned parenDepth = 0; while(!exitLoop) @@ -377,7 +401,6 @@ break; } } - */ break; } /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ibr...@us...> - 2013-07-09 16:27:49
|
Revision: 4676 http://sourceforge.net/p/tora/code/4676 Author: ibre5041 Date: 2013-07-09 16:27:38 +0000 (Tue, 09 Jul 2013) Log Message: ----------- Support for ((SELECT * FROM DUAL)) Modified Paths: -------------- branches/tora3/src/parsing/tsqllexer.h branches/tora3/src/parsing/tsqllexeroracle2.cc Modified: branches/tora3/src/parsing/tsqllexer.h =================================================================== --- branches/tora3/src/parsing/tsqllexer.h 2013-07-08 19:19:45 UTC (rev 4675) +++ branches/tora3/src/parsing/tsqllexer.h 2013-07-09 16:27:38 UTC (rev 4676) @@ -56,23 +56,23 @@ X_UNASSIGNED = 0 , X_EOF , X_EOL - , X_FAILURE - , X_ONE_LINE + , X_FAILURE // invalid character not understood by lexer + , X_ONE_LINE // SQLPlus command // White space "hidden" channel - , X_WHITE - , X_COMMENT - , X_COMMENT_ML - , X_COMMENT_ML_END + , X_WHITE // "white" char space, tab, newline + , X_COMMENT // single line comment, preferable without newline part + , X_COMMENT_ML // Multi-line comment (the correct one) + , X_COMMENT_ML_END // Partially edited multi-line comment, usually ends with EOF // Leaf node - , L_RESERVED + , L_RESERVED // Reserved word , L_IDENTIFIER - , L_BUILDIN - , L_STRING - , L_LPAREN - , L_RPAREN - , L_DML_INTRODUCER - , L_PL_INTRODUCER - , L_OTHER_INTRODUCER + , L_BUILDIN // Buildin function name + , L_STRING // single/double quoted string + , L_LPAREN // '(' + , L_RPAREN // ')' + , L_DML_INTRODUCER // SELECT, INSERT, UPDATE + , L_PL_INTRODUCER // DECLARE, BEGIN, CREATE, PACKAGE, PROCEDURE + , L_OTHER_INTRODUCER // ALTER, EXPLAIN, ... }; inline Token(); Modified: branches/tora3/src/parsing/tsqllexeroracle2.cc =================================================================== --- branches/tora3/src/parsing/tsqllexeroracle2.cc 2013-07-08 19:19:45 UTC (rev 4675) +++ branches/tora3/src/parsing/tsqllexeroracle2.cc 2013-07-09 16:27:38 UTC (rev 4676) @@ -307,16 +307,50 @@ Lexer::token_const_iterator OracleGuiLexer::findStartToken( Lexer::token_const_iterator const &start) { + // These Token types can start new statement QSet<SQLLexer::Token::TokenType> INTRODUCERS = QSet<SQLLexer::Token::TokenType>() << SQLLexer::Token::L_DML_INTRODUCER << SQLLexer::Token::L_PL_INTRODUCER << SQLLexer::Token::L_OTHER_INTRODUCER << SQLLexer::Token::L_LPAREN << SQLLexer::Token::X_ONE_LINE - ; - token_const_iterator i(start); - i = i.consumeUntil(INTRODUCERS); - return i; + ; + token_const_iterator i(start); + while(i->getTokenType() != SQLLexer::Token::X_EOF) + { + i = i.consumeUntil(INTRODUCERS); + if(i->getTokenType() != SQLLexer::Token::L_LPAREN) + return i; // Return this Token - it is not LPAREN '(' + + bool exitLoop = false; + // LPAREN starts a new SQL query if and only if it's followed by SELECT + // create a duplicit iterator and iterate it until something interesting is found + { + token_const_iterator j(i); + while(j->getTokenType() != SQLLexer::Token::X_EOF && !exitLoop) + { + j++; + switch(j->getTokenType()) + { + case SQLLexer::Token::X_WHITE: + case SQLLexer::Token::X_COMMENT: + case SQLLexer::Token::X_COMMENT_ML: + case SQLLexer::Token::X_COMMENT_ML_END: + case SQLLexer::Token::X_EOL: + case SQLLexer::Token::L_LPAREN: // SQL QUERY can start with multiple LPARENs '((( SELECT ...' + continue; // nothing interesting was found, try the next Token + case SQLLexer::Token::L_DML_INTRODUCER: + if(j->getText().compare("SELECT", Qt::CaseInsensitive) == 0 ) + return i; // SELECT was found return position of LPAREN + return j; // otherwise return position of the DML Token + default: + exitLoop = true; // SELECT was not found => exit the loop; + } + } + i = j; // Advance position of the outer loop iterator - continue looping + } + } + return i; // NOTE: this will only return EOF } Lexer::token_const_iterator OracleGuiLexer::findEndToken( Lexer::token_const_iterator const &start) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ibr...@us...> - 2013-07-09 22:20:05
|
Revision: 4677 http://sourceforge.net/p/tora/code/4677 Author: ibre5041 Date: 2013-07-09 22:20:01 +0000 (Tue, 09 Jul 2013) Log Message: ----------- Modified Paths: -------------- branches/tora3/src/parsing/tsqllexer.h branches/tora3/src/parsing/tsqllexeroracle2.cc Modified: branches/tora3/src/parsing/tsqllexer.h =================================================================== --- branches/tora3/src/parsing/tsqllexer.h 2013-07-09 16:27:38 UTC (rev 4676) +++ branches/tora3/src/parsing/tsqllexer.h 2013-07-09 22:20:01 UTC (rev 4677) @@ -60,7 +60,7 @@ , X_ONE_LINE // SQLPlus command // White space "hidden" channel , X_WHITE // "white" char space, tab, newline - , X_COMMENT // single line comment, preferable without newline part + , X_COMMENT // single line comment, preferably without newline part , X_COMMENT_ML // Multi-line comment (the correct one) , X_COMMENT_ML_END // Partially edited multi-line comment, usually ends with EOF // Leaf node Modified: branches/tora3/src/parsing/tsqllexeroracle2.cc =================================================================== --- branches/tora3/src/parsing/tsqllexeroracle2.cc 2013-07-09 16:27:38 UTC (rev 4676) +++ branches/tora3/src/parsing/tsqllexeroracle2.cc 2013-07-09 22:20:01 UTC (rev 4677) @@ -308,12 +308,12 @@ Lexer::token_const_iterator OracleGuiLexer::findStartToken( Lexer::token_const_iterator const &start) { // These Token types can start new statement - QSet<SQLLexer::Token::TokenType> INTRODUCERS = QSet<SQLLexer::Token::TokenType>() - << SQLLexer::Token::L_DML_INTRODUCER - << SQLLexer::Token::L_PL_INTRODUCER - << SQLLexer::Token::L_OTHER_INTRODUCER - << SQLLexer::Token::L_LPAREN - << SQLLexer::Token::X_ONE_LINE + static const QSet<SQLLexer::Token::TokenType> INTRODUCERS = QSet<SQLLexer::Token::TokenType>() + << SQLLexer::Token::L_DML_INTRODUCER + << SQLLexer::Token::L_PL_INTRODUCER + << SQLLexer::Token::L_OTHER_INTRODUCER + << SQLLexer::Token::L_LPAREN + << SQLLexer::Token::X_ONE_LINE ; token_const_iterator i(start); while(i->getTokenType() != SQLLexer::Token::X_EOF) @@ -360,31 +360,37 @@ { case Token::L_PL_INTRODUCER: { - QVector<BlockContextEnum> stack; + // Every nested block pushes it's context onto stack + // Stack's top value can be also adjused, but the value can only be increased (CREATE => PACKAGE => DECLARE => BEGIN => END) + QVector<BlockContextEnum> stack; bool exitLoop = false; BlockContextEnum tokenContext = start->getBlockContext(); if( tokenContext == BlkCtx::NONE) - throw Exception(); - stack << tokenContext; + throw Exception(); // Assertion error. 1st Token must have block context + stack << tokenContext; // Push the 1st value onto stack while(!exitLoop) { i++; QString txt = i->getText(); - tokenContext = i->getBlockContext(); - BlockContextEnum &stackContext = stack.back(); + tokenContext = i->getBlockContext(); // context for next Token + BlockContextEnum &stackContext = stack.back(); // non-const reference the current stack's top switch(i->getTokenType()) { - case Token::L_OTHER_INTRODUCER: - case Token::X_ONE_LINE: + // These Tokens must not be present in PL/SQL CODE + case Token::L_OTHER_INTRODUCER: // ALTER, EXPLAIN + case Token::X_ONE_LINE: // SPOOL, EXIT, DEFINE, ... case Token::X_EOF: - case Token::X_FAILURE: + case Token::X_FAILURE: // Char not understood be the Lexer exitLoop = true; continue; - case Token::L_DML_INTRODUCER: + case Token::L_DML_INTRODUCER: // SELECT, INSERT, UPDATE, DELETE + // TODO TRIGGER abc BEFORE INSERT/UPDATE/DELETE is handled wrongly + // + // DML keyword can be only present within BEGIN or LOOP context if( stackContext == BlkCtx::PACKAGE || stackContext == BlkCtx::PROCEDURE) { exitLoop = true; @@ -396,12 +402,12 @@ continue; // Commbine two enumerated values. The current Stack's top - // and the current Token's context. The resulting value will be used - // the switch/case. BlkCtx has 7 possible values, - // theoretically we should cover up to 49 possible combinations + // and the current Token's context. The resulting value will be used in switch/case. + // BlkCtx has 7 possible values, theoretically we should cover up to 49 possible combinations. // // - The value on the stack's top can only be increased, as token iterator moves forward // CREATE -> PACKAGE -> DECLARE -> BEGIN -> END + // LOOP -> END // - In other cases we push new value onto stack ( like BLOCK inside BLOCK ) // - All other combinations are considered ilegal - they stop parsing (like LOOP inside DECLARE ) unsigned var = M<NONE,NONE>::combine(stackContext, tokenContext); @@ -413,7 +419,7 @@ case M< DECLARE, CREATE >::value : case M< BEGIN, CREATE >::value : case M< LOOP, CREATE >::value : - exitLoop = true; // CREATE inside anything => failure exit loop + exitLoop = true; // CREATE inside anything => failure, exit loop continue; case M< CREATE, PACKAGE >::value : @@ -439,7 +445,7 @@ i->getText().compare("AS", Qt::CaseInsensitive) == 0 ) stackContext = DECLARE; else - exitLoop = true; + exitLoop = true; // "DECLARE" inside PACKAGE/PROCEDURE => failure, exit loop continue; case M<DECLARE, DECLARE >::value : if( i->getText().compare("IS", Qt::CaseInsensitive) == 0 || @@ -449,8 +455,8 @@ continue; case M<BEGIN, DECLARE >::value : case M<LOOP, DECLARE >::value : - // IS is also part of IS NULL, IS AS SET // DECLARE/IS/AS inside BEGIN/LOOP (push DECLARE) - // AS is also part of pure SQL statemets + // IS is also part of "IS NULL", "IS A SET" // DECLARE/IS/AS inside BEGIN/LOOP (push DECLARE) + // AS is also part of pure SQL statemets "AS OF TIMESTAMP ..." // DECLARE itself starts a new block if( i->getText().compare("DECLARE", Qt::CaseInsensitive) == 0 ) stack << DECLARE; @@ -469,7 +475,7 @@ case M<DECLARE, LOOP >::value : case M<BEGIN, LOOP >::value : case M<LOOP, LOOP >::value : - stack << LOOP; // LOOP/CASE inside DECLARE (push LOOP) (CASE can return variables init value) + stack << LOOP; // CASE inside DECLARE (push LOOP) (CASE can return variable's init value) continue; // LOOP/CASE inside BEGIN/LOOP (push LOOP) (CASE can return variables init value) case M<BEGIN, END >::value : @@ -477,7 +483,7 @@ BlockContextEnum ctx = stackContext; stack.pop_back(); if( stack.isEmpty() ) exitLoop = true; - // TODO find SEMICOLON + // TODO find SEMICOLON (or label_name/package_name SEMICOLON) i = i.consumeUntil(PLSQLGuiLexer::SEMICOLON); continue; } @@ -502,7 +508,7 @@ /** * Pseudo parser for: INSERT, SELECT, WITH, UPDATE, DELETE, MERGE, COMMIT, ROLLBACK, EXPLAIN statement * - some of those words(SELECT, UPDATE, DELETE, WITH, SET) can also be inside other statement - * - SELECT can only follow LEFT_PAREN, RIGHT_PAREN or UNION (ALL), MINUS, INTERSECT + * - SELECT can only follow LEFT_PAREN, RIGHT_PAREN or UNION (ALL), MINUS, INTERSECT, otherwise it starts a new statement * - in case of MERGE statement DELETE can follow anything, SELECT/UPDATE follow 'THEN' * - MERGE can not be in the middle of any statement * - UPDATE can be part of FOR UPDATE OF statement @@ -516,8 +522,7 @@ bool mergeFound = start->getText().compare("MERGE", Qt::CaseInsensitive) == 0; bool explainFound = start->getText().compare("EXPLAIN", Qt::CaseInsensitive) == 0; bool forFound = false; - bool exitLoop = false; - while(!exitLoop) + while(i->getOrigTokenType() != PLSQLGuiLexer::EOF_TOKEN) { i++; QString txt = i->getText(); @@ -529,11 +534,11 @@ break; case PLSQLGuiLexer::SQL_COMMAND_INTRODUCER: if( forFound && i->getText().compare("UPDATE", Qt::CaseInsensitive) == 0) // FOR UPDATE continue parsing - exitLoop = false; - else if( !parenFound && !mergeFound) // No PARENS no MERGE but 'SELECT' was found - exitLoop = true; + break; + else if( !parenFound && !mergeFound) // No PARENS no MERGE but 'SELECT' was found + goto exitLoop; else if( i->getText().compare("MERGE", Qt::CaseInsensitive) == 0) // New MERGE statement begins - exitLoop = true; + goto exitLoop; break; case PLSQLGuiLexer::PLSQL_RESERVED: if( i->getText().compare("FOR", Qt::CaseInsensitive) == 0) @@ -556,10 +561,9 @@ case PLSQLGuiLexer::SQLPLUS_COMMAND_INTRODUCER: case PLSQLGuiLexer::SQLPLUS_SOLIDUS: case PLSQLGuiLexer::SEMICOLON: - exitLoop = true; i--; - break; - case PLSQLGuiLexer::OTHER_COMMAND_INTRODUCER: // ALTER, GRANT, TRUNCATE, SET, ... + goto exitLoop; + case PLSQLGuiLexer::OTHER_COMMAND_INTRODUCER: // ALTER, GRANT, TRUNCATE, SET TRANCACTION, ... // EXPLAIN PLAN SET STATEMENT - do not end this stmt //if(explainFound && i->getText().compare("SET", Qt::CaseInsensitive) == 0) // break; @@ -570,12 +574,12 @@ break; case PLSQLGuiLexer::EOF_TOKEN: case CommonTokenType::TOKEN_INVALID: - exitLoop = true; - break; + goto exitLoop; default: // any other word clear parenFound parenFound = false; } - } + } // while() + exitLoop:; break; } /** @@ -586,7 +590,6 @@ case Token::L_OTHER_INTRODUCER: { bool grantFound = start->getText().compare("GRANT", Qt::CaseInsensitive) == 0; - bool exitLoop = false; while(true) { i++; @@ -594,13 +597,11 @@ { case PLSQLGuiLexer::EOF_TOKEN: case PLSQLGuiLexer::SEMICOLON: - case PLSQLGuiLexer::SOLIDUS:// TODO - exitLoop = true; - break; + case PLSQLGuiLexer::SQLPLUS_SOLIDUS: + goto exitLoopOtherIntroducer; } - if( exitLoop) - break; } + exitLoopOtherIntroducer:; break; } // Handle OneLiners (SQLPLUS commands) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ibr...@us...> - 2013-08-03 14:35:14
|
Revision: 4690 http://sourceforge.net/p/tora/code/4690 Author: ibre5041 Date: 2013-08-03 14:35:12 +0000 (Sat, 03 Aug 2013) Log Message: ----------- Added Paths: ----------- branches/tora3/src/parsing/tolexeroracle.cpp branches/tora3/src/parsing/tolexeroracle.h Added: branches/tora3/src/parsing/tolexeroracle.cpp =================================================================== Added: branches/tora3/src/parsing/tolexeroracle.h =================================================================== This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ibr...@us...> - 2013-08-09 22:49:26
|
Revision: 4733 http://sourceforge.net/p/tora/code/4733 Author: ibre5041 Date: 2013-08-09 22:49:22 +0000 (Fri, 09 Aug 2013) Log Message: ----------- ANTLR based Oracle lexer Modified Paths: -------------- branches/tora3/src/parsing/tosyntaxanalyzer.h branches/tora3/src/parsing/tosyntaxanalyzernl.cpp branches/tora3/src/parsing/tosyntaxanalyzeroracle.cpp Modified: branches/tora3/src/parsing/tosyntaxanalyzer.h =================================================================== --- branches/tora3/src/parsing/tosyntaxanalyzer.h 2013-08-09 20:14:05 UTC (rev 4732) +++ branches/tora3/src/parsing/tosyntaxanalyzer.h 2013-08-09 22:49:22 UTC (rev 4733) @@ -90,9 +90,15 @@ toSyntaxAnalyzer(toHighlightedText *parent); virtual ~toSyntaxAnalyzer(); + /* + * this method should be "stateless" can be called from "both" threads + */ virtual statementList getStatements(QString const& text) = 0; + virtual statement getStatementAt(unsigned line, unsigned linePos) = 0; + virtual QsciLexer* createLexer(QObject *parent = 0) = 0; + virtual void sanitizeStatement(statement&) = 0; }; Modified: branches/tora3/src/parsing/tosyntaxanalyzernl.cpp =================================================================== --- branches/tora3/src/parsing/tosyntaxanalyzernl.cpp 2013-08-09 20:14:05 UTC (rev 4732) +++ branches/tora3/src/parsing/tosyntaxanalyzernl.cpp 2013-08-09 22:49:22 UTC (rev 4733) @@ -156,8 +156,6 @@ void toSyntaxAnalyzerNL::sanitizeStatement(statement &stat) { - - toHighlightedText *editor = qobject_cast<toHighlightedText *>(parent()); stat.posFrom = editor->SendScintilla(QsciScintilla::SCI_POSITIONFROMLINE, stat.lineFrom); stat.posTo = editor->SendScintilla(QsciScintilla::SCI_GETLINEENDPOSITION, stat.lineTo); Modified: branches/tora3/src/parsing/tosyntaxanalyzeroracle.cpp =================================================================== --- branches/tora3/src/parsing/tosyntaxanalyzeroracle.cpp 2013-08-09 20:14:05 UTC (rev 4732) +++ branches/tora3/src/parsing/tosyntaxanalyzeroracle.cpp 2013-08-09 22:49:22 UTC (rev 4733) @@ -59,12 +59,83 @@ toSyntaxAnalyzer::statementList toSyntaxAnalyzerOracle::getStatements(const QString& text) { toSyntaxAnalyzer::statementList retval; + std::string str(text.toStdString()); + try { + std::auto_ptr <SQLLexer::Lexer> lexer = LexerFactTwoParmSing::Instance().create("OracleGuiLexer", "", "toCustomLexer"); + lexer->setStatement(str.c_str(), str.length()); + + SQLLexer::Lexer::token_const_iterator start = lexer->begin(); + start = lexer->findStartToken(start); + while(start->getTokenType() != SQLLexer::Token::X_EOF) + { + SQLLexer::Lexer::token_const_iterator end = lexer->findEndToken(start); + retval << statement( + start->getPosition().getLine(), + end->getPosition().getLine()); + start = lexer->findStartToken(end); + } + } catch(std::exception const &e) { + std::string s(e.what()); + std::cout << s << std::endl; + } catch(QString const& e) { + qDebug() << e; + } catch(...) { + qDebug() << __FUNCTION__ ; + } return retval; } toSyntaxAnalyzer::statement toSyntaxAnalyzerOracle::getStatementAt(unsigned line, unsigned linePos) { toSyntaxAnalyzer::statement retval; + + toHighlightedText *editor = qobject_cast<toHighlightedText *>(parent()); + std::string str(editor->text().toStdString()); + try { + std::auto_ptr <SQLLexer::Lexer> lexer = LexerFactTwoParmSing::Instance().create("OracleGuiLexer", "", "toCustomLexer"); + lexer->setStatement(str.c_str(), str.length()); + + SQLLexer::Lexer::token_const_iterator start = lexer->begin(); + start = lexer->findStartToken(start); + while(start->getTokenType() != SQLLexer::Token::X_EOF) + { + SQLLexer::Lexer::token_const_iterator end = lexer->findEndToken(start); + retval = statement( + start->getPosition().getLine(), + end->getPosition().getLine()); + start = lexer->findStartToken(end); + + switch(start->getTokenType()) + { + case SQLLexer::Token::L_LPAREN: + case SQLLexer::Token::L_DML_INTRODUCER: // INSERT/UPDATE/DELETE/MERGE + retval.statementType = SELECT; + break; + case SQLLexer::Token::L_PL_INTRODUCER: + retval.statementType = PLSQL; + break; + case SQLLexer::Token::L_OTHER_INTRODUCER: + retval.statementType = OTHER; + break; + case SQLLexer::Token::X_ONE_LINE: + retval.statementType = SQLPLUS; + break; +// DDL, // CREATE +// OTHER, // ALTER SESSION ..., ANALYZE, SET ROLE, EXPLAIN +// SQLPLUS // sqlplus command + } + + if(start->getPosition().getLine() > line) + return retval; + } + } catch(std::exception const &e) { + std::string s(e.what()); + std::cout << s << std::endl; + } catch(QString const& e) { + qDebug() << e; + } catch(...) { + qDebug() << __FUNCTION__ ; + } return retval; } @@ -76,4 +147,7 @@ void toSyntaxAnalyzerOracle::sanitizeStatement(statement& stat) { + toHighlightedText *editor = qobject_cast<toHighlightedText *>(parent()); + stat.posFrom = editor->SendScintilla(QsciScintilla::SCI_POSITIONFROMLINE, stat.lineFrom); + stat.posTo = editor->SendScintilla(QsciScintilla::SCI_GETLINEENDPOSITION, stat.lineTo); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |