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:
- " value = (-pi() + apple) - 50 / 90 * 2
- " Into:
- " let value = (-pi()+apple)-50/90*2
- "
- " In and of itself not terribly amazing, agreed, but the value is in the how,
- " not the what.
- "Parser {{{1
- function! Error(msg) "{{{2
- echoerr "Error: " . a:msg . "."
- endfunction
- function! Expected(msg) "{{{2
- call Error('Expected ' . a:msg . " at byte position " . s:pos . " but got '" . s:look . "' instead")
- endfunction
- function! Match(c) "{{{2
- if s:look == a:c
- call GetChar()
- else
- call Expected("'" . a:c . "'")
- endif
- endfunction
- function! IsAddop(c) "{{{2
- return index(['+', '-'], a:c) != -1
- endfunction
- function! IsAlpha(c) "{{{2
- return match(a:c, '[A-Z]') != -1
- endfunction
- function! IsDigit(c) "{{{2
- return match(a:c, '[0-9]') != -1
- endfunction
- function! IsAlNum(c) "{{{2
- return IsAlpha(a:c) || IsDigit(a:c)
- endfunction
- function! IsWhite(c) "{{{2
- return index([' ', "\t"], a:c) != -1
- endfunction
- function! SkipWhite() "{{{2
- while IsWhite(s:look)
- call GetChar()
- endwhile
- endfunction
- function! GetChar() "{{{2
- let s:look = strpart(s:input, s:pos, 1)
- let s:pos += 1
- call SkipWhite()
- endfunction
- function! GetName() "{{{2
- let name = ''
- if !IsAlpha(s:look)
- call Expected('Name')
- endif
- while IsAlNum(s:look)
- let name .= s:look
- call GetChar()
- endwhile
- return name
- endfunction
- function! GetNum() "{{{2
- let value = ''
- if !IsDigit(s:look)
- call Expected('Integer')
- endif
- while IsDigit(s:look)
- let value .= s:look
- call GetChar()
- endwhile
- return value
- endfunction
- function! Emit(code) "{{{2
- let s:output .= a:code
- endfunction
- function! Init(input) "{{{2
- let s:look = ''
- let s:input = a:input
- let s:output = ''
- let s:pos = 0
- call GetChar()
- endfunction
- function! Ident() "{{{2
- let name = GetName()
- if s:look == '('
- call Match('(')
- call Match(')')
- call Emit(name . '()')
- else
- call Emit(name)
- endif
- endfunction
- function! Factor() "{{{2
- 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() "{{{2
- call Match('*')
- call Emit('*')
- call Factor()
- endfunction
- function! Divide() "{{{2
- call Match('/')
- call Emit('/')
- call Factor()
- endfunction
- function! Term() "{{{2
- call Factor()
- while index(['*', '/'], s:look) != -1
- if s:look == '*'
- call Multiply()
- elseif s:look == '/'
- call Divide()
- endif
- endwhile
- endfunction
- function! Add() "{{{2
- call Match('+')
- call Emit('+')
- call Term()
- endfunction
- function! Subtract() "{{{2
- call Match('-')
- call Emit('-')
- call Term()
- endfunction
- function! Expression() "{{{2
- 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() "{{{2
- let name = GetName()
- call Match('=')
- call Emit('let ' . name . ' = ')
- call Expression()
- endfunction
- " Driver {{{1
- function! ParseAssignmentExpression(input)
- call Init(a:input)
- call Assignment()
- if s:look != ""
- call Expected('EOF')
- else
- return s:output
- endif
- endfunction
- " Test {{{1
- echo ParseAssignmentExpression("value = (-pi() + apple) - 15 / 90 * 2")
- " vim: fdm=marker
Advertisement
Add Comment
Please, Sign In to add comment