2018-06-19 19:52:56 +02:00
|
|
|
|
#ifndef SQLPARSER_H
|
|
|
|
|
|
#define SQLPARSER_H
|
|
|
|
|
|
|
|
|
|
|
|
#include "SqlLexer.h"
|
2019-01-28 20:53:10 +01:00
|
|
|
|
#include "SqlAstNode.h"
|
2018-06-19 19:52:56 +02:00
|
|
|
|
#include <memory>
|
|
|
|
|
|
#include <optional>
|
|
|
|
|
|
|
|
|
|
|
|
enum class Keyword {
|
|
|
|
|
|
NotAKeyword,
|
|
|
|
|
|
As,
|
|
|
|
|
|
By,
|
|
|
|
|
|
Delete,
|
|
|
|
|
|
From,
|
|
|
|
|
|
Group,
|
|
|
|
|
|
Insert,
|
|
|
|
|
|
Order,
|
|
|
|
|
|
Select,
|
|
|
|
|
|
Update,
|
|
|
|
|
|
Where,
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
namespace SqlAst {
|
|
|
|
|
|
|
2019-01-28 20:53:10 +01:00
|
|
|
|
class Node;
|
2018-06-19 19:52:56 +02:00
|
|
|
|
class Select;
|
|
|
|
|
|
class SelectList;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
// The parsing works by calling functions that know either a global part
|
|
|
|
|
|
// or a smaller specific part and is thus recursive. At certain points a function parsing something specific
|
|
|
|
|
|
// will reach a point where it is in a valid terminal state and it encounters something that cannot be a continuation
|
|
|
|
|
|
// of what it is parsing and thus returns succesfully or it is in a non terminal state and encounters something unexpected
|
|
|
|
|
|
// In both cases it will return hoping that one of the functions above can continue (and recover from the error if needed)
|
|
|
|
|
|
|
|
|
|
|
|
class SqlParser
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
explicit SqlParser(SqlLexer &lexer);
|
|
|
|
|
|
|
2019-01-28 20:53:10 +01:00
|
|
|
|
std::shared_ptr<SqlAst::Node> parse();
|
2018-06-19 19:52:56 +02:00
|
|
|
|
|
|
|
|
|
|
/** Checks to see if the next token is the expected keyword.
|
|
|
|
|
|
*
|
|
|
|
|
|
* If it is the token is consumed and the function returns true.
|
|
|
|
|
|
* Otherwise false is returned
|
|
|
|
|
|
*/
|
|
|
|
|
|
std::optional<SqlToken> expectKeyword(Keyword kw);
|
|
|
|
|
|
std::optional<SqlToken> expectSymbol();
|
|
|
|
|
|
std::optional<SqlToken> expectToken(BasicTokenType tt);
|
|
|
|
|
|
|
|
|
|
|
|
/** If the next token is Keyword kw consume it otherwise do nothing.
|
|
|
|
|
|
* In some cases the return value is unimportant as the keyword is completely optional
|
|
|
|
|
|
* in other cases the optional keywords presence might force the next token to be something specific
|
|
|
|
|
|
*
|
|
|
|
|
|
* \return true if the token was found
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool consumeOptionalKeyword(Keyword kw);
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
|
|
//using TokenStack = std::stack<SqlToken>;
|
|
|
|
|
|
|
|
|
|
|
|
//TokenStack tokenStack;
|
|
|
|
|
|
|
|
|
|
|
|
SqlLexer &lexer;
|
|
|
|
|
|
|
|
|
|
|
|
//bool try_reduce(SqkToken token);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // SQLPARSER_H
|