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.

171 lines
3.3 KiB

  1. package circuitcompiler
  2. import (
  3. "errors"
  4. "io"
  5. "regexp"
  6. "strings"
  7. )
  8. // Parser data structure holds the Scanner and the Parsing functions
  9. type Parser struct {
  10. s *Scanner
  11. buf struct {
  12. tok Token // last read token
  13. lit string // last read literal
  14. n int // buffer size (max=1)
  15. }
  16. }
  17. // NewParser creates a new parser from a io.Reader
  18. func NewParser(r io.Reader) *Parser {
  19. return &Parser{s: NewScanner(r)}
  20. }
  21. func (p *Parser) scan() (tok Token, lit string) {
  22. // if there is a token in the buffer return it
  23. if p.buf.n != 0 {
  24. p.buf.n = 0
  25. return p.buf.tok, p.buf.lit
  26. }
  27. tok, lit = p.s.scan()
  28. p.buf.tok, p.buf.lit = tok, lit
  29. return
  30. }
  31. func (p *Parser) unscan() {
  32. p.buf.n = 1
  33. }
  34. func (p *Parser) scanIgnoreWhitespace() (tok Token, lit string) {
  35. tok, lit = p.scan()
  36. if tok == WS {
  37. tok, lit = p.scan()
  38. }
  39. return
  40. }
  41. // parseLine parses the current line
  42. func (p *Parser) parseLine() (*Constraint, error) {
  43. /*
  44. in this version,
  45. line will be for example s3 = s1 * s4
  46. this is:
  47. val eq val op val
  48. */
  49. c := &Constraint{}
  50. tok, lit := p.scanIgnoreWhitespace()
  51. switch lit {
  52. case "def":
  53. c.Op = FUNC
  54. // format: `func name(in):`
  55. //todo this is all a bit hacky and unsafe
  56. line, err := p.s.r.ReadString(':')
  57. line = strings.Replace(line, " ", "", -1)
  58. line = strings.Replace(line, ":", "", -1)
  59. //set function name
  60. //c.Literal = strings.Split(line, "(")[0]
  61. c.Out = line
  62. if err != nil {
  63. return c, err
  64. }
  65. // read string inside ( )
  66. rgx := regexp.MustCompile(`\((.*?)\)`)
  67. insideParenthesis := rgx.FindStringSubmatch(line)
  68. varsString := strings.Replace(insideParenthesis[1], " ", "", -1)
  69. c.Inputs = strings.Split(varsString, ",")
  70. return c, nil
  71. case "var":
  72. //var a = 234
  73. //c.Literal += lit
  74. _, lit = p.scanIgnoreWhitespace()
  75. c.Out = lit
  76. //c.Literal += lit
  77. _, lit = p.scanIgnoreWhitespace() // skip =
  78. //c.Literal += lit
  79. // v1
  80. _, lit = p.scanIgnoreWhitespace()
  81. c.V1 = lit
  82. //c.Literal += lit
  83. break
  84. case "#":
  85. return nil, errors.New("comment parseline")
  86. default:
  87. c.Out = lit
  88. //c.Literal += lit
  89. _, lit = p.scanIgnoreWhitespace() // skip =
  90. //c.Literal += lit
  91. // v1
  92. tok, lit = p.scanIgnoreWhitespace()
  93. c.V1 = lit
  94. //c.Literal += lit
  95. // operator
  96. tok, lit = p.scanIgnoreWhitespace()
  97. c.Op = tok
  98. //c.Literal += lit
  99. // v2
  100. _, lit = p.scanIgnoreWhitespace()
  101. c.V2 = lit
  102. //c.Literal += lit
  103. }
  104. if tok == EOF {
  105. return nil, errors.New("eof in parseline")
  106. }
  107. return c, nil
  108. }
  109. func existInArray(arr []string, elem string) bool {
  110. for _, v := range arr {
  111. if v == elem {
  112. return true
  113. }
  114. }
  115. return false
  116. }
  117. func addToArrayIfNotExist(arr []string, elem string) []string {
  118. for _, v := range arr {
  119. if v == elem {
  120. return arr
  121. }
  122. }
  123. arr = append(arr, elem)
  124. return arr
  125. }
  126. // Parse parses the lines and returns the compiled Circuit
  127. func (p *Parser) Parse() (programm *Program, err error) {
  128. programm = NewProgram()
  129. var circuit *Circuit
  130. for {
  131. constraint, err := p.parseLine()
  132. if err != nil {
  133. break
  134. }
  135. if constraint.Op == FUNC {
  136. circuit = programm.addFunction(constraint)
  137. } else {
  138. circuit.addConstraint(constraint)
  139. }
  140. }
  141. //TODO
  142. //circuit.NVars = len(circuit.Signals)
  143. //circuit.NSignals = len(circuit.Signals)
  144. return programm, nil
  145. }
  146. func copyArray(in []string) []string { // tmp
  147. var out []string
  148. for _, e := range in {
  149. out = append(out, e)
  150. }
  151. return out
  152. }