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.

236 lines
5.7 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. 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. fmt.Println(constraint)
  148. if constraint.Literal == "func" {
  149. // one constraint for each input
  150. for _, in := range constraint.PrivateInputs {
  151. newConstr := &Constraint{
  152. Op: "in",
  153. Out: in,
  154. }
  155. circuit.Constraints = append(circuit.Constraints, *newConstr)
  156. nInputs++
  157. }
  158. for _, in := range constraint.PublicInputs {
  159. newConstr := &Constraint{
  160. Op: "in",
  161. Out: in,
  162. }
  163. circuit.Constraints = append(circuit.Constraints, *newConstr)
  164. nInputs++
  165. }
  166. circuit.PublicInputs = constraint.PublicInputs
  167. circuit.PrivateInputs = constraint.PrivateInputs
  168. continue
  169. }
  170. if constraint.Literal == "equals" {
  171. // TODO
  172. fmt.Println("circuit.Signals", circuit.Signals)
  173. continue
  174. }
  175. circuit.Constraints = append(circuit.Constraints, *constraint)
  176. isVal, _ := isValue(constraint.V1)
  177. if !isVal {
  178. circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.V1)
  179. }
  180. isVal, _ = isValue(constraint.V2)
  181. if !isVal {
  182. circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.V2)
  183. }
  184. // fmt.Println("---")
  185. // fmt.Println(circuit.PublicInputs[0])
  186. // fmt.Println(constraint.Out)
  187. // fmt.Println(constraint.Out == circuit.PublicInputs[0])
  188. // fmt.Println("---")
  189. // if constraint.Out == "out" {
  190. // if Out is "out", put it after first value (one) and before the inputs
  191. // if constraint.Out == circuit.PublicInputs[0] {
  192. if existInArray(circuit.PublicInputs, constraint.Out) {
  193. // if Out is a public signal, put it after first value (one) and before the private inputs
  194. if !existInArray(circuit.Signals, constraint.Out) {
  195. // if already don't exists in signal array
  196. signalsCopy := copyArray(circuit.Signals)
  197. var auxSignals []string
  198. auxSignals = append(auxSignals, signalsCopy[0])
  199. auxSignals = append(auxSignals, constraint.Out)
  200. auxSignals = append(auxSignals, signalsCopy[1:]...)
  201. circuit.Signals = auxSignals
  202. // circuit.PublicInputs = append(circuit.PublicInputs, constraint.Out)
  203. circuit.NPublic++
  204. }
  205. } else {
  206. circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.Out)
  207. }
  208. }
  209. circuit.NVars = len(circuit.Signals)
  210. circuit.NSignals = len(circuit.Signals)
  211. return circuit, nil
  212. }
  213. func copyArray(in []string) []string { // tmp
  214. var out []string
  215. for _, e := range in {
  216. out = append(out, e)
  217. }
  218. return out
  219. }