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.

247 lines
6.4 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. c.V1 = params[0]
  94. c.V2 = params[1]
  95. return c, nil
  96. }
  97. // if c.Literal == "out" {
  98. // // TODO
  99. // return c, nil
  100. // }
  101. _, lit = p.scanIgnoreWhitespace() // skip =
  102. c.Literal += lit
  103. // v1
  104. _, lit = p.scanIgnoreWhitespace()
  105. c.V1 = lit
  106. c.Literal += lit
  107. // operator
  108. _, lit = p.scanIgnoreWhitespace()
  109. c.Op = lit
  110. c.Literal += lit
  111. // v2
  112. _, lit = p.scanIgnoreWhitespace()
  113. c.V2 = lit
  114. c.Literal += lit
  115. if tok == EOF {
  116. return nil, errors.New("eof in parseline")
  117. }
  118. return c, nil
  119. }
  120. func existInArray(arr []string, elem string) bool {
  121. for _, v := range arr {
  122. if v == elem {
  123. return true
  124. }
  125. }
  126. return false
  127. }
  128. func addToArrayIfNotExist(arr []string, elem string) []string {
  129. for _, v := range arr {
  130. if v == elem {
  131. return arr
  132. }
  133. }
  134. arr = append(arr, elem)
  135. return arr
  136. }
  137. // Parse parses the lines and returns the compiled Circuit
  138. func (p *Parser) Parse() (*Circuit, error) {
  139. circuit := &Circuit{}
  140. circuit.Signals = append(circuit.Signals, "one")
  141. nInputs := 0
  142. for {
  143. constraint, err := p.parseLine()
  144. if err != nil {
  145. break
  146. }
  147. if constraint.Literal == "func" {
  148. // one constraint for each input
  149. for _, in := range constraint.PublicInputs {
  150. newConstr := &Constraint{
  151. Op: "in",
  152. Out: in,
  153. }
  154. circuit.Constraints = append(circuit.Constraints, *newConstr)
  155. nInputs++
  156. circuit.Signals = addToArrayIfNotExist(circuit.Signals, in)
  157. circuit.NPublic++
  158. }
  159. for _, in := range constraint.PrivateInputs {
  160. newConstr := &Constraint{
  161. Op: "in",
  162. Out: in,
  163. }
  164. circuit.Constraints = append(circuit.Constraints, *newConstr)
  165. nInputs++
  166. circuit.Signals = addToArrayIfNotExist(circuit.Signals, in)
  167. }
  168. circuit.PublicInputs = constraint.PublicInputs
  169. circuit.PrivateInputs = constraint.PrivateInputs
  170. continue
  171. }
  172. if constraint.Literal == "equals" {
  173. constr1 := &Constraint{
  174. Op: "*",
  175. V1: constraint.V2,
  176. V2: "1",
  177. Out: constraint.V1,
  178. Literal: "equals(" + constraint.V1 + ", " + constraint.V2 + "): " + constraint.V1 + "==" + constraint.V2 + " * 1",
  179. }
  180. circuit.Constraints = append(circuit.Constraints, *constr1)
  181. constr2 := &Constraint{
  182. Op: "*",
  183. V1: constraint.V1,
  184. V2: "1",
  185. Out: constraint.V2,
  186. Literal: "equals(" + constraint.V1 + ", " + constraint.V2 + "): " + constraint.V2 + "==" + constraint.V1 + " * 1",
  187. }
  188. circuit.Constraints = append(circuit.Constraints, *constr2)
  189. continue
  190. }
  191. circuit.Constraints = append(circuit.Constraints, *constraint)
  192. isVal, _ := isValue(constraint.V1)
  193. if !isVal {
  194. circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.V1)
  195. }
  196. isVal, _ = isValue(constraint.V2)
  197. if !isVal {
  198. circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.V2)
  199. }
  200. // if constraint.Out == "out" {
  201. // if Out is "out", put it after first value (one) and before the inputs
  202. // if constraint.Out == circuit.PublicInputs[0] {
  203. // if existInArray(circuit.PublicInputs, constraint.Out) {
  204. // // if Out is a public signal, put it after first value (one) and before the private inputs
  205. // if !existInArray(circuit.Signals, constraint.Out) {
  206. // // if already don't exists in signal array
  207. // signalsCopy := copyArray(circuit.Signals)
  208. // var auxSignals []string
  209. // auxSignals = append(auxSignals, signalsCopy[0])
  210. // auxSignals = append(auxSignals, constraint.Out)
  211. // auxSignals = append(auxSignals, signalsCopy[1:]...)
  212. // circuit.Signals = auxSignals
  213. // // circuit.PublicInputs = append(circuit.PublicInputs, constraint.Out)
  214. // circuit.NPublic++
  215. // }
  216. // } else {
  217. circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.Out)
  218. // }
  219. }
  220. circuit.NVars = len(circuit.Signals)
  221. circuit.NSignals = len(circuit.Signals)
  222. return circuit, nil
  223. }
  224. func copyArray(in []string) []string { // tmp
  225. var out []string
  226. for _, e := range in {
  227. out = append(out, e)
  228. }
  229. return out
  230. }