Skip to content

Commit

Permalink
add code
Browse files Browse the repository at this point in the history
  • Loading branch information
root committed Mar 9, 2021
1 parent 94c9f6a commit 25021be
Show file tree
Hide file tree
Showing 8 changed files with 1,715 additions and 0 deletions.
11 changes: 11 additions & 0 deletions main.go
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)
}
49 changes: 49 additions & 0 deletions parser/lex.go
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
}
136 changes: 136 additions & 0 deletions parser/node.go
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 ""
}
177 changes: 177 additions & 0 deletions parser/parse.y
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}
}

%%
Loading

0 comments on commit 25021be

Please sign in to comment.