Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "bufio"
- "fmt"
- "os"
- "strconv"
- )
- type Tag int
- const (
- ERROR Tag = 1 << iota
- NUMBER
- VAR
- PLUS
- MINUS
- MUL
- DIV
- LPAREN
- RPAREN
- END
- )
- var vars = make(map[string]int64)
- var varExist = make(map[string]bool)
- var var_queue []int64
- var missedLexems []Lexem
- func AskVar(varName string) int64{
- _, ok := varExist[varName]
- if ok{
- return vars[varName]
- }else{
- value := var_queue[0]
- var_queue = var_queue[1:]
- varExist[varName] = true
- vars[varName] = value
- return value
- }
- }
- type Lexem struct {
- Tag
- Image string
- }
- func GetLexem(lexems chan Lexem) Lexem{
- var curLexem Lexem
- if len(missedLexems) > 0{
- curLexem = missedLexems[0]
- missedLexems = missedLexems[1:]
- }else{
- var ok bool
- curLexem, ok = <- lexems
- if !ok || (curLexem.Tag & ERROR) != 0{
- fmt.Println("error")
- os.Exit(0)
- }
- }
- return curLexem
- }
- func ParseExpr(lexems chan Lexem) int64{
- res := ParseT(lexems)
- ParseSubExpr(&res, lexems)
- return res
- }
- func ParseSubExpr(res *int64, lexems chan Lexem){
- curLexem := GetLexem(lexems)
- if curLexem.Tag & PLUS != 0{
- *res += ParseT(lexems)
- ParseSubExpr(res, lexems)
- return
- }else if curLexem.Tag & MINUS != 0{
- *res += -ParseT(lexems)
- ParseSubExpr(res, lexems)
- return
- }
- missedLexems = append(missedLexems,curLexem)
- }
- /*
- <E> ::= <T> <E’>.
- <E’> ::= + <T><E'> | - <T><E'> | .
- <T> ::= <F> <T’>.
- <T’> ::= * <F> <T’> | / <F> <T’> | .
- <F> ::= <number> | <var> | ( <E> ) | - <F>.
- */
- func ParseT(lexems chan Lexem) int64{
- res := ParseF(lexems)
- ParseSubT(&res, lexems)
- return res
- }
- func ParseSubT(res *int64, lexems chan Lexem){
- curLexem := GetLexem(lexems)
- if curLexem.Tag & MUL != 0{
- *res *= ParseF(lexems)
- ParseSubT(res,lexems)
- return
- }else if curLexem.Tag & DIV != 0{
- *res /= ParseF(lexems)
- ParseSubT(res,lexems)
- return
- }
- missedLexems = append(missedLexems,curLexem)
- }
- func ParseF(lexems chan Lexem)int64{
- curLexem := GetLexem(lexems)
- if curLexem.Tag & NUMBER != 0{
- value, _:=strconv.Atoi(curLexem.Image)
- return int64(value)
- }else if curLexem.Tag & VAR != 0{
- return AskVar(curLexem.Image)
- }else if curLexem.Tag & LPAREN != 0{
- res := ParseExpr(lexems)
- _ = GetLexem(lexems)
- return res
- }else if curLexem.Tag & MINUS != 0{
- return -ParseF(lexems)
- }else if curLexem.Tag & PLUS != 0{
- return ParseF(lexems)
- }else{
- fmt.Println("error")
- os.Exit(0)
- }
- return 1
- }
- func IsDigit(ch uint8) bool{
- return '0' <= ch && ch <= '9'
- }
- func IsAlpha(ch uint8) bool{
- return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')
- }
- func ParseInt(expr string, i int) int{
- for i < len(expr) && IsDigit(expr[i]){
- i++
- }
- return i
- }
- func ParseVar(expr string, i int) int{
- for i < len(expr) && (IsDigit(expr[i]) || IsAlpha(expr[i])){
- i++
- }
- return i
- }
- func lexer(expr string, lexems chan Lexem){
- for i := 0; i < len(expr); i++{
- curChar := expr[i]
- if curChar == ' '{
- continue
- }else if curChar == '+'{
- lexems <- Lexem{PLUS,"+"}
- }else if curChar == '-'{
- lexems <- Lexem{MINUS,"-"}
- }else if curChar == '*'{
- lexems <- Lexem{MUL,"*"}
- }else if curChar == '/'{
- lexems <- Lexem{DIV,"/"}
- }else if curChar == '('{
- lexems <- Lexem{LPAREN,"("}
- }else if curChar == ')'{
- lexems <- Lexem{RPAREN,")"}
- }else if IsDigit(curChar){
- end := ParseInt(expr,i)
- lexems <- Lexem{NUMBER,expr[i:end]}
- i = end-1
- }else if IsAlpha(curChar){
- end := ParseVar(expr,i)
- lexems <- Lexem{VAR,expr[i:end]}
- i = end-1
- }else{
- lexems <- Lexem{ERROR,"undefined char found"}
- }
- }
- lexems <- Lexem{END,"end of expr"}
- close(lexems)
- }
- func main(){
- var expr string
- tmp := bufio.NewScanner(os.Stdin)
- state := 0
- for tmp.Scan(){
- if state == 0{
- expr = tmp.Text()
- state = 1
- }else{
- value, _ := strconv.Atoi(tmp.Text())
- var_queue = append(var_queue, int64(value))
- }
- }
- lexCh := make(chan Lexem)
- go lexer(expr,lexCh)
- res := ParseExpr(lexCh)
- if len(lexCh) == 0 && len(missedLexems) == 1 && missedLexems[0].Tag & END != 0{
- fmt.Println(res)
- }else{
- fmt.Println("error")
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement