bairui

Crenshaw's Compiler Tutorial in VimL

Jun 26th, 2011
210
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VIM 3.10 KB | None | 0 0
  1. let s:look = ''
  2. let s:input = ''
  3. let s:output = ''
  4. let s:pos = 0
  5.  
  6. function! GetChar()
  7.   let s:look = strpart(s:input, s:pos, 1)
  8.   let s:pos += 1
  9. endfunction
  10.  
  11. function! Error(msg)
  12.   echoerr "Error: " . a:msg . "."
  13. endfunction
  14.  
  15. function! Abort(msg)
  16.   call Error(a:msg)
  17.   " Halt   let s:running = 0
  18. endfunction
  19.  
  20. function! Expected(msg)
  21.   call Abort(a:msg . ' Expected')
  22. endfunction
  23.  
  24. function! Match(c)
  25.   if s:look == a:c
  26.     call GetChar()
  27.   else
  28.     call Expected("'" . x . "'")
  29.   endif
  30. endfunction
  31.  
  32. function! IsAddop(c)
  33.   return index(['+', '-'], a:c) != -1
  34. endfunction
  35.  
  36. function! IsAlpha(c)
  37.   return match(a:c, '\C[A-Z]') != -1
  38. endfunction
  39.  
  40. function! IsDigit(c)
  41.   return match(a:c, '[0-9]') != -1
  42. endfunction
  43.  
  44. function! GetName()
  45.   if !IsAlpha(s:look)
  46.     call Expected('Name')
  47.   endif
  48.   let retval = toupper(s:look)
  49.   call GetChar()
  50.   return retval
  51. endfunction
  52.  
  53. function! GetNum()
  54.   if !IsDigit(s:look)
  55.     call Expected('Integer')
  56.   endif
  57.   let retval = s:look
  58.   call GetChar()
  59.   return retval
  60. endfunction
  61.  
  62. function! Emit(code)
  63.   let s:output .= a:code
  64. endfunction
  65.  
  66. function! EmitLn(code)
  67.   call Emit(a:code)
  68.   let s:output .= "\r"
  69. endfunction
  70.  
  71. function! Init(input)
  72.   let s:look = ''
  73.   let s:input = a:input
  74.   let s:output = ''
  75.   let s:pos = 0
  76.   call GetChar()
  77. endfunction
  78.  
  79. function! Ident()
  80.   let name = GetName()
  81.   if s:look == '('
  82.     call Match('(')
  83.     call Match(')')
  84.     call EmitLn('BSR ' . name)
  85.   else
  86.     call EmitLn('MOVE ' . name . '(PC),D0')
  87.   endif
  88. endfunction
  89.  
  90. function! Factor()
  91.   if s:look == '('
  92.     call Match('(')
  93.     call Expression()
  94.     call Match(')')
  95.   elseif IsAlpha(s:look)
  96.     call Ident()
  97.   else
  98.     call EmitLn('MOVE #' . GetNum() . ',D0')
  99.   endif
  100. endfunction
  101.  
  102. function! Multiply()
  103.   call Match('*')
  104.   call Factor()
  105.   call EmitLn('MULS (SP)+,D0')
  106. endfunction
  107.  
  108. function! Divide()
  109.   call Match('/')
  110.   call Factor()
  111.   call EmitLn('MOVE (SP)+,D1')
  112.   call EmitLn('DIVS D1,D0')
  113. endfunction
  114.  
  115. function! Term()
  116.   call Factor()
  117.   while index(['*', '/'], s:look) != -1
  118.     call EmitLn('MOVE D0,-(SP)')
  119.     if s:look == '*'
  120.       call Multiply()
  121.     elseif s:look == '/'
  122.       call Divide()
  123.     endif
  124.   endwhile
  125. endfunction
  126.  
  127. function! Add()
  128.   call Match('+')
  129.   call Term()
  130.   call EmitLn('ADD (SP)+,D0')
  131. endfunction
  132.  
  133. function! Subtract()
  134.   call Match('-')
  135.   call Term()
  136.   call EmitLn('SUB (SP)+,D0')
  137.   call EmitLn('NEG D0')
  138. endfunction
  139.  
  140. function! Expression()
  141.   if IsAddop(s:look)
  142.     call EmitLn('CLR D0')
  143.   else
  144.     call Term()
  145.     while IsAddop(s:look)
  146.       call EmitLn('MOVE D0,-(SP)')
  147.       if s:look == '+'
  148.         call Add()
  149.       elseif s:look == '-'
  150.         call Subtract()
  151.       endif
  152.     endwhile
  153.   endif
  154. endfunction
  155.  
  156. function! Assignment()
  157.   let name = GetName()
  158.   call Match('=')
  159.   call Expression()
  160.   call EmitLn('LEA ' . name . '(PC),A0')
  161.   call EmitLn('MOVE D0,(A0)')
  162. endfunction
  163.  
  164. function! Parse(input)
  165.   call Init(a:input)
  166.   call Expression()
  167.   if s:look != "\n"
  168.     call Expected('Newline')
  169.   else
  170.     echomsg s:output
  171.   endif
  172. endfunction
  173.  
  174. call Parse("(1+2)/9\n")
Advertisement
Add Comment
Please, Sign In to add comment