Advertisement
EWTD

6

Sep 18th, 2021
1,127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 4.11 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4.     "bufio"
  5.     "fmt"
  6.     "os"
  7.     "strconv"
  8. )
  9.  
  10. type Tag int
  11.  
  12. const (
  13.     ERROR Tag = 1 << iota
  14.     NUMBER
  15.     VAR
  16.     PLUS
  17.     MINUS
  18.     MUL
  19.     DIV
  20.     LPAREN
  21.     RPAREN
  22.     END
  23. )
  24. var vars = make(map[string]int64)
  25. var varExist = make(map[string]bool)
  26. var var_queue []int64
  27. var missedLexems []Lexem
  28.  
  29. func AskVar(varName string) int64{
  30.     _, ok := varExist[varName]
  31.     if ok{
  32.         return vars[varName]
  33.     }else{
  34.         value := var_queue[0]
  35.         var_queue = var_queue[1:]
  36.         varExist[varName] = true
  37.         vars[varName] = value
  38.         return value
  39.     }
  40. }
  41. type Lexem struct {
  42.     Tag
  43.     Image string
  44. }
  45. func GetLexem(lexems chan Lexem) Lexem{
  46.     var curLexem Lexem
  47.     if len(missedLexems) > 0{
  48.         curLexem = missedLexems[0]
  49.         missedLexems = missedLexems[1:]
  50.     }else{
  51.         var ok bool
  52.         curLexem, ok = <- lexems
  53.         if !ok || (curLexem.Tag & ERROR) != 0{
  54.             fmt.Println("error")
  55.             os.Exit(0)
  56.         }
  57.     }
  58.     return curLexem
  59. }
  60. func ParseExpr(lexems chan Lexem) int64{
  61.     res := ParseT(lexems)
  62.     ParseSubExpr(&res, lexems)
  63.     return res
  64. }
  65. func ParseSubExpr(res *int64, lexems chan Lexem){
  66.     curLexem := GetLexem(lexems)
  67.  
  68.     if curLexem.Tag & PLUS != 0{
  69.         *res += ParseT(lexems)
  70.         ParseSubExpr(res, lexems)
  71.         return
  72.     }else if curLexem.Tag & MINUS != 0{
  73.         *res += -ParseT(lexems)
  74.         ParseSubExpr(res, lexems)
  75.         return
  76.     }
  77.     missedLexems = append(missedLexems,curLexem)
  78. }
  79. /*
  80. <E>  ::= <T> <E’>.
  81. <E’> ::= + <T><E'> | - <T><E'> | .
  82. <T>  ::= <F> <T’>.
  83. <T’> ::= * <F> <T’> | / <F> <T’> | .
  84. <F>  ::= <number> | <var> | ( <E> ) | - <F>.
  85. */
  86. func ParseT(lexems chan Lexem) int64{
  87.     res := ParseF(lexems)
  88.     ParseSubT(&res, lexems)
  89.     return res
  90. }
  91. func ParseSubT(res *int64, lexems chan Lexem){
  92.     curLexem := GetLexem(lexems)
  93.     if curLexem.Tag & MUL != 0{
  94.         *res *= ParseF(lexems)
  95.         ParseSubT(res,lexems)
  96.         return
  97.     }else if curLexem.Tag & DIV != 0{
  98.         *res /= ParseF(lexems)
  99.         ParseSubT(res,lexems)
  100.         return
  101.     }
  102.     missedLexems = append(missedLexems,curLexem)
  103. }
  104. func ParseF(lexems chan Lexem)int64{
  105.     curLexem := GetLexem(lexems)
  106.     if curLexem.Tag & NUMBER != 0{
  107.         value, _:=strconv.Atoi(curLexem.Image)
  108.         return int64(value)
  109.     }else if curLexem.Tag & VAR != 0{
  110.         return AskVar(curLexem.Image)
  111.     }else if curLexem.Tag & LPAREN != 0{
  112.         res := ParseExpr(lexems)
  113.         _ = GetLexem(lexems)
  114.         return res
  115.     }else if curLexem.Tag & MINUS != 0{
  116.         return -ParseF(lexems)
  117.     }else if curLexem.Tag & PLUS != 0{
  118.         return ParseF(lexems)
  119.     }else{
  120.         fmt.Println("error")
  121.         os.Exit(0)
  122.     }
  123.     return 1
  124. }
  125. func IsDigit(ch uint8) bool{
  126.     return '0' <= ch && ch <= '9'
  127. }
  128. func IsAlpha(ch uint8) bool{
  129.     return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')
  130. }
  131. func ParseInt(expr string, i int) int{
  132.     for i < len(expr) && IsDigit(expr[i]){
  133.         i++
  134.     }
  135.     return i
  136. }
  137. func ParseVar(expr string, i int) int{
  138.     for i < len(expr) && (IsDigit(expr[i]) || IsAlpha(expr[i])){
  139.         i++
  140.     }
  141.     return i
  142. }
  143. func lexer(expr string, lexems chan Lexem){
  144.     for i := 0; i < len(expr); i++{
  145.         curChar := expr[i]
  146.         if curChar == ' '{
  147.             continue
  148.         }else if curChar == '+'{
  149.             lexems <- Lexem{PLUS,"+"}
  150.         }else if curChar == '-'{
  151.             lexems <- Lexem{MINUS,"-"}
  152.         }else if curChar == '*'{
  153.             lexems <- Lexem{MUL,"*"}
  154.         }else if curChar == '/'{
  155.             lexems <- Lexem{DIV,"/"}
  156.         }else if curChar == '('{
  157.             lexems <- Lexem{LPAREN,"("}
  158.         }else if curChar == ')'{
  159.             lexems <- Lexem{RPAREN,")"}
  160.         }else if IsDigit(curChar){
  161.             end := ParseInt(expr,i)
  162.             lexems <- Lexem{NUMBER,expr[i:end]}
  163.             i = end-1
  164.         }else if IsAlpha(curChar){
  165.             end := ParseVar(expr,i)
  166.             lexems <- Lexem{VAR,expr[i:end]}
  167.             i = end-1
  168.         }else{
  169.             lexems <- Lexem{ERROR,"undefined char found"}
  170.         }
  171.     }
  172.     lexems <- Lexem{END,"end of expr"}
  173.     close(lexems)
  174.  
  175. }
  176. func main(){
  177.     var expr string
  178.     tmp := bufio.NewScanner(os.Stdin)
  179.     state := 0
  180.     for tmp.Scan(){
  181.         if state == 0{
  182.             expr = tmp.Text()
  183.             state = 1
  184.         }else{
  185.             value, _ := strconv.Atoi(tmp.Text())
  186.             var_queue = append(var_queue, int64(value))
  187.         }
  188.     }
  189.     lexCh := make(chan Lexem)
  190.     go lexer(expr,lexCh)
  191.     res := ParseExpr(lexCh)
  192.     if len(lexCh) == 0 && len(missedLexems) == 1 && missedLexems[0].Tag & END != 0{
  193.         fmt.Println(res)
  194.     }else{
  195.         fmt.Println("error")
  196.     }
  197. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement