static NODE * statement(void){ NODE *t = NULL; switch (token.type){ case IF: t = if_stmt(); break; case WHILE: t = while_stmt(); break; case READ: t = read(); break; case VAR: t = assign(); break; case PRINT: t = print(); break; case BEGIN: t = stmt_list(); break; default: syntax_error("Unexpected token ->"); token = getToken(); break; } return t; }
struct ifStatement* ifSt() { struct ifStatement* ifstmt; struct statementNode* noop; ifstmt = make_ifSt(); ifstmt->condition = condition(); ttype = getToken(); if(ttype == LBRACE) { //body ifstmt->stmt_list = stmt_list(); noop = make_stmt(NOOPSTMT); //find last stmt stmt ->next = noop; findLast(ifstmt->stmt_list)->next = noop; //true ifstmt->condition->trueBranch = ifstmt->stmt_list; //false //noop = make_stmt(NOOPSTMT); //find last stmt stmt ->next = noop; ifstmt->condition->falseBranch = noop; return ifstmt; } else { return NULL; } }
struct statementNode* stmt_list() { struct statementNode* st; // statement struct statementNode* st1; // statement list struct statementNode* no_op; struct statementNode* gt; st = stmt(); if(ttype == RBRACE) { getToken(); } ttype = getToken(); //printf("TTYPE before %d\n",ttype); if (((ttype == ID)||(ttype == WHILE)||(ttype == PRINT)||(ttype == IF))) { //printf("TTYPE after %d\n",ttype); ungetToken(); st1 = stmt_list(); findLast(st)->next = st1; //stmt head stmt_head = st; return st; } else { return st; } }
void compound_stmt(int level) { int this_line = line_cnt; if(strcmp(tokenPos->textOfLine,"{") == 0) { push(LCGWAL, this_line); push_child(this_line,LOCDEC); local_dec(level+1); push_child(this_line,STMT); stmt_list(level+1); pTreeType[this_line][0] = COM_STMT; pTreeType[this_line][1] = level; if(strcmp(tokenPos->textOfLine,"}") != 0) { print_err(tokenPos->lineNum,tokenPos->textOfLine,"COMPOUND_STMT","}",tokenPos->tokenType); } else { push(RCGWAL, this_line); } } }
void stmt_list(int depth) { if (lookahead == PRINT || lookahead == IF || lookahead == DO_TIMES || lookahead == ID || lookahead == FUNC || lookahead == CALL) { stmt(depth); match(SEMICOLON); stmt_list(depth); } }
Node * parse(void){ Node * t; token = getToken(); t = stmt_list(); if (token != ENDFILE){ syntax_error("still code left in the file\n"); } }
static NODE * if_stmt(void){ NODE * t = new_stmt(N_IF); match(IF); if (t != NULL){ t->child[0] = exp(); } match(THEN); if (t != NULL){ t->child[1] = stmt_list(); } if (token.type == ELSE){ match(ELSE); if (t!= NULL){ t->child[2] = stmt_list(); } } return t; }
opt_stmts(){ printf("in opt_statements : ------ %s\n",yytext); // example : "begin end" if( !match( END ) ){ printf("opt_list : not END \n"); stmt_list(); } }
void parse() { emit(".data \n nl: .asciiz \"\\n\" \n"); emit(".text \n main:"); emit("b start \n"); stmt_list(0); match(EOF); emit("exit: li $v0, 10 \n"); emit("syscall"); }
static NODE * while_stmt(void){ NODE * t = new_stmt(N_WHILE); match(WHILE); if(t != NULL){ t->child[0] = exp(); } match(DO); if(t != NULL) { t->child[1] = stmt_list(); } return t; }
struct statementNode* stmt_list() { struct statementNode* st; // statement struct statementNode* st1; // statement list struct statementNode* no_op; struct gotoStatement* gt; st = stmt(); st1 = NULL; no_op = NULL; //call makestmt? ttype = getToken(); if (!stmt_head && (ttype == ID)|(ttype == WHILE)|(ttype == PRINT)|(ttype == IF)) { ungetToken(); st1 = stmt_list(); if (st->stmtType == IFSTMT) { st->ifSt->stmt_list->next = no_op; st->ifSt->condition->falseBranch = no_op; st->ifSt->condition->trueBranch = st->ifSt->stmt_list; //true? st->next = no_op; //append no_op to st? no_op->next = st1; } if(st->stmtType == WHILE) { gt->target = st; st->whileSt->stmt_list->next = gt->target; st->whileSt->condition->falseBranch = no_op; st->whileSt->condition->trueBranch = st->whileSt->stmt_list; st->next = no_op; no_op->next = st1; } st->next = st1; //stmt head stmt_head = st; return st; } else { return st; } }
struct whileStatement* whileStatement() { struct whileStatement* wSt; struct statementNode* noop; struct statementNode* gt; wSt = make_whileStatement(); wSt->condition = condition(); ttype = getToken(); if(ttype == LBRACE) { //body wSt->stmt_list = stmt_list(); //noop = make_stmt(NOOPSTMT); //findLast(wSt->stmt_list)->next = noop; //true wSt->condition->trueBranch = wSt->stmt_list; //target //gt = make_stmt(GOTOSTMT); //findLast(wSt->condition->trueBranch)->next = gt; //wSt->condition->trueBranch = gt; //false //find last stmt stmt ->next = noop; //wSt->condition->falseBranch = noop; return wSt; } else { return NULL; } }
struct bodyNode* body() { struct bodyNode* bod; ttype = getToken(); //printf("LBRACE %d\n", ttype); if (ttype == LBRACE) { bod = make_body(); bod->stmt_list = stmt_list(); if (ttype == RBRACE) { return bod; } else { return NULL; } } else { return NULL; } }
struct conditionNode* condition() { struct conditionNode* cNode; struct varNode* op1; struct varNode* op2; struct statementNode* tBranch; struct statementNode* fBranch; int op; cNode = make_condition(); ttype = getToken(); if ((ttype == ID)|(ttype == NUM)) { ungetToken(); //ungetToken since it still be parsed cNode->op1 = primary(); //left operand of a condition is a primary ttype = getToken(); if ((ttype == GREATER)|(ttype == GTEQ)|(ttype == LESS) |(ttype == NOTEQUAL)|(ttype == LTEQ)) { cNode->operator = ttype; //relop is set to >, <, etc. ttype = getToken(); if ((ttype == ID)|(ttype == NUM)) { ungetToken(); //ungetToken since it still be parsed cNode->op2 = primary(); //right operand of a condition is a primary ttype = getToken(); if(ttype == RPAREN) { ttype = getToken(); if(ttype == THEN) { cNode->trueBranch = stmt_list(); return cNode; } else { return NULL; } } else { return NULL; } } else { return NULL; } } else { return NULL; } } else { return NULL; } }
TEST_F(ParserUtilTests, BasicTest) { std::vector<std::string> queries; // SELECT statement queries.push_back("SELECT * FROM orders;"); queries.push_back("SELECT MAX(*) FROM orders;"); queries.push_back("SELECT MAX(price) FROM orders;"); queries.push_back("SELECT a FROM orders;"); queries.push_back("SELECT orders.a FROM orders;"); queries.push_back( "SELECT a FROM foo WHERE a > 12 OR b > 3 AND NOT c LIMIT 10"); queries.push_back( "SELECT * FROM foo where bar = 42 ORDER BY id DESC LIMIT 23;"); queries.push_back( "SELECT col1 AS myname, col2, 'test' FROM \"table\", foo AS t WHERE age " "> 12 AND zipcode = 12345 GROUP BY col1;"); queries.push_back( "SELECT * from \"table\" JOIN table2 ON a = b WHERE (b OR NOT a) AND a = " "12.5"); queries.push_back( "(SELECT a FROM foo WHERE a > 12 OR b > 3 AND c NOT LIKE 's%' LIMIT " "10);"); queries.push_back( "SELECT * FROM \"table\" LIMIT 10 OFFSET 10; SELECT * FROM second;"); queries.push_back("SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY col1;"); queries.push_back( "SELECT player_name, year, " "CASE WHEN year = 'SR' THEN 'yes' " "ELSE NULL END AS is_a_senior " "FROM benn.college_football_players"); // JOIN queries.push_back( "SELECT t1.a, t1.b, t2.c FROM \"table\" AS t1 JOIN (SELECT * FROM foo " "JOIN bar ON foo.id = bar.id) t2 ON t1.a = t2.b WHERE (t1.b OR NOT t1.a) " "AND t2.c = 12.5"); queries.push_back("SELECT * FROM t1 JOIN t2 ON c1 = c2;"); queries.push_back("SELECT a, SUM(b) FROM t2 GROUP BY a HAVING SUM(b) > 100;"); // CREATE statement queries.push_back( "CREATE TABLE students (name TEXT, student_number INTEGER, city TEXT, " "grade DOUBLE)"); // Multiple statements queries.push_back( "CREATE TABLE students (name TEXT, student_number INTEGER); SELECT * " "FROM \"table\";"); // INSERT queries.push_back("INSERT INTO test_table VALUES (1, 2, 'test');"); queries.push_back( "INSERT INTO test_table VALUES (1, 2, 'test'), (2, 3, 'test2');"); queries.push_back( "INSERT INTO test_table VALUES (1, 2, 'test'), (2, 3, 'test2'), (3, 4, " "'test3');"); queries.push_back( "INSERT INTO test_table (id, value, name) VALUES (1, 2, 'test');"); queries.push_back( "INSERT INTO test_table (id, value, name) VALUES (1, 2, 'test'), (2, 3, " "'test2');"); queries.push_back( "INSERT INTO test_table (id, value, name) VALUES (1, 2, 'test'), (2, 3, " "'test2'), (3, 4, 'test3');"); queries.push_back("INSERT INTO test_table SELECT * FROM students;"); // DELETE queries.push_back("DELETE FROM students WHERE grade > 3.0"); queries.push_back("DELETE FROM students"); queries.push_back("TRUNCATE students"); // UPDATE queries.push_back( "UPDATE students SET grade = 1.3 WHERE name = 'Max Mustermann';"); queries.push_back( "UPDATE students SET grade = 1.3, name='Felix Fürstenberg' WHERE name = " "'Max Mustermann';"); queries.push_back("UPDATE students SET grade = 1.0;"); // DROP queries.push_back("DROP TABLE students;"); queries.push_back("DROP SCHEMA students;"); queries.push_back("DROP TRIGGER tri ON students;"); // PREPARE queries.push_back( "PREPARE prep_inst AS INSERT INTO test VALUES ($1, $2, $3);"); queries.push_back( "COPY pg_catalog.query_metric TO '/home/user/output.csv' DELIMITER ',';"); // ANALYZE queries.push_back("ANALYZE t ( col1, col2, col3 );"); // EXECUTE queries.push_back("EXECUTE fooplan(1, 'Hunter Valley', 't', 200.00);"); queries.push_back("EXECUTE prep_inst(1, 2, 3);"); queries.push_back("EXECUTE prep;"); // TRANSACTION queries.push_back("BEGIN TRANSACTION;"); queries.push_back("COMMIT TRANSACTION;"); queries.push_back("ROLLBACK TRANSACTION;"); // Parsing UNUSED_ATTRIBUTE int ii = 0; for (auto query : queries) { std::unique_ptr<parser::SQLStatementList> stmt_list( parser::PostgresParser::ParseSQLString(query)); EXPECT_TRUE(stmt_list->is_valid); if (stmt_list->is_valid == false) { LOG_ERROR("Message: %s, line: %d, col: %d", stmt_list->parser_msg, stmt_list->error_line, stmt_list->error_col); } for (auto &stmt : stmt_list->statements) { LOG_TRACE("%s\n", stmt->GetInfo().c_str()); EXPECT_TRUE(stmt->GetInfo().size() > 0); } } }
void stmt(int depth) { if (lookahead == PRINT) { match(PRINT); emit("li $v0,1 \n"); emit("li $t0,"); literal(); emit("\n"); emit("move $a0,$t0 \n"); emit("syscall \n"); // print newline emit("li $v0,4 \n"); emit("la $a0,nl \n"); emit("syscall \n"); } else if (lookahead == IF) { char after_label[10]; new_label(after_label); char else_label[10]; new_label(else_label); match(IF); emit("li $t0,"); literal(); emit("\n beq $t0,0,"); emit(else_label); emit("\n"); match(OPEN_BRACKET); stmt_list(depth+1); match(CLOSE_BRACKET); emit("b "); emit(after_label); emit("\n"); match(ELSE); emit(else_label); emit(":"); match(OPEN_BRACKET); stmt_list(depth+1); match(CLOSE_BRACKET); emit(after_label); emit(":"); } else if (lookahead == DO_TIMES) { // the register used is based on the depth, // so that structures can be nested without conflict. char reg_id[5]; sprintf(reg_id, "$t%d", depth+1); char start_label[10]; new_label(start_label); char end_label[10]; new_label(end_label); match(DO_TIMES); emit("li "); emit(reg_id); emit(",0 \n"); emit(start_label); emit(":"); emit("bge "); emit(reg_id); emit(","); literal(); emit(","); emit(end_label); emit("\n"); match(OPEN_BRACKET); stmt_list(depth+1); match(CLOSE_BRACKET); emit("addi "); emit(reg_id); emit(","); emit(reg_id); emit(",1 \n"); emit("b "); emit(start_label); emit("\n"); emit(end_label); emit(":"); } else if (lookahead == ID) { char lexeme[22] = ""; strcpy(lexeme, token_value_str); match(ID); match(EQUALS); int value = token_value; match(NUM); symtable_insert(lexeme, ID, value); } else if (lookahead == FUNC) { match(FUNC); char func_label[20] = ""; strcpy(func_label, token_value_str); match(ID); emit(func_label); emit(":"); match(OPEN_BRACKET); stmt_list(depth+1); match(CLOSE_BRACKET); emit("b "); emit("exit \n"); } else if (lookahead == CALL) { match(CALL); char func_label[20] = ""; strcpy(func_label, token_value_str); match(ID); emit("b "); emit(func_label); emit("\n"); } }