永发信息网

Ruby写的一个对四则运算表达式解析和求值的程序

答案:2  悬赏:50  手机版
解决时间 2021-04-13 05:56
  • 提问者网友:謫仙
  • 2021-04-12 20:07
Ruby写的一个对四则运算表达式解析和求值的程序
最佳答案
  • 五星知识达人网友:妄饮晩冬酒
  • 2021-04-12 20:36
加上#encoding:utf-8
全部回答
  • 1楼网友:不想翻身的咸鱼
  • 2021-04-12 21:32
class ParseError < Exception
end
#词法分析类
class Lex
        def initialize(strExp)
                @strExp = strExp.gsub(/s+/, '')
        end
        def nextToken
                if @strExp =~ /^d+/
                        @strExp = $'
                        $&.to_i
                elsif @strExp =~ /^(+|-|*|/|(|))/
                        @strExp = $'
                        $&
                elsif @strExp =~ /^$/
                        nil
                else
                        raise ParseError.new('Unknown character ==> ' 
                                + @strExp)
                end
        end
end
#语法分析和求值在这里一勺烩了
class Syntax
        def parse(&procToken)
                @procToken = procToken
                nextToken
                val = exp
                matchType(NilClass)
                return val
        end
private
        def nextToken
                @currentToken = @procToken.call
        end
        def matchStr(t)
                if @currentToken.is_a?(String) and @currentToken == t
                        nextToken
                        return t
                else
                        requireError(t)
                end
        end
        def matchType(t)
                tmp = @currentToken
                if @currentToken.is_a?(t)
                        nextToken
                        return tmp
                else
                        requireError(t.class)
                end
        end
        def requireError(*a)
                raise ParseError.new(
                        "require '#{a.join(',')}', " + 
                                "token='#{@currentToken}'")
        end
        def exp
                val = term
                while TRUE
                        if @currentToken == '+'
                                matchStr('+')
                                val += term
                        elsif @currentToken == '-'
                                matchStr('-')
                                val -= term
                        else
                                break
                        end
                end
                return val
        end
        def term
                val = factor
                while TRUE
                        if @currentToken == '*'
                                matchStr('*')
                                val *= factor
                        elsif @currentToken == '/'
                                matchStr('/')
                                d = factor
                                raise '除数为零' if d == 0
                                val /= d
                        else
                                break
                        end
                end
                return val
        end
        def factor
                if @currentToken.is_a?(Integer)
                        return matchType(Integer)
                elsif @currentToken == '('
                        matchStr('(')
                        val = exp
                        matchStr(')')
                        return val
                else
                        requireError(['Integer', '('])
                end
        end
end
#为了方便使用定义一个包装函数
def parseExp(exp)
        l = Lex.new(exp)
        s = Syntax.new
        s.parse { l.nextToken }
end
#测试代码
EXPS = %w{
        100
        (1)
        1+2
        1*3
        1+2-3
        5-2-1
        5-(2-1)
        1-2*3
        (1-2)*3
        4/2
        (1+2)*(3+4)
        (1+2)*(3+(4*2))
        1+(2+3 
        1+2+
        1++
        4/(1-1)
}
EXPS.each do
        |x|
        begin
                puts "#{x}=#{parseExp(x)}"
        rescue Exception => e
                puts "*Error* #{e}(#{e.class}), exp=#{x}"
        end
end
我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息
大家都在看
推荐资讯