Permalink
Browse files

Add a simple SELECT grammar and test.

  • Loading branch information...
1 parent 857b26b commit d283909751980f9c7dbd75a86bdfcfa67076ef58 @umitanuki committed Jan 21, 2013
Showing with 127 additions and 6 deletions.
  1. +73 −4 src/bigpot/parser/gram.y
  2. +26 −0 src/bigpot/parser/gram_test.go
  3. +11 −2 src/bigpot/parser/scan.l
  4. +17 −0 src/bigpot/parser/scan_test.go
View
@@ -4,16 +4,32 @@ package parser
import (
"fmt"
+ "strings"
)
-type Node struct {
+type Node interface {
}
+type ResTarget struct {
+ name string
+}
+
+type ParseTable struct {
+ name string
+}
+
+type SelectStmt struct {
+ target []*ResTarget
+ from []*ParseTable
+}
+
+var TopList []Node
%}
%union{
- node *Node
+ node Node
+ list []Node
str string
ival int
keyword string
@@ -24,6 +40,7 @@ type Node struct {
%left '-' '+'
%left '*' '/'
+%type <list> statements column_list table_list
%type <node> statement
/*
@@ -44,11 +61,63 @@ type Node struct {
%%
statements: /* empty */
+ {
+ $$ = nil
+ }
+ | statement
+ {
+ $$ = append(make([]Node, 0), $1)
+ TopList = $$
+ }
| statements ';' statement
+ {
+ $$ = append($1, $3)
+ TopList = $$
+ }
;
-statement:
+statement: SELECT column_list FROM table_list
{
- $$ = &Node{}
+ target := make([]*ResTarget, len($2), len($2))
+ for i, elem := range $2 {
+ target[i] = elem.(*ResTarget)
+ }
+ from := make([]*ParseTable, len($4), len($4))
+ for i, elem := range $4 {
+ from[i] = elem.(*ParseTable)
+ }
+ $$ = &SelectStmt{
+ target: target,
+ from: from,
+ }
+ }
+
+column_list: IDENT
+ {
+ n := &ResTarget{name: $1}
+ $$ = append(make([]Node, 0), Node(n))
+ }
+ | column_list ',' IDENT
+ {
+ n := &ResTarget{name: $3}
+ $$ = append($1, Node(n))
+ }
+
+table_list: IDENT
+ {
+ n := &ParseTable{name: $1}
+ $$ = append(make([]Node, 0), Node(n))
+ }
+ | table_list ',' IDENT
+ {
+ n := &ParseTable{name: $3}
+ $$ = append($1, Node(n))
}
%%
+
+func ExParse(query string) Node {
+ reader := strings.NewReader(query)
+ lexer := newLexer(reader)
+ yyParse(lexer)
+ return TopList[0]
+}
@@ -0,0 +1,26 @@
+package parser
+
+import (
+ . "launchpad.net/gocheck"
+ "testing"
+)
+
+// Hook up gocheck into the gotest runner.
+func Test(t *testing.T) {
+ TestingT(t)
+}
+
+type MySuite struct{}
+var _ = Suite(&MySuite{})
+func (s *MySuite) TestYYParse_1(c *C) {
+ query := " select col1, col2 FROM tab1"
+ lexer := strLexer(query)
+ yyParse(lexer)
+ node, ok := TopList[0].(*SelectStmt)
+ if !ok {
+ c.Error("node is not SelectStmt")
+ }
+ c.Check(node.target[0].name, Equals, "col1")
+ c.Check(node.target[1].name, Equals, "col2")
+ c.Check(node.from[0].name, Equals, "tab1")
+}
View
@@ -112,7 +112,14 @@ func (l *lexer) Lex(lval *yySymType) int {
xq
xdolq
)
- c := l.next()
+
+ /* Start with the last characher we scanned. */
+ c := l.current
+
+ if c == 0 {
+ /* But get next if not scanned (e.g. the very first time). */
+ c = l.next()
+ }
xcdepth := 0
%}
@@ -692,6 +699,7 @@ other .
{identifier}
yystr := l.getBuf()
+ l.SET_YYLLOC()
/*
* If this is a keyword, return the token number instead of IDENT
*/
@@ -709,7 +717,8 @@ other .
\0
l.SET_YYLLOC()
- return yyEofCode
+ return 0
+ //return yyEofCode
%%
@@ -47,6 +47,23 @@ func ExampleLex_1() {
// 2
}
+func ExampleLex_2() {
+ lexer := strLexer("select col1, col2 from tab1")
+ lexer.lexPrintExpect(SELECT)
+ lexer.lexPrintExpect(IDENT)
+ lexer.lexPrintExpect(int(','))
+ lexer.lexPrintExpect(IDENT)
+ lexer.lexPrintExpect(FROM)
+ lexer.lexPrintExpect(IDENT)
+ // Output:
+ // select
+ // col1
+ // ,
+ // col2
+ // from
+ // tab1
+}
+
func ExampleLex_consts() {
lexer := strLexer("b'0101' x'ff'")
lexer.lexPrintExpect(BCONST)

0 comments on commit d283909

Please sign in to comment.