Advertisement
Guest User

Untitled

a guest
Aug 2nd, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.30 KB | None | 0 0
  1. # -*- coding: latin-1 -*-
  2. try: #True/False definition
  3. True, False
  4. except NameError:
  5. True, False = (1==1), (0==1)
  6.  
  7. def hex2int(str):
  8. hexref = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9,'A':10,'B':11,'C':12,'D':13,'E':14,'F':15}
  9. return hexref[str[0]]*16 hexref[str[1]]
  10.  
  11. def str2hex(str):
  12. return chr(hex2int(str))
  13.  
  14. def hex2ascii(strHex):
  15. out = ''
  16. strHex = strHex.replace("\n",'').replace("\t",'').replace(" ",'')
  17. for i in range(0,len(strHex),2):
  18. out = str2hex(strHex[i:i 2])
  19. return out
  20.  
  21. def int2hex(val):
  22. return hex(int(val)).replace('x','').upper()
  23.  
  24. # -----
  25. # ASM
  26. # -----
  27. class asm:
  28. pc = 0x100
  29. all = ''
  30. fixup = []
  31. movref = {'[AX]':'A1','AX':'B8','AL':'B0','BX':'BB','BL':'B3','CX':'B9','CH':'B5','DX':'DA','DL':'B2'}
  32. fmovref = {'AX':'A3'}
  33. pushref = {'AX':'50','DX':'52'}
  34. popref = {'AX':'58','BX':'5B'}
  35. addref = {'AX':'01','BX':'D8','CX':'C1'}
  36. imulref = {'BX':'EB'}
  37. negref = {'AX':'D8'}
  38. ifref = {'=':'7403','<>':'7503','<':'7C03','<=':'7E03','>':'7F03','>=':'7D03','odd':'24013C017403'}
  39. cmpref = {'AX':'39','BX':'C3'}
  40. pcon = True
  41.  
  42. def __init__(this,fileName):
  43. this.comFile = file(fileName '.com','wb')
  44.  
  45. def script(this,inst):
  46. if this.pcon == True:
  47. this.pc = len(inst)/2
  48. this.comFile.write(hex2ascii(inst))
  49. return inst
  50.  
  51. def jmp(this,pTo,pFrom=-1):
  52. this.all = 'JMP(%s,%s) \n' % (pTo,pFrom)
  53. return this.script('E9' this.address(pTo,pFrom))
  54.  
  55. def call(this,pTo,pFrom=-1):
  56. this.all = 'CALL(%s,%s) \n' % (pTo,pFrom)
  57. return this.script('E8' this.address(pTo,pFrom))
  58.  
  59. def address(this,pTo,pFrom=-1):
  60. if pFrom < 0: pFrom = this.pc
  61.  
  62. dis = hex(0xFFFF-pFrom pTo-2).upper()
  63. return dis[-2:] dis[-4:-2]
  64.  
  65. def write(this,txt):
  66. this.all = 'WRITE <str> \n'
  67. for c in txt:
  68. this.mov('DL',hex(ord(c))[2:].upper())
  69. this.call(0x107)
  70.  
  71. def neg(this,reg):
  72. this.all = 'NEG(%s) \n' % (reg)
  73. return this.script('F7' this.negref[reg])
  74.  
  75. def mov(this,to,val):
  76. this.all = 'MOV(%s,%s) \n' % (to,val)
  77. if to in this.movref:
  78. code = this.movref[to]
  79. elif val in this.fmovref:
  80. code = this.fmovref[val]
  81. aux = val
  82. val = to
  83. to = aux
  84.  
  85. if type(val)==int:
  86. val = int2hex(val)
  87.  
  88. if to[-1]=='X' or to[-1]==']':
  89. val = '0'*(4-len(val)) val
  90.  
  91. return this.script(code val[-2:] val[-4:-2])
  92.  
  93. def increment(this,reg,val=1):
  94. this.mov('[AX]', reg)
  95. this.push('AX')
  96. this.mov('AX', val)
  97. this.push('AX')
  98. this.pop('AX')
  99. this.pop('BX')
  100. this.add('AX','BX')
  101. this.mov(reg, 'AX')
  102.  
  103. def imul(this,reg):
  104. this.all = 'iMUL(%s) \n' % (reg)
  105. return this.script('F7' this.imulref[reg])
  106.  
  107. def mul(this):
  108. this.all = 'MUL(AX,BX) \n'
  109. return this.pop('AX') this.pop('BX') this.imul('BX') this.push('AX')
  110.  
  111. def div(this):
  112. this.all = 'DIV \n'
  113. return this.script('585B933D00007C06BA0000E90300BAFFFFF7FB50')
  114.  
  115. def ret(this):
  116. this.all = 'RET \n'
  117. return this.script('C3')
  118.  
  119. def cmp(this,r1,r2):
  120. this.all = 'CMP((%s,%s) \n' % (r1,r2)
  121. return this.script(this.cmpref[r1] this.cmpref[r2])
  122.  
  123. def op(this,op):
  124. this.all = 'OP( %s ) \n' % (op)
  125. return this.script(this.ifref[op])
  126.  
  127. def end(this):
  128. this.all = 'END \n'
  129. return this.script('B8004CCD21')
  130.  
  131. def push(this,reg):
  132. this.all = 'PUSH(%s) \n' % (reg)
  133. return this.script(this.pushref[reg])
  134.  
  135. def pop(this,reg):
  136. this.all = 'POP(%s) \n' % (reg)
  137. return this.script(this.popref[reg])
  138.  
  139. def add(this,r1,r2):
  140. this.all = 'ADD(%s,%s) \n' % (r1,r2)
  141. return this.script(this.addref[r1] this.addref[r2])
  142.  
  143. def setFixup(this,type):
  144. this.all = '<fixup>(%s) \n\n' % (type)
  145. if len(this.fixup) > 0:
  146. address = this.fixup.pop()
  147. else:
  148. address = 0x100
  149.  
  150. this.comFile.seek(address-0x100)
  151. this.pcon = False
  152. if type == 'while':
  153. this.jmp(this.pc 3,address)
  154. address = this.fixup.pop()
  155. else:
  156. this.jmp(this.pc,address)
  157. this.pcon = True
  158. this.comFile.seek(0,2)
  159. return address
  160.  
  161. def close(this):
  162. this.comFile.close()
  163.  
  164.  
  165. # -------------------------------------------
  166.  
  167.  
  168. # -----
  169. # LEX
  170. # -----
  171. class Lex:
  172. tRef = ('<op>','<del>','<nl>','<id>','<int>','<kw>','<str>')
  173. delDic = {0:(':=','<>','<=','>=','==','=',' ','-','*','/','<','>'), #Tuple, constantes
  174. 1:('[',']','(',')',';','.',','),
  175. 2:("\n","\t",' ')
  176. }
  177. ch = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM00123456789'
  178. num = '0123456789'
  179. fileName = ''
  180. kw = ('procedure','const','while','begin','then','call','var','end','do','if','write','writeln','readln','for','to')
  181. tokenList = []
  182. lexemList = []
  183. lineList = []
  184. index = -1
  185. listCount = 0
  186.  
  187. def __init__(this,fileName):
  188. try:
  189. this.fileName = fileName
  190. lexFile = file(fileName,'r') #codigo a analizar
  191. except IOError, e:
  192. import sys
  193. print e
  194. sys.exit() #termina el programa
  195.  
  196. this.fileLines = lexFile.readlines() #lee el archivo completo y lo mete linea por linea en una lista
  197. this.generateTokens()
  198. this.token = this.tRef[this.tokenList[0]]
  199. this.lexem = this.lexemList[0]
  200. this.listCount = len(this.tokenList)
  201.  
  202. def __repr__(this):
  203. return this.lexem
  204.  
  205. def __iter__(this):
  206. return this
  207.  
  208. def reset(this):
  209. this.index = 0
  210.  
  211. def next(this,step=1):
  212. this.index = step
  213. if this.index>=this.listCount:
  214. return False
  215.  
  216. this.token = this.tRef[this.tokenList[this.index]] #pop
  217. this.lexem = this.lexemList[this.index] #pop
  218. this.line = this.lineList[this.index] #pop
  219. return True
  220.  
  221. def prev(this):
  222. return this.next(-1)
  223.  
  224. def generateTokens(this):
  225. lineNro = 1
  226. for line in this.fileLines: #recorro el archivo por lineas
  227. startPos = endPos = 0
  228. lineLen = len(line)
  229. while endPos <= lineLen:
  230. isId = 1
  231. for lexType in this.delDic:
  232. for word in this.delDic[lexType]:
  233. endPos = startPos len(word)
  234. if line[startPos:endPos]==word:
  235. if lexType != 2: #ignora <nl>
  236. this.lexemList = [word]
  237. this.tokenList = [lexType]
  238. this.lineList = [lineNro]
  239. startPos = endPos
  240. isId = 0
  241.  
  242. if isId:
  243. this.lineList = [lineNro]
  244. wordPos = startPos
  245. if line[startPos:endPos] == "'":
  246. startPos = 1
  247. endPos = 1
  248. while line[startPos:endPos] != "'":
  249. startPos = 1
  250. endPos = 1
  251. startPos = 1
  252. endPos = 1
  253. if wordPos != startPos:
  254. this.lexemList = [line[wordPos 1:endPos-2]]
  255. this.tokenList = [6] #str
  256. continue
  257.  
  258. while line[startPos:endPos] in this.num:
  259. startPos = 1
  260. endPos = 1
  261. if wordPos != startPos:
  262. this.lexemList = [line[wordPos:endPos-1]]
  263. this.tokenList = [4] #int
  264. continue
  265.  
  266. #wordPos = startPos
  267. while line[startPos:endPos] in this.ch:
  268. startPos = 1
  269. endPos = 1
  270.  
  271. this.lexemList = [line[wordPos:endPos-1]]
  272. if this.lexemList[-1] in this.kw:
  273. this.tokenList = [5] #kw
  274. else:
  275. this.tokenList = [3] #id
  276. lineNro = 1
  277.  
  278. # -----
  279. # SEM
  280. # -----
  281. class sem:
  282. id = []
  283. type = []
  284. value = []
  285.  
  286. def add(this,id,type,value):
  287. this.id = [id]
  288. this.type = [type]
  289. this.value = [value]
  290.  
  291. def __str__(this):
  292. print "ID\tTYPE\tVALUE"
  293. for i in range(len(this.id)):
  294. print this.id[i],"\t",this.type[i],"\t",this.value[i]
  295. return ''
  296.  
  297. def search(this,id):
  298. for i in range(len(this.id)):
  299. if this.id[i] == id:
  300. return i
  301.  
  302. def getType(this,id):
  303. return this.type[this.search(id)]
  304.  
  305. def getVal(this,id):
  306. return this.value[this.search(id)]
  307.  
  308.  
  309. # -----
  310. # PL0
  311. # -----
  312. class PL0:
  313. asm
  314. semList = sem()
  315. varInit = 0x02BA
  316.  
  317. def __init__(this,symbol):
  318. this.asm = asm(symbol.fileName)
  319. io = '043088C2B402CD21C3B402B20DCD21B20ACD21C33D0080751FB22DE8E6FFB003E8DDFFB002E8D8FFB007E8D3FFB006E8CEFFB008E8C9FFC33D00007D0A50B402B22DCD2158F7D83D0A007C433D64007C313DE8037C1F3D10277C0DBA0000BB1027F7FB52E899FF58BA0000BBE803F7FB52E88CFF58BA0000BB6400F7FB52E87FFF58BA0000BB0A00F7FB52E872FF58E86EFFC3B90000B303B407CD213C0D7503E9F8003C087503E97E003C2D7503E9D7003C307CE33C397FDF2C3080FB0074D880FB02750A81F9000075043C0074C980FB03750B3C007505B300E90200B30181F9CC0C7FB381F934F37CAD88C7B80A00F7E93DF87F74083D0880740BE9100080FF077E0BE991FF80FF087E03E989FFB50088F980FB02740501C1E9030029C89188F8E8DBFEE970FF80FB037503E968FFB402B208CD21B220CD21B208CD2180FB007505B303E950FF80FB02750B81F900007505B303E940FF89C8B90A00BA00003D00007D09F7D8F7F9F7D8E90200F7F989C181F900007403E91DFF80FB027503E915FFB303E910FF80FB037403E908FFB402B22DCD21B302E9FDFE80FB037503E9F5FE80FB02750981F900007503E9E7FEE855FE89C8C3'
  320. vrs = '90'*256
  321. this.symbol = symbol
  322. this.asm.jmp(0x03BA) #JMP 03CD
  323. this.asm.script(io vrs)
  324.  
  325. def __str__(this):
  326. while this.symbol.next():
  327. print this.symbol,this.symbol.token
  328. return ''
  329.  
  330. def die(this,msg):
  331. import sys
  332. print msg
  333. sys.exit()
  334.  
  335. def check(this,s1,s2):
  336. if s1 in s2:
  337. this.symbol.next()
  338. return True
  339. else:
  340. this.error(s2)
  341.  
  342. def error(this,s2):
  343. import os
  344. this.asm.close()
  345. os.remove(this.symbol.fileName '.com')
  346. this.die('Se esperaba "' s2 '", no "' this.symbol.lexem '"' ' [linea ' str(this.symbol.line) ']')
  347.  
  348. def programa(this):
  349. this.symbol.next()
  350. this.bloque()
  351. if this.symbol.lexem=='.':
  352. #print 'Proceso exitoso!'
  353. this.asm.end()
  354. this.asm.close()
  355. else:
  356. this.error('.')
  357.  
  358. def bloque(this):
  359. if this.symbol.lexem == 'const': #CONST
  360. this.symbol.next()
  361. while True:
  362. this.semList.id = [this.symbol.lexem]
  363. this.semList.type = ['const']
  364. this.check(this.symbol.token, ('<id>')) #check controla y lee el proximo simbolo
  365. this.check(this.symbol.lexem, ('='))
  366. this.semList.value = [int2hex(this.symbol.lexem)]
  367. this.check(this.symbol.token, ('<int>'))
  368. if this.symbol.lexem != ',': break
  369. this.symbol.next()
  370.  
  371. this.check(this.symbol.lexem, (';'))
  372.  
  373. if this.symbol.lexem == 'var': #VAR
  374. this.symbol.next()
  375. while True:
  376. this.semList.add(this.symbol.lexem,'var',this.varInit)
  377. this.varInit = 2
  378. this.check(this.symbol.token, ('<id>'))
  379. if this.symbol.lexem != ',': break
  380. this.symbol.next()
  381. this.check(this.symbol.lexem, (';'))
  382.  
  383. while this.symbol.lexem == 'procedure': #PROCEDURE
  384. this.symbol.next()
  385. if this.symbol.token == '<id>':
  386. this.semList.add(this.symbol.lexem,'procedure',this.asm.pc)
  387. else:
  388. this.error('<id>')
  389. this.symbol.next()
  390. this.check(this.symbol.lexem, (';'))
  391. this.bloque()
  392. this.check(this.symbol.lexem, (';'))
  393. this.asm.ret()
  394.  
  395. this.asm.setFixup('init')
  396. this.proposicion()
  397.  
  398. def proposicion(this):
  399. lexem = this.symbol.lexem
  400. if this.symbol.token == '<id>': #ASSIGN
  401. semIndex = this.semList.search(lexem)
  402. if semIndex == None:
  403. this.error(this.symbol.token ' ' lexem)
  404.  
  405. if this.semList.type[semIndex] == 'var':
  406. this.symbol.next()
  407. this.check(this.symbol.lexem, (':='))
  408. this.expresion()
  409. this.asm.pop('AX')
  410. this.asm.mov(this.semList.value[semIndex],'AX')
  411. else:
  412. this.error('<var>')
  413.  
  414. elif lexem=='call': #CALL
  415. this.symbol.next()
  416. if this.symbol.token == '<id>':
  417. semIndex = this.semList.search(this.symbol.lexem)
  418. if semIndex == None:
  419. this.error(this.symbol.token ' ' this.symbol.lexem)
  420. this.symbol.next()
  421. if this.semList.type[semIndex] == 'procedure':
  422. this.asm.call(this.semList.value[semIndex])
  423. else:
  424. this.error('<id>')
  425.  
  426. elif lexem == 'begin': #BEGIN
  427. this.symbol.next()
  428. this.proposicion()
  429. while this.symbol.lexem == ';':
  430. this.symbol.next()
  431. this.proposicion()
  432. this.check(this.symbol.lexem, ('end'))
  433.  
  434. elif lexem == 'if': #IF
  435. this.symbol.next()
  436. this.condicion()
  437. this.check(this.symbol.lexem, ('then'))
  438. this.proposicion()
  439. this.asm.setFixup('if')
  440. elif lexem == 'readln': #READLN
  441. this.symbol.next()
  442. this.check(this.symbol.lexem, ('('))
  443. if this.symbol.token == '<id>':
  444. this.asm.call(0x196)
  445. this.asm.mov(this.semList.getVal(this.symbol.lexem),'AX')
  446. this.symbol.next()
  447. else:
  448. this.error('<id>')
  449.  
  450. while this.symbol.lexem == ',':
  451. this.symbol.next() #tmp
  452. this.check(this.symbol.token, ('<id>'))
  453. this.check(this.symbol.lexem, (')'))
  454.  
  455. elif lexem == 'write' or lexem == 'writeln': #WRITE & WRITELN
  456. this.symbol.next()
  457. if this.symbol.lexem == '(':
  458. this.symbol.next()
  459. if this.symbol.token == '<str>': #STRING
  460. this.asm.write(this.symbol.lexem)
  461. this.symbol.next()
  462. else: #EXPRESION
  463. this.expresion()
  464. this.asm.pop('AX')
  465. this.asm.call(0x117) #AX print nro
  466. while this.symbol.lexem == ',':
  467. this.symbol.next()
  468. if this.symbol.token == '<str>': #STRING
  469. this.asm.write(this.symbol.lexem)
  470. this.symbol.next()
  471. else: #EXPRESION
  472. this.expresion()
  473. this.asm.pop('AX')
  474. this.asm.call(0x117)
  475. this.check(this.symbol.lexem, (')'))
  476. if lexem=='writeln':
  477. this.asm.call(0x10C)
  478.  
  479. elif lexem == 'while': #WHILE
  480. this.symbol.next()
  481. this.asm.fixup = [this.asm.pc]
  482. this.condicion()
  483. this.check(this.symbol.lexem, ('do'))
  484. this.proposicion()
  485. this.asm.jmp(this.asm.setFixup('while'))
  486.  
  487. elif lexem == 'for': #FOR
  488. this.symbol.next()
  489. lexem = this.symbol.lexem
  490. this.asignacion()
  491. this.asm.fixup = [this.asm.pc] # for begin
  492. this.condicionFor(lexem)
  493. this.check(this.symbol.lexem, ('do'))
  494. this.proposicion()
  495. semIndex = this.semList.search(lexem)
  496. this.asm.increment(this.semList.value[semIndex])
  497. this.asm.jmp(this.asm.setFixup('while')) # end
  498.  
  499. def condicionFor(this,lexem):
  500. semIndex = this.semList.search(lexem)
  501. if semIndex == None:
  502. this.error(this.symbol.token ' ' lexem)
  503. else:
  504. this.asm.mov('[AX]',this.semList.value[semIndex])
  505. this.asm.push('AX')
  506.  
  507. op = '<='
  508. this.check(this.symbol.lexem, ('to'))
  509. this.expresion()
  510. this.asm.pop('AX')
  511. this.asm.pop('BX')
  512. this.asm.cmp('AX','BX')
  513. this.asm.op(op)
  514. this.asm.fixup = [this.asm.pc]
  515. this.asm.jmp(0) #fake jump
  516.  
  517. def asignacion(this):
  518. lexem = this.symbol.lexem
  519. this.check(this.symbol.token, ('<id>'))
  520. semIndex = this.semList.search(lexem)
  521. if semIndex == None:
  522. this.error(this.symbol.token ' ' lexem)
  523.  
  524. if this.semList.type[semIndex] == 'var':
  525. this.check(this.symbol.lexem, (':='))
  526. this.expresion()
  527. this.asm.pop('AX')
  528. this.asm.mov(this.semList.value[semIndex],'AX')
  529. else:
  530. this.error('<var>')
  531.  
  532. def condicion(this):
  533. if this.symbol.lexem == 'odd': #ODD
  534. op = this.symbol.lexem
  535. this.symbol.next()
  536. else:
  537. this.expresion()
  538. op = this.symbol.lexem
  539. this.check(this.symbol.lexem, ('=','<>','<','<=','>','>='))
  540. this.expresion()
  541. this.asm.pop('AX')
  542. if op != 'odd':
  543. this.asm.pop('BX')
  544. this.asm.cmp('AX','BX')
  545. this.asm.op(op)
  546. this.asm.fixup = [this.asm.pc]
  547. this.asm.jmp(0) #fake jump
  548.  
  549. def expresion(this):
  550. op = this.symbol.lexem
  551. if op == ' ': #PLUS
  552. this.symbol.next()
  553. elif op == '-':
  554. this.symbol.next()
  555.  
  556. this.termino()
  557. if op == '-':
  558. this.asm.pop('AX')
  559. this.asm.neg('AX')
  560. this.asm.push('AX')
  561. while this.symbol.lexem in (' ','-'):
  562. op = this.symbol.lexem
  563. this.check(op, (' ','-'))
  564. this.termino()
  565. if op==' ':
  566. this.asm.pop('AX')
  567. this.asm.pop('BX')
  568. this.asm.add('AX','BX')
  569. this.asm.push('AX')
  570. else:
  571. this.asm.script('585B9329D850')
  572.  
  573. def termino(this):
  574. this.factor()
  575. while this.symbol.lexem in ('*','/'):
  576. op = this.symbol.lexem
  577. this.check(op, ('*','/'))
  578. this.termino()
  579. if op == '*':
  580. this.asm.mul()
  581. else:
  582. this.asm.div()
  583.  
  584. def factor(this):
  585. if this.symbol.token == '<id>':
  586. semIndex = this.semList.search(this.symbol.lexem)
  587. if semIndex == None:
  588. this.error(this.symbol.token ' ' this.symbol.lexem)
  589. if this.semList.type[semIndex] == 'const':
  590. this.asm.mov('AX',this.semList.value[semIndex])
  591. else:
  592. this.asm.mov('[AX]',this.semList.value[semIndex])
  593. this.asm.push('AX')
  594. this.symbol.next()
  595. elif this.symbol.token == '<int>': #INT
  596. this.asm.mov('AX',int(this.symbol.lexem))
  597. this.asm.push('AX')
  598. this.symbol.next()
  599. elif this.symbol.lexem == '(':
  600. this.symbol.next() #tmp
  601. this.expresion()
  602. this.check(this.symbol.lexem, (')'))
  603. else:
  604. this.error('<id> o <int> o (<expresion>)')
  605.  
  606. import sys
  607. import os
  608.  
  609. #print sys.argv[1]
  610. symbol = Lex(sys.argv[1])
  611. syntax = PL0(symbol)
  612. syntax.programa()
  613. os.system(sys.argv[1] '.com')
  614. #print syntax.semList
  615. #print syntax.asm.all
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement