// Path: src/main/parser/fm/liu/timo/parser/ast/fragment/GroupBy.java
// public class GroupBy implements ASTNode {
//     /** might be {@link LinkedList} */
//     private final List<Pair<Expression, SortOrder>> orderByList;
//     private boolean                                 withRollup = false;
// 
//     public boolean isWithRollup() {
//         return withRollup;
//     }
// 
//     /**
//      * @return never null
//      */
//     public List<Pair<Expression, SortOrder>> getOrderByList() {
//         return orderByList;
//     }
// 
//     /**
//      * performance tip: expect to have only 1 order item
//      */
//     public GroupBy(Expression expr, SortOrder order, boolean withRollup) {
//         this.orderByList = new ArrayList<Pair<Expression, SortOrder>>(1);
//         this.orderByList.add(new Pair<Expression, SortOrder>(expr, order));
//         this.withRollup = withRollup;
//     }
// 
//     /**
//      * performance tip: linked list is used
//      */
//     public GroupBy() {
//         this.orderByList = new LinkedList<Pair<Expression, SortOrder>>();
//     }
// 
//     public GroupBy setWithRollup() {
//         withRollup = true;
//         return this;
//     }
// 
//     public GroupBy addOrderByItem(Expression expr, SortOrder order) {
//         orderByList.add(new Pair<Expression, SortOrder>(expr, order));
//         return this;
//     }
// 
//     @Override
//     public void accept(Visitor visitor) {
//         visitor.visit(this);
//     }
// }
// 
// Path: src/main/parser/fm/liu/timo/parser/ast/fragment/OrderBy.java
// public class OrderBy implements ASTNode {
//     /** might be {@link LinkedList} */
//     private final List<Pair<Expression, SortOrder>> orderByList;
// 
//     public List<Pair<Expression, SortOrder>> getOrderByList() {
//         return orderByList;
//     }
// 
//     /**
//      * performance tip: linked list is used
//      */
//     public OrderBy() {
//         this.orderByList = new LinkedList<Pair<Expression, SortOrder>>();
//     }
// 
//     /**
//      * performance tip: expect to have only 1 order item
//      */
//     public OrderBy(Expression expr, SortOrder order) {
//         this.orderByList = new ArrayList<Pair<Expression, SortOrder>>(1);
//         this.orderByList.add(new Pair<Expression, SortOrder>(expr, order));
//     }
// 
//     public OrderBy(List<Pair<Expression, SortOrder>> orderByList) {
//         if (orderByList == null)
//             throw new IllegalArgumentException("order list is null");
//         this.orderByList = orderByList;
//     }
// 
//     public OrderBy addOrderByItem(Expression expr, SortOrder order) {
//         orderByList.add(new Pair<Expression, SortOrder>(expr, order));
//         return this;
//     }
// 
//     @Override
//     public void accept(Visitor visitor) {
//         visitor.visit(this);
//     }
// }


import static fm.liu.timo.parser.recognizer.mysql.MySQLToken.*;
import java.sql.SQLSyntaxErrorException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import fm.liu.timo.parser.ast.expression.Expression;
import fm.liu.timo.parser.ast.fragment.GroupBy;
import fm.liu.timo.parser.ast.fragment.Limit;
import fm.liu.timo.parser.ast.fragment.OrderBy;
import fm.liu.timo.parser.ast.fragment.tableref.Dual;
import fm.liu.timo.parser.ast.fragment.tableref.TableReference;
import fm.liu.timo.parser.ast.fragment.tableref.TableReferences;
import fm.liu.timo.parser.ast.stmt.dml.DMLQueryStatement;
import fm.liu.timo.parser.ast.stmt.dml.DMLSelectStatement;
import fm.liu.timo.parser.ast.stmt.dml.DMLSelectUnionStatement;
import fm.liu.timo.parser.recognizer.mysql.MySQLToken;
import fm.liu.timo.parser.recognizer.mysql.lexer.MySQLLexer;
import fm.liu.timo.parser.util.Pair;
                                    return option;
                                option.queryCache = DMLSelectStatement.QueryCacheStrategy.SQL_CACHE;
                                break outer;
                            case SQL_NO_CACHE:
                                if (option.queryCache != DMLSelectStatement.QueryCacheStrategy.UNDEF)
                                    return option;
                                option.queryCache =
                                        DMLSelectStatement.QueryCacheStrategy.SQL_NO_CACHE;
                                break outer;
                        }
                    }
                default:
                    return option;
            }
        }
    }

    private List<Pair<Expression, String>> selectExprList() throws SQLSyntaxErrorException {
        Expression expr = exprParser.expression();
        String alias = as();
        List<Pair<Expression, String>> list;
        if (lexer.token() == PUNC_COMMA) {
            list = new LinkedList<Pair<Expression, String>>();
            list.add(new Pair<Expression, String>(expr, alias));
        } else {
            list = new ArrayList<Pair<Expression, String>>(1);
            list.add(new Pair<Expression, String>(expr, alias));
            return list;
        }
        for (; lexer.token() == PUNC_COMMA; list.add(new Pair<Expression, String>(expr, alias))) {
// Path: src/main/parser/fm/liu/timo/parser/ast/fragment/GroupBy.java
// public class GroupBy implements ASTNode {
//     /** might be {@link LinkedList} */
//     private final List<Pair<Expression, SortOrder>> orderByList;
//     private boolean                                 withRollup = false;
// 
//     public boolean isWithRollup() {
//         return withRollup;
//     }
// 
//     /**
//      * @return never null
//      */
//     public List<Pair<Expression, SortOrder>> getOrderByList() {
//         return orderByList;
//     }
// 
//     /**
//      * performance tip: expect to have only 1 order item
//      */
//     public GroupBy(Expression expr, SortOrder order, boolean withRollup) {
//         this.orderByList = new ArrayList<Pair<Expression, SortOrder>>(1);
//         this.orderByList.add(new Pair<Expression, SortOrder>(expr, order));
//         this.withRollup = withRollup;
//     }
// 
//     /**
//      * performance tip: linked list is used
//      */
//     public GroupBy() {
//         this.orderByList = new LinkedList<Pair<Expression, SortOrder>>();
//     }
// 
//     public GroupBy setWithRollup() {
//         withRollup = true;
//         return this;
//     }
// 
//     public GroupBy addOrderByItem(Expression expr, SortOrder order) {
//         orderByList.add(new Pair<Expression, SortOrder>(expr, order));
//         return this;
//     }
// 
//     @Override
//     public void accept(Visitor visitor) {
//         visitor.visit(this);
//     }
// }
// 
// Path: src/main/parser/fm/liu/timo/parser/ast/fragment/OrderBy.java
// public class OrderBy implements ASTNode {
//     /** might be {@link LinkedList} */
//     private final List<Pair<Expression, SortOrder>> orderByList;
// 
//     public List<Pair<Expression, SortOrder>> getOrderByList() {
//         return orderByList;
//     }
// 
//     /**
//      * performance tip: linked list is used
//      */
//     public OrderBy() {
//         this.orderByList = new LinkedList<Pair<Expression, SortOrder>>();
//     }
// 
//     /**
//      * performance tip: expect to have only 1 order item
//      */
//     public OrderBy(Expression expr, SortOrder order) {
//         this.orderByList = new ArrayList<Pair<Expression, SortOrder>>(1);
//         this.orderByList.add(new Pair<Expression, SortOrder>(expr, order));
//     }
// 
//     public OrderBy(List<Pair<Expression, SortOrder>> orderByList) {
//         if (orderByList == null)
//             throw new IllegalArgumentException("order list is null");
//         this.orderByList = orderByList;
//     }
// 
//     public OrderBy addOrderByItem(Expression expr, SortOrder order) {
//         orderByList.add(new Pair<Expression, SortOrder>(expr, order));
//         return this;
//     }
// 
//     @Override
//     public void accept(Visitor visitor) {
//         visitor.visit(this);
//     }
// }


// Path: src/main/parser/fm/liu/timo/parser/recognizer/mysql/syntax/MySQLDMLSelectParser.java
import static fm.liu.timo.parser.recognizer.mysql.MySQLToken.*;
import java.sql.SQLSyntaxErrorException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import fm.liu.timo.parser.ast.expression.Expression;
import fm.liu.timo.parser.ast.fragment.GroupBy;
import fm.liu.timo.parser.ast.fragment.Limit;
import fm.liu.timo.parser.ast.fragment.OrderBy;
import fm.liu.timo.parser.ast.fragment.tableref.Dual;
import fm.liu.timo.parser.ast.fragment.tableref.TableReference;
import fm.liu.timo.parser.ast.fragment.tableref.TableReferences;
import fm.liu.timo.parser.ast.stmt.dml.DMLQueryStatement;
import fm.liu.timo.parser.ast.stmt.dml.DMLSelectStatement;
import fm.liu.timo.parser.ast.stmt.dml.DMLSelectUnionStatement;
import fm.liu.timo.parser.recognizer.mysql.MySQLToken;
import fm.liu.timo.parser.recognizer.mysql.lexer.MySQLLexer;
import fm.liu.timo.parser.util.Pair;

                                    return option;
                                option.queryCache = DMLSelectStatement.QueryCacheStrategy.SQL_CACHE;
                                break outer;
                            case SQL_NO_CACHE:
                                if (option.queryCache != DMLSelectStatement.QueryCacheStrategy.UNDEF)
                                    return option;
                                option.queryCache =
                                        DMLSelectStatement.QueryCacheStrategy.SQL_NO_CACHE;
                                break outer;
                        }
                    }
                default:
                    return option;
            }
        }
    }

    private List<Pair<Expression, String>> selectExprList() throws SQLSyntaxErrorException {
        Expression expr = exprParser.expression();
        String alias = as();
        List<Pair<Expression, String>> list;
        if (lexer.token() == PUNC_COMMA) {
            list = new LinkedList<Pair<Expression, String>>();
            list.add(new Pair<Expression, String>(expr, alias));
        } else {
            list = new ArrayList<Pair<Expression, String>>(1);
            list.add(new Pair<Expression, String>(expr, alias));
            return list;
        }
        for (; lexer.token() == PUNC_COMMA; list.add(new Pair<Expression, String>(expr, alias))) {
            lexer.nextToken();