Guest User

Untitled

a guest
May 14th, 2018
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. namespace "Analysis", ->
  2.     "use strict"
  3.  
  4.     class @Parser
  5.         maker = new Building.PrimeMaker
  6.  
  7.         run : (@source = '') ->
  8.             do @compressStrings
  9.             do @makeLexems
  10.             do @decorateLexems
  11.             do @generateAddlBlocks
  12.             do @compressBlocks
  13.             do @parseBlocks
  14.            
  15.             return @program
  16.  
  17.         compressStrings : ->
  18.             @strings = []
  19.             @source = @source.replace /'.*?'/g, (str) =>
  20.                 @strings.push str
  21.                 "$!#{@strings.length-1}!$"
  22.             return
  23.  
  24.         makeLexems : ->
  25.             @lexems = @source
  26.                 .replace(/\w+|[;\)\(]/g, ' $& ')
  27.                 .split(/\s+/)
  28.                 .clear()
  29.             return
  30.  
  31.         replTable =
  32.             ':='  : '=', '*'   : '∙', '/'   : '÷', 'in'  : '∈'
  33.             'and' : '∧', 'or'  : '∨', 'xor' : '⊕', 'not' : '¬'
  34.             '<='  : '≤', '>='  : '≥', '<>'  : '≠', '><'  : '≠'
  35.  
  36.         decorateLexems : ->
  37.             @lexems = @lexems.map (el) ->
  38.                 replTable[el.low] || el
  39.  
  40.             return
  41.  
  42.         generateAddlBlocks : ->
  43.             # loop repeat-until
  44.             for lexem, i in @lexems when lexem.low == 'repeat'
  45.                 @lexems.splice i+1, 0, 'begin'
  46.                 ++i
  47.            
  48.             for lexem, i in @lexems when lexem.low == 'until'
  49.                 @lexems.splice i, 0, 'end'
  50.                 ++i
  51.  
  52.             # after keywords
  53.             keys = ['do', 'then', 'else']; n = @lexems.length
  54.             for i in [0...n] when (lexem = @lexems[i].low) in keys
  55.                 continue if @lexems[i+1] == 'begin'
  56.  
  57.                 @lexems.splice ++i, 0, 'begin'
  58.                 ++i # now i is first index after 'begin'
  59.  
  60.                 conds = blocks = 0
  61.                 end = i - 1
  62.                 isBody = yes
  63.                 while isBody
  64.                     switch @lexems[++end].low
  65.                         when 'then'  then ++conds
  66.                         when 'begin' then ++blocks
  67.                         when 'end'   then --blocks
  68.  
  69.                         when 'else'
  70.                             unless conds
  71.                                 isBody = no
  72.                             else --conds
  73.  
  74.                         when ';'
  75.                             isBody = no unless blocks
  76.                
  77.                 @lexems.splice end, 0, ';', 'end'
  78.                 n += 2
  79.            
  80.             return
  81.  
  82.         compressBlocks : ->
  83.             createProgram = (type, name) ->
  84.                 {type, name, sub : [], main : null}
  85.  
  86.             globName = @lexems[i+1] if ~i = @lexems.indexOf('program')
  87.             @program = createProgram('program', globName || 'nameless')
  88.  
  89.             @links  = []
  90.             @blocks = []
  91.  
  92.             sub = /^(?:procedure|function)$/
  93.             stack = [@program]
  94.             for lexem, i in @lexems
  95.                 lexem = lexem.low
  96.                 if sub.test lexem
  97.                     current = createProgram(lexem, @lexems[i+1])
  98.                     stack.last.sub.push current
  99.                     stack.push current
  100.  
  101.                 else if lexem is 'begin'
  102.                     {stop : i} = @compressBlock i
  103.                     stack.pop().main = @blocks.last
  104.            
  105.             return
  106.  
  107.         sepr = /\s*;\s*/
  108.         compressBlock : (start) ->
  109.             localLexems = []
  110.             i = start + 1
  111.  
  112.             loop
  113.                 lexem = @lexems[i]
  114.                 break if lexem.low == 'end'
  115.  
  116.                 if lexem.low == 'begin'
  117.                     {lexems, stop} = @compressBlock(i)
  118.                     i = stop
  119.  
  120.                     lexem = "$#{@links.length-1}$"
  121.  
  122.                 localLexems.push lexem
  123.                 ++i
  124.             localLexems = localLexems.join(' ').split(sepr).clear()
  125.             @links.push localLexems
  126.             @blocks.push []
  127.             {lexems : localLexems, stop : i}
  128.  
  129.         expandBlock : (str) ->
  130.             return null unless str?
  131.             if str[0] is '$'
  132.                 end = str.indexOf('$', 1)
  133.                 num = +str[1...end]
  134.                 return null if isNaN num
  135.                 @blocks[num]
  136.  
  137.         expandString : (str) ->
  138.             return null unless str?
  139.             str.replace /\$!.*?!\$/g, (el) =>
  140.                 end = el.lastIndexOf('!$')
  141.                 num = +el[2...end].trim()
  142.                 @strings[num]
  143.  
  144.         decList = [
  145.             [/\s*([\(\):¬])\s*/g, '$1']
  146.             [/\s*,\s*/g, ', ']
  147.             [/\s*([∙=÷∈∧∨⊕≤≥≠])\s*/g,' $1 ']
  148.         ]
  149.  
  150.         decorateStatement : (str) ->
  151.             decList.each (pair) ->
  152.                 str = str.replace(pair[0], pair[1])
  153.            
  154.             return str
  155.  
  156.         makeGetterPrimes : (args..., def) ->
  157.             improve = (str) =>
  158.                 @expandString @decorateStatement str
  159.  
  160.             sets = []
  161.             for list, i in args by 2
  162.                 sets.push
  163.                     # [0..1] - temporary solution
  164.                     sign : new RegExp "\\b#{list[0..1].join('\\b.*?\\b')}\\b", 'i'
  165.                     sepr : new RegExp "\\s*\\b(?:#{list.join('|')})\\b\\s*", 'i'
  166.                     func : args[i+1]
  167.            
  168.             return (str) =>
  169.                 for st in sets when st.sign.test str
  170.  
  171.                     return st.func str.split(st.sepr).clear().map (str) =>
  172.                         @expandBlock(str) || improve(str)
  173.                
  174.                 return def(improve str)
  175.  
  176.         parseBlocks : ->
  177.             getPrimes = @makeGetterPrimes(
  178.                 ['if', 'then', 'else'],  maker.condition
  179.                 ['for', 'to', 'do'],     maker.loopForU
  180.                 ['for', 'downto', 'do'], maker.loopForD
  181.                 ['for', 'in'],           maker.loopIn
  182.                 ['while', 'do'],         maker.loopWhile
  183.                 ['repeat', 'until'],     maker.loopUntil
  184.                                          maker.statement
  185.             )
  186.  
  187.             for strBlock, i in @links
  188.                 for str in strBlock
  189.                     @blocks[i].push getPrimes(str)...
  190.            
  191.             # Start-end
  192.             main = @blocks.last
  193.             main.unshift maker.terminator('Начало')[0]
  194.             main.push    maker.terminator('Конец' )[0]
  195.  
  196.             return
Add Comment
Please, Sign In to add comment