source: branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/src/go-symexpr/parse.go @ 16620

Last change on this file since 16620 was 16620, checked in by hmaislin, 6 months ago

#2929: Reorganized folder structure for make script, removed explicit marshalling, erased go-side logging

File size: 6.8 KB
Line 
1package symexpr
2
3import (
4  "fmt"
5  "math"
6  "strconv"
7  "strings"
8)
9
10func ParseFunc(text string, varNames []string) Expr {
11  expr := parse(text, varNames)
12  return expr
13}
14
15var itemPrec = map[itemType]int{
16  itemAdd:     3,
17  itemNeg:     4,
18  itemMul:     5,
19  itemDiv:     5,
20  itemDiv2:    5,
21  itemKeyword: 6,
22  itemCarrot:  7,
23}
24
25func parse(input string, variables []string) Expr {
26  L := lex("test", input, variables)
27  go L.run()
28
29  // var rules = DefaultRules()
30
31  // fmt.Printf( "Input:     %s\n",input)
32  expr := parseExpr("", L, 0)
33  // fmt.Printf( "Result:    %v\n\n",expr)
34  // simp := expr.Simplify(rules)
35  // fmt.Printf( "Output:    %v\n\n",simp)
36
37  return expr
38}
39
40func parseExpr(prefix string, L *lexer, p int) Expr {
41  // fmt.Printf("%sin-E(%d)\n", prefix, p)
42  e := parsePiece(prefix+"  ", L)
43  // fmt.Printf("%se(%d): %v\n", prefix, p, e)
44  for i := 0; ; i++ {
45    var next item
46    // fmt.Printf("%sLEX: %v\n", prefix, L.nextToken)
47
48    if L.nextToken.typ == itemNil {
49      next = <-L.items
50    } else {
51      next, L.nextToken.typ = L.nextToken, itemNil
52    }
53    // fmt.Printf("%snext(%d-%d): %v\n", prefix, p, i, next)
54    typ := next.typ
55    // fmt.Printf("%sn(%d): %v\n", prefix, p, next)
56    if isBinary(typ) && itemPrec[typ] >= p {
57      // fmt.Printf("%sbin: %v\n", prefix, next)
58      q := itemPrec[typ]
59      e2 := parseExpr(prefix+"  ", L, q)
60      // fmt.Printf("%se2: %v\n", prefix, e2)
61      // fmt.Printf("%snext2(%d-%d): %v\n", prefix, p, i, next2)
62      switch typ {
63      case itemAdd:
64        add := NewAdd()
65        add.Insert(e)
66        add.Insert(e2)
67        e = add
68      case itemMul:
69        mul := NewMul()
70        mul.Insert(e)
71        mul.Insert(e2)
72        e = mul
73      case itemNeg:
74        if e == nil {
75          neg := NewNeg(e2)
76          e = neg
77        } else {
78          add := NewAdd()
79          add.Insert(e)
80          add.Insert(NewNeg(e2))
81          e = add
82        }
83      case itemDiv, itemDiv2:
84        div := NewDiv(e, e2)
85        e = div
86      case itemCarrot:
87        switch e2.ExprType() {
88        case CONSTANTF:
89          pow := NewPowI(e, int(e2.(*ConstantF).F))
90          e = pow
91        default:
92          pow := NewPowE(e, e2)
93          e = pow
94        }
95      }
96      // fmt.Printf("%snew e: %v\n", prefix, e)
97    } else if typ == itemIdentifier && itemPrec[itemMul] >= p {
98      L.nextToken = next
99      e2 := parseExpr(prefix+"  ", L, itemPrec[itemMul])
100      mul := NewMul()
101      mul.Insert(e)
102      mul.Insert(e2)
103      e = mul
104      // fmt.Printf("%sid-e: %v\ne2: %v\n", prefix, e, e2)
105    } else if typ > itemKeyword && itemPrec[itemKeyword] >= p {
106      // fmt.Printf("%skey-e: %v\n", prefix, e)
107      L.nextToken = next
108      e2 := parseExpr(prefix+"  ", L, itemPrec[itemKeyword])
109      mul := NewMul()
110      mul.Insert(e)
111      mul.Insert(e2)
112      e = mul
113      // fmt.Printf("%se: %v\ne2: %v\n", prefix, e, e2)
114    } else if typ == itemLParen || typ == itemLBrack {
115      // consumed '(' or '{'
116      e2 := parseExpr(prefix+"  ", L, 0)
117      // now consume ')','}'
118      var next2 item
119      if L.nextToken.typ == itemNil {
120        next2 = <-L.items
121      } else {
122        next2, L.nextToken.typ = L.nextToken, itemNil
123      }
124      typ2 := next2.typ
125      if (typ == itemLParen && typ2 != itemRParen) || (typ == itemLBrack && typ2 != itemRBrack) {
126        fmt.Printf("error: expected rhs of %v\n", next2)
127      }
128      // fmt.Printf("%s(): %v  %v\n", prefix, e, e2)
129
130      mul := NewMul()
131      mul.Insert(e)
132      mul.Insert(e2)
133      e = mul
134    } else {
135      // fmt.Printf("%selse(%d-%d): %v   %v\n", prefix, p, itemPrec[typ], e, next)
136      L.nextToken = next
137      break
138    }
139  }
140  // fmt.Printf("%sout-E(%d): %v   %v\n", prefix, p, e, L.nextToken)
141  return e
142}
143
144func parsePiece(prefix string, L *lexer) Expr {
145  // fmt.Printf("%sin-P()\n", prefix)
146  var next item
147  if L.nextToken.typ == itemNil {
148    next = <-L.items
149  } else {
150    next, L.nextToken.typ = L.nextToken, itemNil
151  }
152  typ := next.typ
153  var e Expr
154  // fmt.Printf("%spnxt  %v\n", prefix, next)
155
156  // if isUnary(typ) {
157  //  e1 := parseExpr(prefix+"  ", L, 0)
158  //  e = NewNeg(e1)
159  // } else
160  if typ == itemNeg {
161    e1 := parsePiece(prefix+"  ", L)
162    e = NewNeg(e1)
163  } else if typ == itemLParen || typ == itemLBrack {
164    // consumed '(' or '{'
165    e = parseExpr(prefix+"  ", L, 0)
166    // now consume ')','}'
167    var next2 item
168    if L.nextToken.typ == itemNil {
169      next2 = <-L.items
170    } else {
171      next2, L.nextToken.typ = L.nextToken, itemNil
172    }
173    typ2 := next2.typ
174    if (typ == itemLParen && typ2 != itemRParen) || (typ == itemLBrack && typ2 != itemRBrack) {
175      fmt.Printf("error: expected rhs of %v\n", next2)
176    }
177    return e
178  } else if typ == itemIdentifier { // leaf
179    if next.val[0] == 'C' {
180      // coefficient
181      ipos := strings.Index(next.val, "_") + 1
182      index, err := strconv.ParseInt(next.val[ipos:], 0, 64)
183      if err != nil {
184        fmt.Printf("Error (%v) parsing index in '%s'\n", err, next.val)
185      }
186      e = NewConstant(int(index))
187    } else if next.val[0] == 'X' {
188      // variable
189      ipos := strings.Index(next.val, "_") + 1
190      index, err := strconv.ParseInt(next.val[ipos:], 0, 64)
191      if err != nil {
192        fmt.Printf("Error (%v) parsing index in '%s'\n", err, next.val)
193      }
194      return NewVar(int(index))
195    } else {
196      // is it a named variable ?
197      for p, v := range L.vars {
198        if next.val == v {
199          e = NewVar(p)
200          break
201        }
202      }
203      // is it a named constant ?
204      if strings.ToLower(next.val) == "pi" {
205        e = NewConstantF(math.Pi)
206      }
207
208      if e == nil {
209        fmt.Printf("UNIMPLEMENTED IDENTIFIER:  %v\n", next)
210      }
211    }
212  } else if typ == itemNumber {
213    flt, err := strconv.ParseFloat(next.val, 64)
214    if err != nil {
215      fmt.Printf("Error (%v) parsing number in '%s'\n", err, next.val)
216    }
217    e = NewConstantF(flt)
218
219    // } elsi if { // func name...
220  } else if typ > itemKeyword {
221    // is it a named function
222    switch typ {
223    case itemSin:
224      e2 := parseExpr(prefix+"  ", L, itemPrec[itemKeyword])
225      e = NewSin(e2)
226    case itemCos:
227      e2 := parseExpr(prefix+"  ", L, itemPrec[itemKeyword])
228      e = NewCos(e2)
229    case itemTan:
230      e2 := parseExpr(prefix+"  ", L, itemPrec[itemKeyword])
231      e = NewTan(e2)
232    case itemAbs:
233      e2 := parseExpr(prefix+"  ", L, itemPrec[itemKeyword])
234      e = NewAbs(e2)
235    case itemSqrt:
236      e2 := parseExpr(prefix+"  ", L, itemPrec[itemKeyword])
237      e = NewSqrt(e2)
238    case itemExp:
239      // now consume the '^'
240      var next2 item
241      if L.nextToken.typ == itemNil {
242        next2 = <-L.items
243      } else {
244        next2, L.nextToken.typ = L.nextToken, itemNil
245      }
246      typ2 := next2.typ
247      if next.val == "e" && typ2 != itemCarrot {
248        fmt.Printf("error: expected ^ after 'e', got %v & %v\n", next, next2)
249      }
250      e2 := parseExpr(prefix+"  ", L, itemPrec[itemCarrot])
251      e = NewExp(e2)
252    case itemLog:
253      e2 := parseExpr(prefix+"  ", L, itemPrec[itemKeyword])
254      e = NewLog(e2)
255    }
256
257    if e == nil {
258      fmt.Printf("Unimplemented Function:  %v\n", next)
259    }
260
261  } else { // error
262    L.nextToken = next
263    e = nil
264  }
265  // } else if { is it a user defined function
266
267  // fmt.Printf("%sout-P(): %v\n", prefix, e)
268  return e
269}
Note: See TracBrowser for help on using the repository browser.