forked from myrp556/yacc_sql
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
root
committed
Mar 9, 2021
1 parent
94c9f6a
commit 25021be
Showing
8 changed files
with
1,715 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/myrp556/yacc_parse/parser" | ||
) | ||
|
||
func main() { | ||
lex := parser.NewLex("SELECT * FROM table1, table2 WHERE a>1 and (b<2 OR c=1)") | ||
statements := parser.Parse(lex) | ||
parser.Travel(statements) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package parser | ||
|
||
import ( | ||
"log" | ||
"strconv" | ||
) | ||
|
||
type lex struct { | ||
input string | ||
scanner *Scanner | ||
Query Query | ||
} | ||
|
||
func NewLex(input string) *lex { | ||
return &lex{ | ||
input: input, | ||
scanner: newScanner(input), | ||
} | ||
} | ||
|
||
func (l *lex) Lex(lval *yySymType) int { | ||
typ, str := l.scanner.nextToken() | ||
log.Println(typ, str) | ||
|
||
switch typ { | ||
case 0: | ||
return 0 | ||
case INTEGER: | ||
lval.int64, _ = strconv.ParseInt(str, 10, 64) | ||
case FLOAT: | ||
lval.float64, _ = strconv.ParseFloat(str, 64) | ||
//case STRING, NAME: | ||
// lex.str = str | ||
case EQ, NEQ, LT, LTE, GT, GTE, AND, OR, ADD, DEC: | ||
lval.int = typ | ||
} | ||
lval.str = str | ||
|
||
return typ | ||
} | ||
|
||
func (l *lex) Error(err string) { | ||
log.Fatal(err) | ||
} | ||
|
||
func Parse(l *lex) Statements { | ||
yyParse(l) | ||
return l.Query.Statements | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package parser | ||
|
||
import ( | ||
"strconv" | ||
"fmt" | ||
) | ||
|
||
type ExprNodeType int | ||
|
||
const ( | ||
Unknown ExprNodeType = 0 | ||
BinaryNode ExprNodeType = 1 | ||
FieldNode ExprNodeType = 2 | ||
IntegerNode ExprNodeType = 3 | ||
FloatNode ExprNodeType = 4 | ||
StringNode ExprNodeType = 5 | ||
) | ||
|
||
type Statements []Statement | ||
type Fields []*Field | ||
type Sources []*Source | ||
|
||
type Field struct { | ||
Name string | ||
} | ||
|
||
type Source struct { | ||
Name string | ||
} | ||
|
||
type Statement interface { | ||
stmt() | ||
travel() | ||
} | ||
|
||
type Query struct { | ||
Statements Statements | ||
} | ||
|
||
type ExprNode struct { | ||
Type ExprNodeType | ||
Left *ExprNode | ||
Right *ExprNode | ||
|
||
FloVal float64 | ||
IntVal int64 | ||
StrVal string | ||
Name string | ||
Op int | ||
} | ||
|
||
func Travel(stmts Statements) { | ||
for _, stmt := range stmts { | ||
stmt.travel() | ||
} | ||
} | ||
|
||
func (fields Fields) str() string { | ||
str := "" | ||
for i, field := range fields { | ||
if i > 0 { | ||
str = str + ", " | ||
} | ||
|
||
str = str + field.str() | ||
} | ||
return str | ||
} | ||
|
||
func (field *Field) str() string { | ||
return field.Name | ||
} | ||
|
||
func (sources Sources) str() string { | ||
str := "" | ||
for i, source := range sources { | ||
if i > 0 { | ||
str = str + ", " | ||
} | ||
str = str + source.str() | ||
} | ||
return str | ||
} | ||
|
||
func (source *Source) str() string { | ||
return source.Name | ||
} | ||
|
||
func (node *ExprNode) str() string { | ||
switch node.Type { | ||
case FieldNode: | ||
return node.Name | ||
case StringNode: | ||
return node.StrVal | ||
case IntegerNode: | ||
return strconv.FormatInt(node.IntVal, 10) | ||
case FloatNode: | ||
return strconv.FormatFloat(node.FloVal, 'f', -1, 64) | ||
case BinaryNode: | ||
return fmt.Sprintf("(%s %s %s)", node.Left.str(), opToStr(node.Op), node.Right.str()) | ||
} | ||
|
||
return "?" | ||
} | ||
|
||
func opToStr(op int) string { | ||
switch op { | ||
case EQ: | ||
return "=" | ||
case NEQ: | ||
return "<>" | ||
case GT: | ||
return ">" | ||
case GTE: | ||
return ">=" | ||
case LT: | ||
return "<" | ||
case LTE: | ||
return "<=" | ||
case AND: | ||
return "AND" | ||
case OR: | ||
return "OR" | ||
case ADD: | ||
return "+" | ||
case DEC: | ||
return "-" | ||
case STAR: | ||
return "*" | ||
case COMMA: | ||
return "," | ||
case SEMICOLON: | ||
return ";" | ||
} | ||
return "" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
%{ | ||
package parser | ||
|
||
import ( | ||
//"fmt" | ||
) | ||
|
||
func addStatement(yylex yyLexer, stmt Statement) { | ||
yylex.(*lex).Query.Statements = append(yylex.(*lex).Query.Statements, stmt) | ||
} | ||
|
||
%} | ||
|
||
%union { | ||
stmt Statement | ||
stmts Statements | ||
selectStmt *SelectStatement | ||
|
||
str string | ||
query Query | ||
field *Field | ||
fields Fields | ||
source *Source | ||
sources Sources | ||
|
||
int int | ||
int64 int64 | ||
float64 float64 | ||
bool bool | ||
|
||
expr *ExprNode | ||
} | ||
|
||
%token <str> SELECT FROM WHERE AS GROUP BY ORDER LIMIT CREATE | ||
%token <str> UPDATE INSERT INTO DELETE | ||
%token <str> STAR | ||
%token <int> EQ NEQ LT LTE GT GTE | ||
%token <int> LEFTC, RIGHTC | ||
%token <str> NAME | ||
%token <int64> INTEGER | ||
%token <float64> FLOAT | ||
%token <str> STRING | ||
%token <str> COMMA SEMICOLON | ||
|
||
%left <int> OR | ||
%left <int> AND | ||
%left <int> ADD DEC | ||
%left <int> TIME DIV MOD | ||
|
||
%type <stmts> QUERIES | ||
%type <stmt> STATEMENT | ||
%type <selectStmt> SELECT_STATEMENT | ||
%type <field> FIELD | ||
%type <fields> FIELDS | ||
%type <source> SOURCE | ||
%type <sources> SOURCES | ||
%type <expr> CONDITION WHERE_CONDITION | ||
%type <expr> CONDITION_VAR | ||
%type <int> OPERATOR | ||
|
||
//%start main | ||
|
||
%% | ||
|
||
QUERIES: | ||
STATEMENT { | ||
addStatement(yylex, $1) | ||
}| | ||
STATEMENT SEMICOLON { | ||
addStatement(yylex, $1) | ||
}| | ||
STATEMENT SEMICOLON QUERIES { | ||
addStatement(yylex, $1) | ||
} | ||
|
||
STATEMENT: | ||
SELECT_STATEMENT { | ||
$$ = $1 | ||
} | ||
|
||
SELECT_STATEMENT: | ||
SELECT FIELDS FROM SOURCES WHERE_CONDITION { | ||
sele := &SelectStatement{ | ||
Fields: $2, | ||
Sources: $4, | ||
WhereCondition: $5, | ||
} | ||
|
||
$$ = sele | ||
} | ||
|
||
FIELDS: | ||
FIELD { | ||
$$ = []*Field{$1} | ||
}| | ||
FIELD COMMA FIELDS { | ||
$$ = append($3, $1) | ||
} | ||
|
||
FIELD: | ||
NAME { | ||
$$ = &Field{Name: $1} | ||
}| | ||
STAR { | ||
$$ = &Field{Name: $1} | ||
} | ||
|
||
SOURCES: | ||
SOURCE { | ||
$$ = []*Source{$1} | ||
}| | ||
SOURCE COMMA SOURCES { | ||
$$ = append($3, $1) | ||
} | ||
|
||
SOURCE: | ||
NAME { | ||
$$ = &Source{Name: $1} | ||
} | ||
|
||
WHERE_CONDITION: | ||
WHERE CONDITION { | ||
$$ = $2 | ||
}| | ||
{ | ||
$$ = nil | ||
} | ||
|
||
CONDITION: | ||
LEFTC CONDITION RIGHTC { | ||
$$ = $2 | ||
}| | ||
CONDITION_VAR OPERATOR CONDITION_VAR { | ||
$$ = &ExprNode{Type: BinaryNode, Left: $1, Op: $2, Right: $3} | ||
}| | ||
CONDITION AND CONDITION { | ||
$$ = &ExprNode{Type: BinaryNode, Left: $1, Op: $2, Right: $3} | ||
}| | ||
CONDITION OR CONDITION { | ||
$$ = &ExprNode{Type: BinaryNode, Left: $1, Op: $2, Right: $3} | ||
} | ||
|
||
OPERATOR: | ||
EQ { | ||
$$ = $1 | ||
}| | ||
NEQ { | ||
$$ = $1 | ||
}| | ||
LT { | ||
$$ = $1 | ||
}| | ||
LTE { | ||
$$ = $1 | ||
}| | ||
GT { | ||
$$ = $1 | ||
}| | ||
GTE { | ||
$$ = $1 | ||
} | ||
|
||
CONDITION_VAR: | ||
NAME { | ||
$$ = &ExprNode{Type: FieldNode, Name: $1} | ||
}| | ||
STRING { | ||
$$ = &ExprNode{Type: StringNode, StrVal: $1} | ||
}| | ||
INTEGER { | ||
$$ = &ExprNode{Type: IntegerNode, IntVal: $1} | ||
}| | ||
FLOAT { | ||
$$ = &ExprNode{Type: FloatNode, FloVal: $1} | ||
} | ||
|
||
%% |
Oops, something went wrong.