You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
6.5 KiB

  1. package circuitcompiler
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. "os"
  7. "regexp"
  8. "strings"
  9. )
  10. // Parser data structure holds the Scanner and the Parsing functions
  11. type Parser struct {
  12. s *Scanner
  13. buf struct {
  14. tok Token // last read token
  15. lit string // last read literal
  16. n int // buffer size (max=1)
  17. }
  18. }
  19. // NewParser creates a new parser from a io.Reader
  20. func NewParser(r io.Reader) *Parser {
  21. return &Parser{s: NewScanner(r)}
  22. }
  23. func (p *Parser) scan() (tok Token, lit string) {
  24. // if there is a token in the buffer return it
  25. if p.buf.n != 0 {
  26. p.buf.n = 0
  27. return p.buf.tok, p.buf.lit
  28. }
  29. tok, lit = p.s.scan()
  30. p.buf.tok, p.buf.lit = tok, lit
  31. return
  32. }
  33. func (p *Parser) unscan() {
  34. p.buf.n = 1
  35. }
  36. func (p *Parser) scanIgnoreWhitespace() (tok Token, lit string) {
  37. tok, lit = p.scan()
  38. if tok == WS {
  39. tok, lit = p.scan()
  40. }
  41. return
  42. }
  43. // parseLine parses the current line
  44. func (p *Parser) parseLine() (*Constraint, error) {
  45. /*
  46. in this version,
  47. line will be for example s3 = s1 * s4
  48. this is:
  49. val eq val op val
  50. */
  51. c := &Constraint{}
  52. tok, lit := p.scanIgnoreWhitespace()
  53. c.Out = lit
  54. c.Literal += lit
  55. if c.Literal == "func" {
  56. // format: `func name(in):`
  57. line, err := p.s.r.ReadString(':')
  58. if err != nil {
  59. return c, err
  60. }
  61. // read string inside ( )
  62. rgx := regexp.MustCompile(`\((.*?)\)`)
  63. insideParenthesis := rgx.FindStringSubmatch(line)
  64. varsString := strings.Replace(insideParenthesis[1], " ", "", -1)
  65. allInputs := strings.Split(varsString, ",")
  66. // from allInputs, get the private and the public separated
  67. for _, in := range allInputs {
  68. if strings.Contains(in, "private") {
  69. input := strings.Replace(in, "private", "", -1)
  70. c.PrivateInputs = append(c.PrivateInputs, input)
  71. } else if strings.Contains(in, "public") {
  72. input := strings.Replace(in, "public", "", -1)
  73. c.PublicInputs = append(c.PublicInputs, input)
  74. } else {
  75. // TODO give more info about the circuit code error
  76. fmt.Println("error on declaration of public and private inputs")
  77. os.Exit(0)
  78. }
  79. }
  80. return c, nil
  81. }
  82. if c.Literal == "equals" {
  83. // format: `equals(a, b)`
  84. line, err := p.s.r.ReadString(')')
  85. if err != nil {
  86. return c, err
  87. }
  88. // read string inside ( )
  89. rgx := regexp.MustCompile(`\((.*?)\)`)
  90. insideParenthesis := rgx.FindStringSubmatch(line)
  91. varsString := strings.Replace(insideParenthesis[1], " ", "", -1)
  92. params := strings.Split(varsString, ",")
  93. fmt.Println("params", params)
  94. // TODO
  95. c.V1 = params[0]
  96. c.V2 = params[1]
  97. return c, nil
  98. }
  99. // if c.Literal == "out" {
  100. // // TODO
  101. // return c, nil
  102. // }
  103. _, lit = p.scanIgnoreWhitespace() // skip =
  104. c.Literal += lit
  105. // v1
  106. _, lit = p.scanIgnoreWhitespace()
  107. c.V1 = lit
  108. c.Literal += lit
  109. // operator
  110. _, lit = p.scanIgnoreWhitespace()
  111. c.Op = lit
  112. c.Literal += lit
  113. // v2
  114. _, lit = p.scanIgnoreWhitespace()
  115. c.V2 = lit
  116. c.Literal += lit
  117. if tok == EOF {
  118. return nil, errors.New("eof in parseline")
  119. }
  120. return c, nil
  121. }
  122. func existInArray(arr []string, elem string) bool {
  123. for _, v := range arr {
  124. if v == elem {
  125. return true
  126. }
  127. }
  128. return false
  129. }
  130. func addToArrayIfNotExist(arr []string, elem string) []string {
  131. for _, v := range arr {
  132. if v == elem {
  133. return arr
  134. }
  135. }
  136. arr = append(arr, elem)
  137. return arr
  138. }
  139. // Parse parses the lines and returns the compiled Circuit
  140. func (p *Parser) Parse() (*Circuit, error) {
  141. circuit := &Circuit{}
  142. circuit.Signals = append(circuit.Signals, "one")
  143. nInputs := 0
  144. for {
  145. constraint, err := p.parseLine()
  146. if err != nil {
  147. break
  148. }
  149. fmt.Println(constraint)
  150. if constraint.Literal == "func" {
  151. // one constraint for each input
  152. for _, in := range constraint.PublicInputs {
  153. newConstr := &Constraint{
  154. Op: "in",
  155. Out: in,
  156. }
  157. circuit.Constraints = append(circuit.Constraints, *newConstr)
  158. nInputs++
  159. circuit.Signals = addToArrayIfNotExist(circuit.Signals, in)
  160. circuit.NPublic++
  161. }
  162. for _, in := range constraint.PrivateInputs {
  163. newConstr := &Constraint{
  164. Op: "in",
  165. Out: in,
  166. }
  167. circuit.Constraints = append(circuit.Constraints, *newConstr)
  168. nInputs++
  169. circuit.Signals = addToArrayIfNotExist(circuit.Signals, in)
  170. }
  171. circuit.PublicInputs = constraint.PublicInputs
  172. circuit.PrivateInputs = constraint.PrivateInputs
  173. continue
  174. }
  175. if constraint.Literal == "equals" {
  176. // TODO
  177. fmt.Println("circuit.Signals", circuit.Signals)
  178. constr1 := &Constraint{
  179. Op: "*",
  180. V1: constraint.V2,
  181. V2: "1",
  182. Out: constraint.V1,
  183. Literal: "equals(" + constraint.V1 + ", " + constraint.V2 + "): " + constraint.V1 + "==" + constraint.V2 + " * 1",
  184. }
  185. circuit.Constraints = append(circuit.Constraints, *constr1)
  186. constr2 := &Constraint{
  187. Op: "*",
  188. V1: constraint.V1,
  189. V2: "1",
  190. Out: constraint.V2,
  191. Literal: "equals(" + constraint.V1 + ", " + constraint.V2 + "): " + constraint.V2 + "==" + constraint.V1 + " * 1",
  192. }
  193. circuit.Constraints = append(circuit.Constraints, *constr2)
  194. continue
  195. }
  196. circuit.Constraints = append(circuit.Constraints, *constraint)
  197. isVal, _ := isValue(constraint.V1)
  198. if !isVal {
  199. circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.V1)
  200. }
  201. isVal, _ = isValue(constraint.V2)
  202. if !isVal {
  203. circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.V2)
  204. }
  205. // if constraint.Out == "out" {
  206. // if Out is "out", put it after first value (one) and before the inputs
  207. // if constraint.Out == circuit.PublicInputs[0] {
  208. // if existInArray(circuit.PublicInputs, constraint.Out) {
  209. // // if Out is a public signal, put it after first value (one) and before the private inputs
  210. // if !existInArray(circuit.Signals, constraint.Out) {
  211. // // if already don't exists in signal array
  212. // signalsCopy := copyArray(circuit.Signals)
  213. // var auxSignals []string
  214. // auxSignals = append(auxSignals, signalsCopy[0])
  215. // auxSignals = append(auxSignals, constraint.Out)
  216. // auxSignals = append(auxSignals, signalsCopy[1:]...)
  217. // circuit.Signals = auxSignals
  218. // // circuit.PublicInputs = append(circuit.PublicInputs, constraint.Out)
  219. // circuit.NPublic++
  220. // }
  221. // } else {
  222. circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.Out)
  223. // }
  224. }
  225. circuit.NVars = len(circuit.Signals)
  226. circuit.NSignals = len(circuit.Signals)
  227. return circuit, nil
  228. }
  229. func copyArray(in []string) []string { // tmp
  230. var out []string
  231. for _, e := range in {
  232. out = append(out, e)
  233. }
  234. return out
  235. }