Implemented conversion from parse tree to SQL structure.
Added debug printing for SQL statements.
This commit is contained in:
@@ -10,8 +10,8 @@ Statement = SelectStmt | InsertStmt | UpdateStmt | DeleteStmt | CreateStmt | Dro
|
|||||||
|
|
||||||
SelectStmt = 'Select', FieldList, 'From', Identifier, ['Where', ComparisonGroup] ;
|
SelectStmt = 'Select', FieldList, 'From', Identifier, ['Where', ComparisonGroup] ;
|
||||||
InsertStmt = 'Insert Into', Identifier, 'Set', AssignmentList ;
|
InsertStmt = 'Insert Into', Identifier, 'Set', AssignmentList ;
|
||||||
UpdateStmt = 'Update', Identifier, 'Set', AssignmentList, 'Where', AssignmentList ;
|
UpdateStmt = 'Update', Identifier, 'Set', AssignmentList, 'Where', ComparisonGroup ;
|
||||||
DeleteStmt = 'Delete From', Identifier, 'Where', AssignmentList ;
|
DeleteStmt = 'Delete From', Identifier, 'Where', ComparisonGroup ;
|
||||||
CreateStmt = 'Create Table', Identifier, '(', ColumnSpecList, ')' ;
|
CreateStmt = 'Create Table', Identifier, '(', ColumnSpecList, ')' ;
|
||||||
DropStmt = 'Drop Table', Identifier ;
|
DropStmt = 'Drop Table', Identifier ;
|
||||||
|
|
||||||
|
|||||||
154
src/SQL.c
154
src/SQL.c
@@ -3,10 +3,13 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include "SQL.h"
|
#include "SQL.h"
|
||||||
|
|
||||||
Value *new_value() {
|
Value *new_value() {
|
||||||
Value *value = malloc(sizeof(Value));
|
Value *value = malloc(sizeof(Value));
|
||||||
|
value->type = VALUE_NONE;
|
||||||
value->number = 0;
|
value->number = 0;
|
||||||
value->string = NULL;
|
value->string = NULL;
|
||||||
return value;
|
return value;
|
||||||
@@ -177,7 +180,7 @@ SelectStmt *new_select_stmt() {
|
|||||||
|
|
||||||
void free_select_stmt(SelectStmt *stmt) {
|
void free_select_stmt(SelectStmt *stmt) {
|
||||||
if (stmt->where != NULL) {
|
if (stmt->where != NULL) {
|
||||||
free_assignment_list(stmt->where);
|
free_comparison_group(stmt->where);
|
||||||
}
|
}
|
||||||
if (stmt->tableName != NULL) {
|
if (stmt->tableName != NULL) {
|
||||||
free(stmt->tableName);
|
free(stmt->tableName);
|
||||||
@@ -218,7 +221,7 @@ void free_update_stmt(UpdateStmt *stmt) {
|
|||||||
free(stmt->tableName);
|
free(stmt->tableName);
|
||||||
}
|
}
|
||||||
if (stmt->where != NULL) {
|
if (stmt->where != NULL) {
|
||||||
free_assignment_list(stmt->where);
|
free_comparison_group(stmt->where);
|
||||||
}
|
}
|
||||||
if (stmt->values != NULL) {
|
if (stmt->values != NULL) {
|
||||||
free_assignment_list(stmt->values);
|
free_assignment_list(stmt->values);
|
||||||
@@ -237,7 +240,7 @@ void free_delete_stmt(DeleteStmt *stmt) {
|
|||||||
free(stmt->tableName);
|
free(stmt->tableName);
|
||||||
}
|
}
|
||||||
if (stmt->where != NULL) {
|
if (stmt->where != NULL) {
|
||||||
free_assignment_list(stmt->where);
|
free_comparison_group(stmt->where);
|
||||||
}
|
}
|
||||||
free(stmt);
|
free(stmt);
|
||||||
}
|
}
|
||||||
@@ -272,10 +275,10 @@ void free_drop_stmt(DropStmt *stmt) {
|
|||||||
free(stmt);
|
free(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
Statement *new_statement() {
|
Statement *new_statement(StatementType type, void *statement) {
|
||||||
Statement *stmt = malloc(sizeof(Statement));
|
Statement *stmt = malloc(sizeof(Statement));
|
||||||
stmt->type = STMT_NONE;
|
stmt->type = type;
|
||||||
stmt->stmt = NULL;
|
stmt->stmt = statement;
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,4 +333,143 @@ void append_statement_list(StatementList *list, Statement *statement) {
|
|||||||
list->length++;
|
list->length++;
|
||||||
list->statements = realloc(list->statements, sizeof(Statement *) * list->length);
|
list->statements = realloc(list->statements, sizeof(Statement *) * list->length);
|
||||||
list->statements[list->length - 1] = statement;
|
list->statements[list->length - 1] = statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_statement_list(StatementList *list) {
|
||||||
|
|
||||||
|
for (size_t i = 0; i < list->length; i++) {
|
||||||
|
Statement *stmt = list->statements[i];
|
||||||
|
switch (stmt->type) {
|
||||||
|
case STMT_SELECT: {
|
||||||
|
SelectStmt *select = stmt->stmt;
|
||||||
|
printf("SELECT ");
|
||||||
|
print_field_list(select->fields);
|
||||||
|
printf(" FROM %s", select->tableName);
|
||||||
|
if (select->where->length > 0) {
|
||||||
|
printf(" WHERE ");
|
||||||
|
print_comparison_group(select->where);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STMT_INSERT: {
|
||||||
|
InsertStmt *insert = stmt->stmt;
|
||||||
|
printf("INSERT INTO %s SET ", insert->tableName);
|
||||||
|
print_assignment_list(insert->values);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STMT_UPDATE: {
|
||||||
|
UpdateStmt *update = stmt->stmt;
|
||||||
|
printf("UPDATE %s SET ", update->tableName);
|
||||||
|
print_assignment_list(update->values);
|
||||||
|
if (update->where->length > 0) {
|
||||||
|
printf(" WHERE ");
|
||||||
|
print_comparison_group(update->where);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STMT_DELETE: {
|
||||||
|
DeleteStmt *delete = stmt->stmt;
|
||||||
|
printf("DELETE FROM %s", delete->tableName);
|
||||||
|
if (delete->where->length > 0) {
|
||||||
|
printf(" ");
|
||||||
|
print_comparison_group(delete->where);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STMT_CREATE: {
|
||||||
|
CreateStmt *create = stmt->stmt;
|
||||||
|
printf("CREATE TABLE %s (", create->tableName);
|
||||||
|
print_column_spec_list(create->columns);
|
||||||
|
printf(")");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STMT_DROP: {
|
||||||
|
DropStmt *drop = stmt->stmt;
|
||||||
|
printf("DELETE TABLE %s", drop->tableName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf(";\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_field_list(FieldList *list) {
|
||||||
|
for (size_t i = 0; i < list->length; i++) {
|
||||||
|
printf("%s%s", list->fields[i], i + 1 < list->length ? ", " : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_assignment_list(AssignmentList *list) {
|
||||||
|
for (size_t i = 0; i < list->length; i++) {
|
||||||
|
Assignment *assignment = list->assignments[i];
|
||||||
|
printf("%s=", assignment->identifier);
|
||||||
|
print_value(assignment->value);
|
||||||
|
if (i + 1 < list->length) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_comparison_group(ComparisonGroup *group) {
|
||||||
|
for (size_t i = 0; i < group->length; i++) {
|
||||||
|
Comparison *comparison = group->comparisons[i];
|
||||||
|
printf("%s=", comparison->identifier);
|
||||||
|
print_value(comparison->value);
|
||||||
|
if (i + 1 < group->length) {
|
||||||
|
printf(" AND ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_column_spec_list(ColumnSpecList *list) {
|
||||||
|
for (size_t i = 0; i < list->length; i++) {
|
||||||
|
ColumnSpec *spec = list->columns[i];
|
||||||
|
if (spec->type == COLTYPE_STRING) {
|
||||||
|
printf("%s STRING(%d)", spec->identifier, spec->size);
|
||||||
|
} else if (spec->type == COLTYPE_INT) {
|
||||||
|
printf("%s INTEGER", spec->identifier);
|
||||||
|
}
|
||||||
|
if (spec->option == COLOPT_INDEX) {
|
||||||
|
printf(" INDEX");
|
||||||
|
}
|
||||||
|
if (i + 1 < list->length) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_value(Value *value) {
|
||||||
|
if (value->type == VALUE_STRING) {
|
||||||
|
printf("'");
|
||||||
|
size_t len = strlen(value->string);
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
char next = value->string[i];
|
||||||
|
switch (next) {
|
||||||
|
case '\'':
|
||||||
|
printf("\\'");
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
printf("\\n");
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
printf("\\r");
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
printf("\\t");
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
printf("\\\\");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("%c", next);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("'");
|
||||||
|
} else if (value->type == VALUE_NUMBER) {
|
||||||
|
printf("%lld", value->number);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
41
src/SQL.h
41
src/SQL.h
@@ -8,11 +8,19 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
union Value_t {
|
enum ValueType_t {
|
||||||
char *string;
|
VALUE_NONE,
|
||||||
uint64_t number;
|
VALUE_STRING,
|
||||||
|
VALUE_NUMBER
|
||||||
};
|
};
|
||||||
typedef union Value_t Value;
|
typedef enum ValueType_t ValueType;
|
||||||
|
|
||||||
|
struct Value_t {
|
||||||
|
ValueType type;
|
||||||
|
char *string;
|
||||||
|
int64_t number;
|
||||||
|
};
|
||||||
|
typedef struct Value_t Value;
|
||||||
|
|
||||||
Value *new_value();
|
Value *new_value();
|
||||||
|
|
||||||
@@ -33,6 +41,7 @@ struct Comparison_t {
|
|||||||
typedef struct Comparison_t Comparison;
|
typedef struct Comparison_t Comparison;
|
||||||
|
|
||||||
Comparison *new_comparison();
|
Comparison *new_comparison();
|
||||||
|
|
||||||
void free_comparison(Comparison *comparison);
|
void free_comparison(Comparison *comparison);
|
||||||
|
|
||||||
struct ComparisonGroup_t {
|
struct ComparisonGroup_t {
|
||||||
@@ -42,7 +51,9 @@ struct ComparisonGroup_t {
|
|||||||
typedef struct ComparisonGroup_t ComparisonGroup;
|
typedef struct ComparisonGroup_t ComparisonGroup;
|
||||||
|
|
||||||
ComparisonGroup *new_comparision_group();
|
ComparisonGroup *new_comparision_group();
|
||||||
void free_comparison_group(ComparisonGroup* group);
|
|
||||||
|
void free_comparison_group(ComparisonGroup *group);
|
||||||
|
|
||||||
void append_comparison_group(ComparisonGroup *group, Comparison *comparison);
|
void append_comparison_group(ComparisonGroup *group, Comparison *comparison);
|
||||||
|
|
||||||
struct Assignment_t {
|
struct Assignment_t {
|
||||||
@@ -119,7 +130,7 @@ void append_column_spec_list(ColumnSpecList *list, ColumnSpec *spec);
|
|||||||
struct SelectStmt_t {
|
struct SelectStmt_t {
|
||||||
FieldList *fields;
|
FieldList *fields;
|
||||||
char *tableName;
|
char *tableName;
|
||||||
AssignmentList *where;
|
ComparisonGroup *where;
|
||||||
};
|
};
|
||||||
typedef struct SelectStmt_t SelectStmt;
|
typedef struct SelectStmt_t SelectStmt;
|
||||||
|
|
||||||
@@ -140,7 +151,7 @@ void free_insert_stmt(InsertStmt *stmt);
|
|||||||
struct UpdateStmt_t {
|
struct UpdateStmt_t {
|
||||||
char *tableName;
|
char *tableName;
|
||||||
AssignmentList *values;
|
AssignmentList *values;
|
||||||
AssignmentList *where;
|
ComparisonGroup *where;
|
||||||
};
|
};
|
||||||
typedef struct UpdateStmt_t UpdateStmt;
|
typedef struct UpdateStmt_t UpdateStmt;
|
||||||
|
|
||||||
@@ -150,7 +161,7 @@ void free_update_stmt(UpdateStmt *stmt);
|
|||||||
|
|
||||||
struct DeleteStmt_t {
|
struct DeleteStmt_t {
|
||||||
char *tableName;
|
char *tableName;
|
||||||
AssignmentList *where;
|
ComparisonGroup *where;
|
||||||
};
|
};
|
||||||
typedef struct DeleteStmt_t DeleteStmt;
|
typedef struct DeleteStmt_t DeleteStmt;
|
||||||
|
|
||||||
@@ -194,7 +205,7 @@ struct Statement_t {
|
|||||||
};
|
};
|
||||||
typedef struct Statement_t Statement;
|
typedef struct Statement_t Statement;
|
||||||
|
|
||||||
Statement *new_statement();
|
Statement *new_statement(StatementType type, void *statement);
|
||||||
|
|
||||||
void free_statement(Statement *stmt);
|
void free_statement(Statement *stmt);
|
||||||
|
|
||||||
@@ -210,4 +221,16 @@ void free_statement_list(StatementList *list);
|
|||||||
|
|
||||||
void append_statement_list(StatementList *list, Statement *statement);
|
void append_statement_list(StatementList *list, Statement *statement);
|
||||||
|
|
||||||
|
void print_statement_list(StatementList *list);
|
||||||
|
|
||||||
|
void print_field_list(FieldList *list);
|
||||||
|
|
||||||
|
void print_assignment_list(AssignmentList *list);
|
||||||
|
|
||||||
|
void print_comparison_group(ComparisonGroup *group);
|
||||||
|
|
||||||
|
void print_column_spec_list(ColumnSpecList *list);
|
||||||
|
|
||||||
|
void print_value(Value *value);
|
||||||
|
|
||||||
#endif //SDB_SQL_H
|
#endif //SDB_SQL_H
|
||||||
|
|||||||
@@ -36,6 +36,11 @@ void parse_input(char *input) {
|
|||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
printf("%s\n", input);
|
printf("%s\n", input);
|
||||||
parser_print_node_tree(node, 0);
|
parser_print_node_tree(node, 0);
|
||||||
|
|
||||||
|
StatementList* list = parser_node_convert(node);
|
||||||
|
print_statement_list(list);
|
||||||
|
free_statement_list(list);
|
||||||
|
|
||||||
free_parser_node(node);
|
free_parser_node(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
153
src/parser.c
153
src/parser.c
@@ -76,6 +76,149 @@ void free_parser(Parser *parser) {
|
|||||||
free(parser);
|
free(parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatementList *parser_node_convert(ParserNode *node) {
|
||||||
|
if (node->type != NODE_STATEMENT_LIST) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementList *list = new_statement_list();
|
||||||
|
|
||||||
|
size_t i, k;
|
||||||
|
|
||||||
|
for (i = 0; i < node->childrenLength; i++) {
|
||||||
|
ParserNode *child = node->children[i];
|
||||||
|
switch (child->type) {
|
||||||
|
case NODE_SELECT_STMT: {
|
||||||
|
SelectStmt *select = new_select_stmt();
|
||||||
|
append_statement_list(list, new_statement(STMT_SELECT, select));
|
||||||
|
select->fields = new_field_list();
|
||||||
|
select->tableName = strdup(child->children[1]->token->valueStr);
|
||||||
|
for (k = 0; k < child->children[0]->childrenLength; k++) {
|
||||||
|
ParserNode *fieldNode = child->children[0]->children[k];
|
||||||
|
append_field_list(select->fields, strdup(fieldNode->token->valueStr));
|
||||||
|
}
|
||||||
|
if (child->childrenLength == 3) {
|
||||||
|
select->where = parser_node_convert_comparison_group(child->children[2]);
|
||||||
|
} else {
|
||||||
|
select->where = new_comparision_group();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NODE_INSERT_STMT: {
|
||||||
|
InsertStmt *insert = new_insert_stmt();
|
||||||
|
append_statement_list(list, new_statement(STMT_INSERT, insert));
|
||||||
|
insert->tableName = strdup(child->children[0]->token->valueStr);
|
||||||
|
insert->values = parser_node_convert_assignment_list(child->children[1]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NODE_UPDATE_STMT: {
|
||||||
|
UpdateStmt *update = new_update_stmt();
|
||||||
|
append_statement_list(list, new_statement(STMT_UPDATE, update));
|
||||||
|
update->tableName = strdup(child->children[0]->token->valueStr);
|
||||||
|
update->values = parser_node_convert_assignment_list(child->children[1]);
|
||||||
|
if (child->childrenLength == 3) {
|
||||||
|
update->where = parser_node_convert_comparison_group(child->children[2]);
|
||||||
|
} else {
|
||||||
|
update->where = new_comparision_group();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NODE_DELETE_STMT: {
|
||||||
|
DeleteStmt *delete = new_delete_stmt();
|
||||||
|
append_statement_list(list, new_statement(STMT_DELETE, delete));
|
||||||
|
delete->tableName = strdup(child->children[0]->token->valueStr);
|
||||||
|
if (child->childrenLength == 2) {
|
||||||
|
delete->where = parser_node_convert_comparison_group(child->children[1]);
|
||||||
|
} else {
|
||||||
|
delete->where = new_comparision_group();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NODE_CREATE_STMT: {
|
||||||
|
CreateStmt *create = new_create_stmt();
|
||||||
|
append_statement_list(list, new_statement(STMT_CREATE, create));
|
||||||
|
create->tableName = strdup(child->children[0]->token->valueStr);
|
||||||
|
create->columns = parser_node_convert_column_spec_list(child->children[1]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NODE_DROP_STMT: {
|
||||||
|
DropStmt *drop= new_drop_stmt();
|
||||||
|
append_statement_list(list, new_statement(STMT_DROP, drop));
|
||||||
|
drop->tableName = (child->children[0]->token->valueStr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnSpecList *parser_node_convert_column_spec_list(ParserNode *node) {
|
||||||
|
ColumnSpecList *list = new_column_spec_list();
|
||||||
|
for (size_t i = 0; i < node->childrenLength; i++) {
|
||||||
|
ParserNode* specNode = node->children[i];
|
||||||
|
ColumnSpec *spec = new_column_spec();
|
||||||
|
append_column_spec_list(list, spec);
|
||||||
|
spec->identifier = strdup(specNode->token->valueStr);
|
||||||
|
ParserNode *colTypeNode = specNode->children[0];
|
||||||
|
if (colTypeNode->token->type == T_KW_STRING) {
|
||||||
|
spec->type = COLTYPE_STRING;
|
||||||
|
spec->size = (size_t)colTypeNode->children[0]->token->valueInt;
|
||||||
|
} else if (colTypeNode->token->type == T_KW_INT) {
|
||||||
|
spec->type = COLTYPE_INT;
|
||||||
|
}
|
||||||
|
if (specNode->childrenLength == 2) {
|
||||||
|
if (specNode->children[1]->token->type == T_KW_INDEX) {
|
||||||
|
spec->option = COLOPT_INDEX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComparisonGroup *parser_node_convert_comparison_group(ParserNode *node) {
|
||||||
|
ComparisonGroup *group = new_comparision_group();
|
||||||
|
for (size_t i = 0; i < node->childrenLength; i++) {
|
||||||
|
ParserNode *compNode = node->children[i];
|
||||||
|
Comparison *comp = new_comparison();
|
||||||
|
append_comparison_group(group, comp);
|
||||||
|
comp->identifier = strdup(compNode->children[0]->token->valueStr);
|
||||||
|
if (compNode->children[1]->token->type == T_COMP_EQ) {
|
||||||
|
comp->comp = COMP_EQ;
|
||||||
|
} else if (compNode->children[1]->token->type == T_COMP_NEQ) {
|
||||||
|
comp->comp = COMP_NEQ;
|
||||||
|
}
|
||||||
|
comp->value = parser_node_convert_value(compNode->children[2]);
|
||||||
|
}
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignmentList *parser_node_convert_assignment_list(ParserNode *node) {
|
||||||
|
AssignmentList *list = new_assignment_list();
|
||||||
|
for (size_t i = 0; i < node->childrenLength; i++) {
|
||||||
|
ParserNode *assignmentNode = node->children[i];
|
||||||
|
Assignment *assignment = new_assignment();
|
||||||
|
append_assignment_list(list, assignment);
|
||||||
|
assignment->identifier = strdup(assignmentNode->token->valueStr);
|
||||||
|
assignment->value = parser_node_convert_value(assignmentNode->children[0]);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value *parser_node_convert_value(ParserNode *node) {
|
||||||
|
Value *value = new_value();
|
||||||
|
if (node->token->type == T_STRING) {
|
||||||
|
value->type = VALUE_STRING;
|
||||||
|
value->string = strdup(node->token->valueStr);
|
||||||
|
} else if (node->token->type == T_NUMBER) {
|
||||||
|
value->type = VALUE_NUMBER;
|
||||||
|
value->number = node->token->valueInt;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
#define NEXT_TOKEN() {\
|
#define NEXT_TOKEN() {\
|
||||||
token = scanner_next_token(scanner, token);\
|
token = scanner_next_token(scanner, token);\
|
||||||
}
|
}
|
||||||
@@ -286,9 +429,9 @@ ParserNode *parser_parse(Parser *parser, Scanner *scanner) {
|
|||||||
ASCEND_NODE();
|
ASCEND_NODE();
|
||||||
} else if (token->type == T_KW_WHERE) {
|
} else if (token->type == T_KW_WHERE) {
|
||||||
node->phase++;
|
node->phase++;
|
||||||
ParserNode *assignments = new_parser_node(NODE_ASSIGNMENT_LIST, NULL);
|
ParserNode *comparisons = new_parser_node(NODE_COMPARISON_GROUP, NULL);
|
||||||
append_parser_node(node, assignments);
|
append_parser_node(node, comparisons);
|
||||||
node = assignments;
|
node = comparisons;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -407,6 +550,10 @@ ParserNode *parser_parse(Parser *parser, Scanner *scanner) {
|
|||||||
parser_set_error(parser, "Expected number", token);
|
parser_set_error(parser, "Expected number", token);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (token->valueInt < 1) {
|
||||||
|
parser_set_error(parser, "Expected positive number", token);
|
||||||
|
break;
|
||||||
|
}
|
||||||
append_parser_node(columnType, new_parser_node(NODE_COLUMN_TYPE_SPECIFIER, token));
|
append_parser_node(columnType, new_parser_node(NODE_COLUMN_TYPE_SPECIFIER, token));
|
||||||
token = NULL;
|
token = NULL;
|
||||||
EXPECT(T_PAREN_CLOSE);
|
EXPECT(T_PAREN_CLOSE);
|
||||||
|
|||||||
12
src/parser.h
12
src/parser.h
@@ -55,7 +55,7 @@ enum ParserNodeType_t {
|
|||||||
typedef enum ParserNodeType_t ParserNodeType;
|
typedef enum ParserNodeType_t ParserNodeType;
|
||||||
#undef X
|
#undef X
|
||||||
|
|
||||||
char* parser_node_type_to_str(ParserNodeType nodeType);
|
char *parser_node_type_to_str(ParserNodeType nodeType);
|
||||||
|
|
||||||
struct ParserNode_t {
|
struct ParserNode_t {
|
||||||
struct ParserNode_t *parent;
|
struct ParserNode_t *parent;
|
||||||
@@ -73,6 +73,16 @@ void free_parser_node(ParserNode *node);
|
|||||||
|
|
||||||
void append_parser_node(ParserNode *node, ParserNode *child);
|
void append_parser_node(ParserNode *node, ParserNode *child);
|
||||||
|
|
||||||
|
StatementList *parser_node_convert(ParserNode *node);
|
||||||
|
|
||||||
|
ColumnSpecList *parser_node_convert_column_spec_list(ParserNode *node);
|
||||||
|
|
||||||
|
ComparisonGroup *parser_node_convert_comparison_group(ParserNode *node);
|
||||||
|
|
||||||
|
AssignmentList *parser_node_convert_assignment_list(ParserNode *node);
|
||||||
|
|
||||||
|
Value *parser_node_convert_value(ParserNode *node);
|
||||||
|
|
||||||
struct Parser_t {
|
struct Parser_t {
|
||||||
ParseStatus status;
|
ParseStatus status;
|
||||||
char *errMsg;
|
char *errMsg;
|
||||||
|
|||||||
@@ -203,11 +203,11 @@ ScannerToken *scanner_next_token(Scanner *scanner, ScannerToken *token) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Numbers
|
//Numbers
|
||||||
if (isdigit(scanner_peek_char(scanner))) {
|
if (isdigit(scanner_peek_char(scanner)) || scanner_peek_char(scanner) == '-') {
|
||||||
char intInput[32] = {0};
|
char intInput[32] = {0};
|
||||||
size_t intIndex = 0;
|
size_t intIndex = 0;
|
||||||
while (scanner_peek_char(scanner) != 0
|
while (scanner_peek_char(scanner) != 0
|
||||||
&& isdigit(scanner_peek_char(scanner))
|
&& (isdigit(scanner_peek_char(scanner)) || scanner_peek_char(scanner) == '-')
|
||||||
&& intIndex + 1 < 32) {
|
&& intIndex + 1 < 32) {
|
||||||
intInput[intIndex++] = scanner_next_char(scanner);
|
intInput[intIndex++] = scanner_next_char(scanner);
|
||||||
}
|
}
|
||||||
@@ -219,7 +219,7 @@ ScannerToken *scanner_next_token(Scanner *scanner, ScannerToken *token) {
|
|||||||
}
|
}
|
||||||
token->type = T_NUMBER;
|
token->type = T_NUMBER;
|
||||||
//convert number
|
//convert number
|
||||||
token->valueInt = (uint64_t) strtol(intInput, NULL, 10);
|
token->valueInt = (int64_t) strtol(intInput, NULL, 10);
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ char* scanner_token_type_to_str(ScannerTokenType tokenType);
|
|||||||
struct ScannerToken_t {
|
struct ScannerToken_t {
|
||||||
ScannerTokenType type;
|
ScannerTokenType type;
|
||||||
char *valueStr;
|
char *valueStr;
|
||||||
uint64_t valueInt;
|
int64_t valueInt;
|
||||||
size_t lineNo;
|
size_t lineNo;
|
||||||
size_t linePos;
|
size_t linePos;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user