Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- " Jack Crenshaw's "Let's Build a Compiler", Part III: More Expressions
- " Barry Arthur Jun 26, 2011
- "
- " This translator converts expressions of the form:
- " x = (-B()+a)-5/9*2
- " Into:
- " let x = (-B()+a)-5/9*2
- "
- " In and of itself not terribly amazing, agreed, but the value is in the how,
- " not the what.
- function! GetChar()
- let s:look = strpart(s:input, s:pos, 1)
- let s:pos += 1
- endfunction
- function! Error(msg)
- echoerr "Error: " . a:msg . "."
- endfunction
- function! Abort(msg)
- call Error(a:msg)
- endfunction
- function! Expected(msg)
- call Abort(a:msg . ' Expected')
- endfunction
- function! Match(c)
- if s:look == a:c
- call GetChar()
- else
- call Expected("'" . a:c . "'")
- endif
- endfunction
- function! IsAddop(c)
- return index(['+', '-'], a:c) != -1
- endfunction
- function! IsAlpha(c)
- return match(a:c, '[A-Z]') != -1
- endfunction
- function! IsDigit(c)
- return match(a:c, '[0-9]') != -1
- endfunction
- function! GetName()
- if !IsAlpha(s:look)
- call Expected('Name')
- endif
- let retval = tolower(s:look)
- call GetChar()
- return retval
- endfunction
- function! GetNum()
- if !IsDigit(s:look)
- call Expected('Integer')
- endif
- let retval = s:look
- call GetChar()
- return retval
- endfunction
- function! Emit(code)
- let s:output .= a:code
- endfunction
- function! Init(input)
- let s:look = ''
- let s:input = a:input
- let s:output = ''
- let s:pos = 0
- call GetChar()
- endfunction
- function! Ident()
- let name = GetName()
- if s:look == '('
- call Match('(')
- call Match(')')
- call Emit(toupper(name) . '()')
- else
- call Emit(name)
- endif
- endfunction
- function! Factor()
- if s:look == '('
- call Match('(')
- call Emit('(')
- call Expression()
- call Match(')')
- call Emit(')')
- elseif IsAlpha(s:look)
- call Ident()
- else
- call Emit(GetNum())
- endif
- endfunction
- function! Multiply()
- call Match('*')
- call Emit('*')
- call Factor()
- endfunction
- function! Divide()
- call Match('/')
- call Emit('/')
- call Factor()
- endfunction
- function! Term()
- call Factor()
- while index(['*', '/'], s:look) != -1
- if s:look == '*'
- call Multiply()
- elseif s:look == '/'
- call Divide()
- endif
- endwhile
- endfunction
- function! Add()
- call Match('+')
- call Emit('+')
- call Term()
- endfunction
- function! Subtract()
- call Match('-')
- call Emit('-')
- call Term()
- endfunction
- function! Expression()
- if IsAddop(s:look)
- call Emit(s:look)
- call GetChar()
- call Expression()
- else
- call Term()
- while IsAddop(s:look)
- if s:look == '+'
- call Add()
- elseif s:look == '-'
- call Subtract()
- endif
- endwhile
- endif
- endfunction
- function! Assignment()
- let name = GetName()
- call Match('=')
- call Emit('let ' . name . ' = ')
- call Expression()
- endfunction
- function! Parse(input)
- call Init(a:input)
- call Assignment()
- if s:look != "\n"
- call Expected('Newline')
- else
- return s:output
- endif
- endfunction
- " Test
- echo Parse("x=(-B()+A)-5/9*2\n")
Advertisement
Add Comment
Please, Sign In to add comment