Guest User

Untitled

a guest
May 27th, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.19 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "bufio"
  6. "os"
  7. "errors"
  8. "unicode"
  9. "strconv"
  10. )
  11.  
  12. type Lexer struct {
  13. Text string
  14. }
  15.  
  16. func (lexer Lexer) GenerateToken() ([]string, error) {
  17. var tokenArray []string
  18.  
  19. for x := 0; x < len(lexer.Text); x++ {
  20. currentChar := string(lexer.Text[x])
  21.  
  22. if(currentChar == "\n" || currentChar == " ") {
  23. //ignore newline and space
  24. continue
  25. } else if(unicode.IsDigit([]rune(currentChar)[0])) {
  26. if(len(tokenArray) == 0) {
  27. tokenArray = append(tokenArray, currentChar)
  28. } else {
  29. if(unicode.IsDigit([]rune(tokenArray[len(tokenArray) - 1])[0])) {
  30. tokenArray[len(tokenArray) - 1] += currentChar
  31. } else {
  32. tokenArray = append(tokenArray, currentChar)
  33. }
  34. }
  35. } else if(currentChar == "(" || currentChar == ")" || currentChar == "+" || currentChar == "-" || currentChar == "/" || currentChar == "*") {
  36. if(currentChar == "+" || currentChar == "-" || currentChar == "/" || currentChar == "*") {
  37. if(len(tokenArray) > 0) {
  38. if(tokenArray[len(tokenArray)-1] == "+" || tokenArray[len(tokenArray)-1] == "-" || tokenArray[len(tokenArray)-1] == "/" || tokenArray[len(tokenArray)-1] == "*") {
  39. return tokenArray, errors.New("Syntax Error")
  40. }
  41. }
  42. }
  43. tokenArray = append(tokenArray, currentChar)
  44. } else {
  45. return tokenArray, errors.New("Syntax Error")
  46. }
  47. }
  48.  
  49. return tokenArray, nil
  50. }
  51.  
  52. type Parser struct {
  53. TokenArray []string
  54. }
  55.  
  56. func (parser *Parser) Parse() error {
  57. precedences := map[string] int{"+": 0, "-": 0, "/": 1, "*": 1} //order of precedences
  58. var operatorStack []string
  59. var outputQueue []string
  60.  
  61. if(len(parser.TokenArray) > 0) {
  62. if(parser.TokenArray[0] == "+" || parser.TokenArray[0] == "-" || parser.TokenArray[0] == "/" || parser.TokenArray[0] == "*") {
  63. //syntax error if the first token is an operator
  64. return errors.New("Syntax error")
  65. }
  66.  
  67. if(parser.TokenArray[len(parser.TokenArray)-1] == "+" || parser.TokenArray[len(parser.TokenArray)-1] == "-" || parser.TokenArray[len(parser.TokenArray)-1] == "/" || parser.TokenArray[len(parser.TokenArray)-1] == "*") {
  68. //syntax error if the last token is an operator
  69. return errors.New("Syntax error")
  70. }
  71.  
  72. //shunting-yard below
  73. //While there are tokens to be read:
  74. for len(parser.TokenArray) > 0 {
  75. //Read a token
  76. currentToken := parser.TokenArray[0]
  77. parser.TokenArray = append(parser.TokenArray[:0], parser.TokenArray[1:]...) //pop the first element
  78.  
  79. if(unicode.IsDigit([]rune(currentToken)[0])) {
  80. //If it's a number add it to queue
  81. outputQueue = append(outputQueue, currentToken)
  82. }
  83.  
  84. if(currentToken == "+" || currentToken == "-" || currentToken == "/" || currentToken == "*") {
  85. //If it's an operator
  86. for true {
  87. if(len(operatorStack) > 0) {
  88. if(precedences[operatorStack[len(operatorStack) - 1]] > precedences[currentToken]) {
  89. /*
  90. While there's an operator on the top of the stack with greater precedence:
  91. Pop operators from the stack onto the output queue
  92. */
  93. outputQueue = append(outputQueue, operatorStack[len(operatorStack) - 1])
  94. operatorStack = operatorStack[:len(operatorStack)-1]
  95. } else {
  96. break
  97. }
  98. } else {
  99. break
  100. }
  101. }
  102. //Push the current operator onto the stack
  103. operatorStack = append(operatorStack, currentToken)
  104. }
  105.  
  106. if(currentToken == "(") {
  107. //If it's a left bracket push it onto the stack
  108. operatorStack = append(operatorStack, currentToken)
  109. }
  110.  
  111. if(currentToken == ")") {
  112. //If it's a right bracket
  113. if(len(operatorStack) > 0) {
  114. for true {
  115. if(operatorStack[len(operatorStack) - 1] != "(") {
  116. /*
  117. While there's not a left bracket at the top of the stack:
  118. Pop operators from the stack onto the output queue.
  119. */
  120. outputQueue = append(outputQueue, operatorStack[len(operatorStack) - 1])
  121. operatorStack = operatorStack[:len(operatorStack)-1]
  122. } else {
  123. //Pop the left bracket from the stack and discard it
  124. operatorStack = operatorStack[:len(operatorStack)-1]
  125. break
  126. }
  127.  
  128. if(len(operatorStack) == 0) {
  129. return errors.New("Syntax error")
  130. }
  131. }
  132. } else {
  133. return errors.New("Syntax error")
  134. }
  135. }
  136. }
  137.  
  138. for len(operatorStack) > 0 {
  139. if(operatorStack[len(operatorStack) - 1] == "(") {
  140. return errors.New("Syntax error")
  141. }
  142. //While there are operators on the stack, pop them to the queue
  143. outputQueue = append(outputQueue, operatorStack[len(operatorStack) - 1])
  144. operatorStack = operatorStack[:len(operatorStack)-1]
  145. }
  146. //now the outputQueue contains the reverse polish notation
  147. //read reverse polish notation below
  148. if(len(outputQueue) > 0) {
  149. var stack []string
  150.  
  151. for len(outputQueue) > 0 {
  152. currentToken := outputQueue[0]
  153. outputQueue = append(outputQueue[:0], outputQueue[1:]...) //pop the first element
  154.  
  155. if(currentToken == "+" || currentToken == "-" || currentToken == "/" || currentToken == "*") {
  156. //get right operand
  157. rightOperand, _ := strconv.Atoi(stack[len(stack)-1])
  158. stack = stack[:len(stack)-1]
  159.  
  160. //get left operand
  161. leftOperand, _ := strconv.Atoi(stack[len(stack)-1])
  162. stack = stack[:len(stack)-1]
  163. var result int
  164. if(currentToken == "+") {
  165. //addition
  166. result = leftOperand + rightOperand
  167. } else if(currentToken == "-") {
  168. //substraction
  169. result = leftOperand - rightOperand
  170. } else if(currentToken == "/") {
  171. //division
  172. result = leftOperand / rightOperand
  173. } else {
  174. //assuming multiplication
  175. result = leftOperand * rightOperand
  176. }
  177.  
  178. stack = append(stack, strconv.Itoa(result))
  179. } else {
  180. stack = append(stack, currentToken)
  181. }
  182. }
  183. //print evaluated result
  184. fmt.Println("> " + stack[0])
  185. }
  186. }
  187.  
  188. return nil
  189. }
  190.  
  191. func main() {
  192. /*
  193. Sample Run
  194. ==========
  195.  
  196. > ((15/(7-(1+1)))*3)-(2+(1+1))
  197. > 5
  198. */
  199. for true {
  200. reader := bufio.NewReader(os.Stdin)
  201. fmt.Print("> ")
  202. text, _ := reader.ReadString('\n')
  203.  
  204. //convert to token
  205. lxr := Lexer{Text: text}
  206. tokenArray, tokenErr := lxr.GenerateToken()
  207.  
  208. if(tokenErr != nil) {
  209. fmt.Println("> " + tokenErr.Error())
  210. } else {
  211. //parse token
  212. parser := Parser{TokenArray: tokenArray}
  213. parseErr := parser.Parse()
  214.  
  215. if(parseErr != nil) {
  216. fmt.Println("> " + parseErr.Error())
  217. }
  218. }
  219.  
  220. }
  221. }
Add Comment
Please, Sign In to add comment