Advertisement
Delfigamer

scripts/index-cmd/init.lua

Oct 23rd, 2015
398
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.61 KB | None | 0 0
  1. local modname = ...
  2. module(modname, package.seeall)
  3. -- local ffi = require('ffi')
  4. local host = require('host')
  5. local window = require('host.window')
  6.  
  7. local getch
  8. local ungetch
  9. local peekch
  10. local tokenstack = {} -- only used to show the command-line user what he's expected to close
  11. -- actual parser state is kept on call stack
  12. do
  13.     local buffer = {}
  14.     local newline = true
  15.  
  16.     local function getch_raw()
  17.         if newline then
  18.             if #tokenstack > 0 then
  19.                 host.write(' ')
  20.                 host.write(table.concat(tokenstack, ' | '))
  21.                 host.write(' >> ')
  22.             else
  23.                 host.write('>> ')
  24.             end
  25.             newline = false
  26.         end
  27.         local ch = host.getchar()
  28.         if ch == '\n' then
  29.             newline = true
  30.         end
  31.         return ch
  32.     end
  33.  
  34.     function getch()
  35.         local ch
  36.         if #buffer > 0 then
  37.             ch = table.pop(buffer)
  38.         else
  39.             ch = getch_raw()
  40.         end
  41.         return ch
  42.     end
  43.  
  44.     function ungetch(ch)
  45.         table.append(buffer, ch)
  46.     end
  47.  
  48.     function peekch()
  49.         local ch = getch()
  50.         ungetch(ch)
  51.         return ch
  52.     end
  53. end
  54.  
  55. local obtaintoken
  56.  
  57. local function obtainstringelement()
  58.     local ch = getch()
  59.     if ch == '\\' then
  60.         ch = ch .. getch()
  61.     end
  62.     return ch
  63. end
  64.  
  65. local function obtainstring()
  66.     local open = getch()
  67.     table.append(tokenstack, open)
  68.     local content = {open}
  69.     while true do
  70.         local element = obtainstringelement()
  71.         table.append(content, element)
  72.         if element == open then
  73.             break
  74.         elseif element == '\n' then
  75.             if peekch() == '\n' then
  76.                 table.append(content, getch())
  77.                 break
  78.             end
  79.         end
  80.     end
  81.     table.pop(tokenstack)
  82.     return table.concat(content)
  83. end
  84.  
  85. local function obtainlongstring(level)
  86.     local open = '[' .. string.rep('=', level) .. '['
  87.     local content = {open}
  88.     table.append(tokenstack, open)
  89.     while true do
  90.         local ch = getch()
  91.         table.append(content, ch)
  92.         if ch == ']' then
  93.             for i = 1, level do
  94.                 ch = getch()
  95.                 if ch == '=' then
  96.                     table.append(content, ch)
  97.                 else
  98.                     ungetch(ch)
  99.                     ch = nil
  100.                     break
  101.                 end
  102.             end
  103.             if ch then
  104.                 ch = getch()
  105.                 if ch == ']' then
  106.                     table.append(content, ch)
  107.                     break
  108.                 else
  109.                     ungetch(ch)
  110.                 end
  111.             end
  112.         elseif ch == '\n' then
  113.             if peekch() == '\n' then
  114.                 table.append(content, getch())
  115.                 break
  116.             end
  117.         end
  118.     end
  119.     table.pop(tokenstack)
  120.     return table.concat(content)
  121. end
  122.  
  123. local letter = {
  124.     ['_'] = true,
  125. }
  126. local letterordigit = {
  127.     ['_'] = true,
  128. }
  129. for i = string.byte('A'), string.byte('Z') do
  130.     letter[string.char(i)] = true
  131.     letterordigit[string.char(i)] = true
  132. end
  133. for i = string.byte('a'), string.byte('z') do
  134.     letter[string.char(i)] = true
  135.     letterordigit[string.char(i)] = true
  136. end
  137. for i = string.byte('0'), string.byte('9') do
  138.     letterordigit[string.char(i)] = true
  139. end
  140.  
  141. local wordtable = {
  142.     ['do'] = 'end',
  143.     ['function'] = 'end',
  144.     ['if'] = 'end',
  145.     ['repeat'] = 'until',
  146. }
  147.  
  148. local function obtainwordbody(open)
  149.     table.append(tokenstack, open)
  150.     local close = wordtable[open]
  151.     local content = {open}
  152.     while true do
  153.         local token = obtaintoken()
  154.         table.append(content, token)
  155.         if token == close then
  156.             break
  157.         elseif token == '\n' then
  158.             if peekch() == '\n' then
  159.                 table.append(content, getch())
  160.                 break
  161.             end
  162.         end
  163.     end
  164.     table.pop(tokenstack)
  165.     return table.concat(content)
  166. end
  167.  
  168. local function obtainword()
  169.     local word = ''
  170.     while true do
  171.         local ch = getch()
  172.         if letterordigit[ch] then
  173.             word = word .. ch
  174.         else
  175.             ungetch(ch)
  176.             break
  177.         end
  178.     end
  179.     if wordtable[word] then
  180.         return obtainwordbody(word)
  181.     else
  182.         return word
  183.     end
  184. end
  185.  
  186. local brackettable = {
  187.     ['('] = ')',
  188.     ['['] = ']',
  189.     ['{'] = '}',
  190. }
  191.  
  192. local function obtainbracket()
  193.     local open = getch()
  194.     table.append(tokenstack, open)
  195.     local close = brackettable[open]
  196.     local content = {open}
  197.     while true do
  198.         local token = obtaintoken()
  199.         table.append(content, token)
  200.         if token == close then
  201.             break
  202.         elseif token == '\n' then
  203.             if peekch() == '\n' then
  204.                 table.append(content, getch())
  205.                 break
  206.             end
  207.         end
  208.     end
  209.     table.pop(tokenstack)
  210.     return table.concat(content)
  211. end
  212.  
  213. local tokentable = {
  214.     ['\''] = obtainstring,
  215.     ['"'] = obtainstring,
  216. }
  217. for ch in pairs(letter) do
  218.     tokentable[ch] = obtainword
  219. end
  220. for ch in pairs(brackettable) do
  221.     tokentable[ch] = obtainbracket
  222. end
  223.  
  224. tokentable['['] = function()
  225.     local open = getch()
  226.     local mid = {}
  227.     for i = 1, 16 do
  228.         local ch = getch()
  229.         if ch == '[' then
  230.             return obtainlongstring(#mid)
  231.         end
  232.         table.append(mid, ch)
  233.         if ch ~= '=' then
  234.             break
  235.         end
  236.     end
  237.     for i = #mid, 1, -1 do
  238.         ungetch(mid[i])
  239.     end
  240.     ungetch(open)
  241.     return obtainbracket()
  242. end
  243.  
  244. function obtaintoken()
  245.     local ch = peekch()
  246.     local tfunc = tokentable[ch]
  247.     if tfunc then
  248.         return tfunc()
  249.     else
  250.         return getch()
  251.     end
  252. end
  253.  
  254. local function obtaininput()
  255.     local str = ''
  256.     while true do
  257.         local token = obtaintoken()
  258.         if token == '\n' then
  259.             break
  260.         end
  261.         str = str .. token
  262.     end
  263.     return str
  264. end
  265.  
  266. function register()
  267.     log('entered interactive mode')
  268.     local terminate = false
  269.  
  270.     local function exit()
  271.         terminate = true
  272.     end
  273.  
  274.     local fenv = setmetatable({exit = exit}, {__index = _G})
  275.     fenv._ENV = fenv
  276.     print('Interactive input. Call "exit()" to continue\n')
  277.  
  278.     while not terminate do
  279.         local str = obtaininput()
  280.         local func, err = loadstring('print(' .. str .. ')', nil, nil, fenv)
  281.         if func then
  282.             local suc, err = pcall(func)
  283.             if not suc then
  284.                 print(err)
  285.             end
  286.         else
  287.             func, err = loadstring(str, nil, nil, fenv)
  288.             if func then
  289.                 local suc, err = pcall(func)
  290.                 if not suc then
  291.                     print(err)
  292.                 end
  293.             else
  294.                 print(err)
  295.             end
  296.         end
  297.     end
  298.     log('exited from interactive mode')
  299.     window:finish()
  300. end
  301.  
  302. function unregister()
  303. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement