【MYSQL】mysql语法解析代码小demo

例子:select * from a left join b where a.id = 1 and (b.id = a.id or a.num*3 = 7)
首先,我们需要构建文法的产生式集合:

  1. S’ -> S
  2. S -> SELECT FROM TABLE WHERE
  3. SELECT -> select *
  4. FROM -> from TABLE
  5. TABLE -> table1 left join table2
  6. WHERE -> EXP and EXP
  7. WHERE -> (EXP or EXP)
  8. EXP -> TABLE PROPERTY OP VALUE
  9. EXP -> TABLE PROPERTY OP TABLE PROPERTY
  10. EXP -> EXP and EXP
  11. EXP -> (EXP or EXP)
  12. TABLE -> a
  13. TABLE -> b
  14. PROPERTY -> id
  15. PROPERTY -> num
  16. OP -> *
  17. OP -> =

接下来,我们构建项目集族和LR(1)分析表。

首先,计算项目集族的闭包:

I0:
S’ -> . S
S -> . SELECT FROM TABLE WHERE
S -> . SELECT FROM TABLE
S -> . SELECT FROM
S -> . SELECT
SELECT -> . select *
FROM -> . from TABLE
TABLE -> . table1 left join table2
TABLE -> . a
TABLE -> . b
PROPERTY -> . id
PROPERTY -> . num
OP -> . *
OP -> . =
WHERE -> . EXP and EXP
WHERE -> . (EXP or EXP)
EXP -> . TABLE PROPERTY OP VALUE
EXP -> . TABLE PROPERTY OP TABLE PROPERTY
EXP -> . EXP and EXP
EXP -> . (EXP or EXP)

根据闭包操作,我们可以得到以下项目集:

I0:
S’ -> . S
S -> . SELECT FROM TABLE WHERE
S -> . SELECT FROM TABLE
S -> . SELECT FROM
S -> . SELECT
SELECT -> . select *
FROM -> . from TABLE
TABLE -> . table1 left join table2
TABLE -> . a
TABLE -> . b
PROPERTY -> . id
PROPERTY -> . num
OP -> . *
OP -> . =
WHERE -> . EXP and EXP
WHERE -> . (EXP or EXP)
EXP -> . TABLE PROPERTY OP VALUE
EXP -> . TABLE PROPERTY OP TABLE PROPERTY
EXP -> . EXP and EXP
EXP -> . (EXP or EXP)

I1:
S’ -> S .

I2:
S -> SELECT . FROM TABLE WHERE
S -> SELECT . FROM TABLE

I3:
FROM -> from . TABLE

I4:
TABLE -> table1 . left join table2

I5:
TABLE -> a .

I6:
TABLE -> b .

I7:
PROPERTY -> id .

I8:
PROPERTY -> num .

I9:
OP -> * .

I10:
OP -> = .

I11:
WHERE -> EXP . and EXP
WHERE -> EXP . and EXP

I12:
WHERE -> ( EXP . or EXP

I13:
EXP -> TABLE . PROPERTY OP VALUE
EXP -> TABLE . PROPERTY OP TABLE PROPERTY
EXP -> EXP . and EXP
EXP -> EXP . and EXP

I14:
EXP -> ( EXP . or EXP

I15:
EXP -> TABLE PROPERTY . OP VALUE
EXP -> TABLE PROPERTY . OP TABLE PROPERTY

I16:
EXP -> ( EXP . or EXP

I17:
EXP -> TABLE PROPERTY OP . VALUE
EXP -> TABLE PROPERTY OP . TABLE PROPERTY

I18:
EXP -> TABLE PROPERTY OP VALUE .
EXP -> TABLE PROPERTY OP TABLE PROPERTY .

I19:
WHERE -> EXP and . EXP

I20:
WHERE -> EXP and EXP .

I21:
WHERE -> ( EXP . or EXP

I22:
EXP -> ( EXP . or EXP

I23:
EXP -> ( EXP or . EXP

I24:
EXP -> ( EXP or EXP .

然后,我们可以根据项目集的转移操作,构建LR(1)分析表:

Action表:

select*fromtable1leftjointable2abidnum=()andor$
0s3s4
1r3r3r3r3r3r3r3r3
2r5r5r5r5r5r5r5r5
3s6s7
4r7r7r7r7r7r7r7r7
5r1
6r4
7r6
8
9s12
10
11s13
12
13s14
14
15r8
16r9

Goto表:

select*fromtable1leftjointable2abidnum=()andor$
0s3s4
1
2
3s6s7
4r7
5r1
6r4
7r6
8
9s12
10
11s13
12
13s14
14
15r8
16r9

接下来我们根据输入的符号进行移进和规约操作:

输入: select * from table1 left join table2 a on b.id = a.id and b.num = a.num

当前状态: 0
接下来的输入符号: select

根据Goto表,在状态0下,输入select,我们需要移进到状态3。

移进到状态3。

输入: * from table1 left join table2 a on b.id = a.id and b.num = a.num

当前状态: 3
接下来的输入符号: *

根据Goto表,在状态3下,输入*,我们需要移进到状态6。

移进到状态6。

输入: from table1 left join table2 a on b.id = a.id and b.num = a.num

当前状态: 6
接下来的输入符号: from

根据Goto表,在状态6下,输入from,我们需要移进到状态7。

移进到状态7。

输入: table1 left join table2 a on b.id = a.id and b.num = a.num

当前状态: 7
接下来的输入符号: table1

根据Goto表,在状态7下,输入table1,我们需要移进到状态12。

移进到状态12。

输入: left join table2 a on b.id = a.id and b.num = a.num

当前状态: 12
接下来的输入符号: left

根据Goto表,在状态12下,输入left,我们需要移进到状态13。

移进到状态13。

输入: join table2 a on b.id = a.id and b.num = a.num

当前状态: 13
接下来的输入符号: join

根据Goto表,在状态13下,输入join,我们需要移进到状态14。

移进到状态14。

输入: table2 a on b.id = a.id and b.num = a.num

当前状态: 14
接下来的输入符号: table2

根据Goto表,在状态14下,输入table2,我们需要移进到状态5。

移进到状态5。

输入: a on b.id = a.id and b.num = a.num

当前状态: 5
接下来的输入符号: a

根据Goto表,在状态5下,输入a,我们需要移进到状态8。

移进到状态8。

输入: on b.id = a.id and b.num = a.num

当前状态: 8
接下来的输入符号: on

根据Goto表,在状态8下,输入on,我们需要移进到状态9。

移进到状态9。

输入: b.id = a.id and b.num = a.num

当前状态: 9
接下来的输入符号: b.id

根据Goto表,在状态9下,输入b.id,我们需要移进到状态10。

移进到状态10。

输入: = a.id and b.num = a.num

当前状态: 10
接下来的输入符号: =

根据Goto表,在状态10下,输入=,我们需要移进到状态11。

移进到状态11。

输入: a.id and b.num = a.num

当前状态: 11
接下来的输入符号: a.id

根据Goto表,在状态11下,输入a.id,我们需要移进到状态15。

移进到状态15。

输入: and b.num = a.num

当前状态: 15
接下来的输入符号: and

根据Goto表,在状态15下,输入and,我们需要移进到状态16。

移进到状态16。

输入: b.num = a.num

当前状态: 16
接下来的输入符号: b.num

根据Goto表,在状态16下,输入b.num,我们需要移进到状态17。

移进到状态17。

输入: = a.num

当前状态: 17
接下来的输入符号: =

根据Goto表,在状态17下,输入=,我们需要移进到状态18。

移进到状态18。

输入: a.num

当前状态: 18
接下来的输入符号: a.num

根据Goto表,在状态18下,输入a.num,我们需要移进到状态19。

移进到状态19。

输入:

当前状态: 19
接下来的输入符号:

根据Goto表,在状态19下,输入空符号,我们需要进行规约操作。

根据规约动作表,我们使用规则R10,将状态19中的符号归约为expression。

当前状态: 9
接下来的输入符号: b.id

根据Goto表,在状态9下,输入b.id,我们需要移进到状态10。

移进到状态10。

输入: = a.id and b.num = a.num

当前状态: 10
接下来的输入符号: =

根据Goto表,在状态10下,输入=,我们需要移进到状态11。

移进到状态11。

输入: a.id and b.num = a.num

当前状态: 11
接下来的输入符号: a.id

根据Goto表,在状态11下,输入a.id,我们需要移进到状态15。

移进到状态15。

输入: and b.num = a.num

当前状态: 15
接下来的输入符号: and

根据Goto表,在状态15下,输入and,我们需要移进到状态16。

移进到状态16。

输入: b.num = a.num

当前状态: 16
接下来的输入符号: b.num

根据Goto表,在状态16下,输入b.num,我们需要移进到状态17。

移进到状态17。

输入: = a.num

当前状态: 17
接下来的输入符号: =

根据Goto表,在状态17下,输入=,我们需要移进到状态18。

移进到状态18。

输入: a.num

当前状态: 18
接下来的输入符号: a.num

根据Goto表,在状态18下,输入a.num,我们需要移进到状态19。

移进到状态19。

输入:

当前状态: 19
接下来的输入符号:

根据Goto表,在状态19下,输入空符号,我们需要进行规约操作。

根据规约动作表,我们使用规则R10,将状态19中的符号归约为expression。

当前状态: 10
接下来的输入符号:

根据Goto表,在状态10下,输入空符号,我们需要进行规约操作。

根据规约动作表,我们使用规则R8,将状态10中的符号归约为condition。

当前状态: 11
接下来的输入符号:

根据Goto表,在状态11下,输入空符号,我们需要进行规约操作。

根据规约动作表,我们使用规则R7,将状态11中的符号归约为expression。

当前状态: 15
接下来的输入符号:

根据Goto表,在状态15下,输入空符号,我们需要进行规约操作。

根据规约动作表,我们使用规则R6,将状态15中的符号归约为condition。

当前状态: 8
接下来的输入符号:

根据Goto表,在状态8下,输入空符号,我们需要进行规约操作。

根据规约动作表,我们使用规则R5,将状态8中的符号归约为expression。

当前状态: 5
接下来的输入符号:

根据Goto表,在状态5下,输入空符号,我们需要进行规约操作。

根据规约动作表,我们使用规则R4,将状态5中的符号归约为expression。

当前状态: 4
接下来的输入符号:

根据Goto表,在状态4下,输入空符号,我们需要进行规约操作。

根据规约动作表,我们使用规则R3,将状态4中的符号归约为expression。

当前状态: 3
接下来的输入符号:

根据Goto表,在状态3下,输入空符号,我们需要进行规约操作。

根据规约动作表,我们使用规则R2,将状态3中的符号归约为statement。

当前状态: 2
接下来的输入符号:

根据Goto表,在状态2下,输入空符号,我们需要进行规约操作。

根据规约动作表,我们使用规则R1,将状态2中的符号归约为program。

最后,我们得到了完整的语法分析树,输入的查询语句被成功解析。

#include <iostream>
#include <stack>
#include <unordered_map>
#include <vector>

using namespace std;

// Token 类型枚举
enum class TokenType {
    SELECT, FROM, JOIN, WHERE, ID, EQUAL, NUM, AND, OR, LPAREN, RPAREN, END
};

// Token 类
struct Token {
    TokenType type;
    string lexeme;
};

// 产生式类
struct Production {
    TokenType left;
    vector<TokenType> right;
};

// Action 表
unordered_map<int, unordered_map<TokenType, int>> actionTable = {
        {0, {{TokenType::SELECT, 1}}},
        {1, {{TokenType::ID, 4}}},
        {2, {{TokenType::FROM, 6}}},
        {3, {{TokenType::ID, 5}}},
        {4, {{TokenType::FROM, -5}}},
        {5, {{TokenType::JOIN, 7}}},
        {6, {{TokenType::JOIN, -6}, {TokenType::WHERE, 10}}},
        {7, {{TokenType::ID, 8}}},
        {8, {{TokenType::WHERE, 10}}},
        {9, {{TokenType::AND, 16}, {TokenType::OR, 17}, {TokenType::RPAREN, 16}, {TokenType::END, -3}}},
        {10, {{TokenType::ID, 11}}},
        {11, {{TokenType::EQUAL, 12}}},
        {12, {{TokenType::NUM, 13}, {TokenType::LPAREN, 14}}},
        {13, {{TokenType::RPAREN, -4}, {TokenType::AND, -4}, {TokenType::OR, -4}, {TokenType::END, -4}}},
        {14, {{TokenType::ID, 15}}},
        {15, {{TokenType::EQUAL, 12}}},
        {16, {{TokenType::ID, 11}}},
        {17, {{TokenType::ID, 11}}}
};

// Goto 表
unordered_map<int, unordered_map<TokenType, int>> gotoTable = {
        {0, {{TokenType::SELECT, 1}, {TokenType::FROM, 2}, {TokenType::JOIN, 3}}},
        {4, {{TokenType::FROM, 5}}},
        {6, {{TokenType::JOIN, 14}}},
        {10, {{TokenType::WHERE, 15}}},
        {12, {{TokenType::LPAREN, 18}}},
        {16, {{TokenType::RPAREN, 19}}}
};

// LR(1) 语法分析器类
class LRParser {
public:
    LRParser(const vector<Token>& tokens) : tokens(tokens) {}

    void parse() {
        stack<int> stateStack;
        stack<Token> symbolStack;
        stateStack.push(0);

        int i = 0;
        while (true) {
            int currentState = stateStack.top();
            Token currentToken = tokens[i];
            int action = actionTable[currentState][currentToken.type];

            if (action == 0) {
                cout << "Accepted" << endl;
                break;
            } else if (action > 0) {
                // 移进
                stateStack.push(action);
                symbolStack.push(currentToken);
                i++;
                cout<< currentToken.lexeme << endl;
            } else if (action < 0) {
                // 规约
                Production production = grammar[-action];
                TokenType nonterminal = production.left;

                cout << "Reduce: ";
                for (auto token : production.right) {
                    stateStack.pop();
                    symbolStack.pop();
                }
                cout<< currentToken.lexeme << endl;

                int newState = gotoTable[stateStack.top()][nonterminal];
                stateStack.push(newState);
                symbolStack.push(Token{nonterminal, ""});
            }
        }
    }

private:
    vector<Token> tokens;
    unordered_map<int, Production> grammar = {
            {-1, {TokenType::SELECT, {TokenType::ID}}},
            {-2, {TokenType::FROM, {TokenType::ID}}},
            {-3, {TokenType::JOIN, {TokenType::ID}}},
            {-4, {TokenType::WHERE, {TokenType::ID, TokenType::EQUAL, TokenType::NUM}}},
    };
};

int main() {
    vector<Token> tokens = {
            {TokenType::SELECT, "select"},
            {TokenType::ID, "*"},
            {TokenType::FROM, "from"},
            {TokenType::ID, "a"},
            {TokenType::JOIN, "left join"},
            {TokenType::ID, "b"},
            {TokenType::WHERE, "where"},
            {TokenType::ID, "a.id"},
            {TokenType::NUM, "3"},
    };

    LRParser parser(tokens);
    parser.parse();

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值