purescript
[tastes.git] / goyacc / parser.go.y
blob27864d3d3aeecfaba14aa12c02e60a5f850dc665
1 %{
2 package main
3 import (
4 "text/scanner"
5 "strconv"
6 "strings"
7 "fmt"
9 type Expression interface{}
10 type ParenExpr struct {
11 SubExpr Expression
13 type Token struct {
14 token int
15 literal string
17 type NumExpr struct {
18 literal string
20 type BinOpExpr struct {
21 left NumExpr
22 operator string
23 right NumExpr
25 type AssocExpr struct {
26 left Expression
27 operator string
28 right Expression
30 type UnaryExpr struct {
31 operator string
32 right Expression
35 %union{
36 token Token
37 expr Expression
39 %type<expr> program
40 %type<expr> expr
41 %token<token> NUMBER NOT AND OR IS
42 %left IS
43 %left '<' GE '>' LE
44 %left AND
45 %left OR
46 %right NOT
48 program
49 : expr
51 $$ = $1
52 yylex.(*Lexer).result = $$
54 expr
55 : NUMBER
57 $$ = NumExpr{literal: $1.literal}
59 | NOT expr
61 $$ = UnaryExpr{operator: "!", right: $2}
63 | expr AND expr
65 $$ = AssocExpr{left: $1, operator: "&&", right: $3}
67 | '(' expr ')'
69 $$ = ParenExpr{SubExpr: $2}
71 | expr OR expr
73 $$ = AssocExpr{left: $1, operator: "||", right: $3}
75 | NUMBER '<' NUMBER
77 $$ = BinOpExpr{left: NumExpr{literal: $1.literal}, operator: "<", right: NumExpr{literal: $3.literal}}
79 | NUMBER '>' NUMBER
81 $$ = BinOpExpr{left: NumExpr{literal: $1.literal}, operator: ">", right: NumExpr{literal: $3.literal}}
83 | NUMBER IS NUMBER
85 $$ = BinOpExpr{left: NumExpr{literal: $1.literal}, operator: "=", right: NumExpr{literal: $3.literal}}
87 | NUMBER GE NUMBER
89 $$ = BinOpExpr{left: NumExpr{literal: $1.literal}, operator: ">=", right: NumExpr{literal: $3.literal}}
91 | NUMBER LE NUMBER
93 $$ = BinOpExpr{left: NumExpr{literal: $1.literal}, operator: "<=", right: NumExpr{literal: $3.literal}}
96 type Lexer struct {
97 scanner.Scanner
98 Vars map[string]interface{}
99 result Expression
101 func (l *Lexer) Lex(lval *yySymType) int {
102 token := l.Scan()
103 lit := l.TokenText()
104 tok := int(token)
105 switch tok {
106 case scanner.Int:
107 tok = NUMBER
108 default:
109 switch lit {
110 case "IS":
111 tok = IS
112 case "NOT":
113 tok = NOT
114 case "AND":
115 tok = AND
116 case "OR":
117 tok = OR
118 case "<=":
119 tok = LE
120 case ">=":
121 tok = GE
122 default:
123 if v, ok := l.Vars[lit]; ok {
124 switch v.(type) {
125 case int:
126 tok = NUMBER
127 lit = strconv.Itoa(v.(int))
132 lval.token = Token{token: tok, literal: lit}
133 return tok
135 func (l *Lexer) Error(e string) {
136 panic(e)
138 func EvalN(e Expression) int {
139 switch t := e.(type) {
140 case NumExpr:
141 num, _ := strconv.Atoi(t.literal)
142 return num
144 return 0
146 func Eval(e Expression) bool {
147 switch t := e.(type) {
148 case ParenExpr:
149 fmt.Println("Sub")
150 return Eval(t.SubExpr)
151 case UnaryExpr:
152 fmt.Println(t.operator)
153 right := Eval(t.right)
154 switch t.operator {
155 case "!":
156 return ! right
158 case AssocExpr:
159 fmt.Println("Assoc")
160 left := Eval(t.left)
161 right := Eval(t.right)
162 switch t.operator {
163 case "||":
164 return left || right
165 case "&&":
166 return left && right
168 case BinOpExpr:
169 fmt.Println("BinOp")
170 left := EvalN(t.left)
171 right := EvalN(t.right)
172 switch t.operator {
173 case ">":
174 return left > right
175 case "<":
176 return left < right
177 case "=":
178 return left == right
180 default:
181 fmt.Printf("unsuported expr[%+v]", t)
183 return false
185 func Parse(exp string, vars map[string]interface{}) bool {
186 l := new(Lexer)
187 l.Vars = vars
188 l.Init(strings.NewReader(exp))
189 yyParse(l)
190 return Eval(l.result)
193 func main() {
194 vars := map[string]interface{}{
195 "A": 1,
196 "B": 1,
198 f := Parse("NOT (A IS B)", vars)
199 fmt.Printf("%t\n", f) // false
201 t := Parse("A IS B", vars)
202 fmt.Printf("%t\n", t) // true