четверг, 14 августа 2014 г.

Калькулятор на Lua в 30 строк

Захотелось написать зародыш компилятора )))

Интерпретатор:
function   oper(src) return src:match'^([-+*/]?)%s*(.*)' end
function number(src) return src:match'^(%d*)%s*(.*)' end
operators = {
    {
        ['+'] = function(a,b) return a+b end,
        ['-'] = function(a,b) return a-b end
    },{
        ['*'] = function(a,b) return a*b end,
        ['/'] = function(a,b) return a/b end
    }
}

function expr(src, pri)
    local a,b,n,r,op
    pri = pri or 1
    op = operators[pri]
    if op then
        a, src = expr(src, pri+1)
        r, src = oper(src)
        while op[r] do
            b, src = expr(src, pri+1)
            a = op[r](a,b)
            r, src = oper(src)
        end
        return a, r..src
    end
    r, src = number(src)
    if r=='' then error('number expected: '..src) end
    return r, src
end

print(expr('2 + 2 * 3')) -- 8
В operators операции расположены по приоритетам (низкий в начале). Можно добавлять свои операции.

Теперь компилятор. Компилирует в псевдокод для стековой машины.
function   oper(src) return src:match'^([-+*/]?)%s*(.*)' end
function number(src) return src:match'^(%d*)%s*(.*)' end

operators = {
    { ['+'] = 'ADD', ['-'] = 'SUB'},
    { ['*'] = 'MUL', ['/'] = 'DIV'}
}

function expr(src, pri)
    local r, op
    pri = pri or 1
    op = operators[pri]
    if op then
        src = expr(src, pri+1)
        r, src = oper(src)
        while op[r] do
            src = expr(src, pri+1)
            print(op[r])
            r, src = oper(src)
        end
        return r..src
    end
    r, src = number(src)
    if r=='' then error('number expected: '..src) end
    print('PUSH '..r)
    return src
end

expr('2+2*3+2')
Результат:
PUSH 2
PUSH 2
PUSH 3
MUL
ADD
PUSH 2
ADD

Комментариев нет:

Отправить комментарий