micro_asm.py (4508:837161d544c3) | micro_asm.py (4512:cfa340f9d12a) |
---|---|
1# Copyright (c) 2003-2005 The Regents of The University of Michigan 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: redistributions of source code must retain the above copyright 7# notice, this list of conditions and the following disclaimer; 8# redistributions in binary form must reproduce the above copyright --- 183 unchanged lines hidden (view full) --- 192 ('asm', 'exclusive'), 193 ('params', 'exclusive'), 194) 195 196reserved_map = { } 197for r in reserved: 198 reserved_map[r.lower()] = r 199 | 1# Copyright (c) 2003-2005 The Regents of The University of Michigan 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: redistributions of source code must retain the above copyright 7# notice, this list of conditions and the following disclaimer; 8# redistributions in binary form must reproduce the above copyright --- 183 unchanged lines hidden (view full) --- 192 ('asm', 'exclusive'), 193 ('params', 'exclusive'), 194) 195 196reserved_map = { } 197for r in reserved: 198 reserved_map[r.lower()] = r 199 |
200# Ignore comments |
|
200def t_ANY_COMMENT(t): 201 r'\#[^\n]*(?=\n)' | 201def t_ANY_COMMENT(t): 202 r'\#[^\n]*(?=\n)' |
202 #print "t_ANY_COMMENT %s" % t.value | |
203 204def t_ANY_MULTILINECOMMENT(t): 205 r'/\*([^/]|((?<!\*)/))*\*/' | 203 204def t_ANY_MULTILINECOMMENT(t): 205 r'/\*([^/]|((?<!\*)/))*\*/' |
206 #print "t_ANY_MULTILINECOMMENT %s" % t.value | |
207 | 206 |
207# A colon marks the end of a label. It should follow an ID which will 208# put the lexer in the "params" state. Seeing the colon will put it back 209# in the "asm" state since it knows it saw a label and not a mnemonic. |
|
208def t_params_COLON(t): 209 r':' 210 t.lexer.begin('asm') | 210def t_params_COLON(t): 211 r':' 212 t.lexer.begin('asm') |
211 #print "t_params_COLON %s" % t.value | |
212 return t 213 | 213 return t 214 |
215# An "ID" in the micro assembler is either a label, directive, or mnemonic 216# If it's either a directive or a mnemonic, it will be optionally followed by 217# parameters. If it's a label, the following colon will make the lexer stop 218# looking for parameters. |
|
214def t_asm_ID(t): 215 r'[A-Za-z_]\w*' 216 t.type = reserved_map.get(t.value, 'ID') 217 t.lexer.begin('params') | 219def t_asm_ID(t): 220 r'[A-Za-z_]\w*' 221 t.type = reserved_map.get(t.value, 'ID') 222 t.lexer.begin('params') |
218 #print "t_asm_ID %s" % t.value | |
219 return t 220 | 223 return t 224 |
225# If there is a label and you're -not- in the assember (which would be caught 226# above), don't start looking for parameters. |
|
221def t_ANY_ID(t): 222 r'[A-Za-z_]\w*' 223 t.type = reserved_map.get(t.value, 'ID') | 227def t_ANY_ID(t): 228 r'[A-Za-z_]\w*' 229 t.type = reserved_map.get(t.value, 'ID') |
224 #print "t_ANY_ID %s" % t.value | |
225 return t 226 | 230 return t 231 |
232# Parameters are a string of text which don't contain an unescaped statement 233# statement terminator, ie a newline or semi colon. |
|
227def t_params_PARAMS(t): 228 r'([^\n;]|((?<=\\)[\n;]))+' 229 t.lineno += t.value.count('\n') 230 t.lexer.begin('asm') | 234def t_params_PARAMS(t): 235 r'([^\n;]|((?<=\\)[\n;]))+' 236 t.lineno += t.value.count('\n') 237 t.lexer.begin('asm') |
231 #print "t_params_PARAMS %s" % t.value | |
232 return t 233 | 238 return t 239 |
240# Braces enter and exit micro assembly |
|
234def t_INITIAL_LBRACE(t): 235 r'\{' 236 t.lexer.begin('asm') | 241def t_INITIAL_LBRACE(t): 242 r'\{' 243 t.lexer.begin('asm') |
237 #print "t_INITIAL_LBRACE %s" % t.value | |
238 return t 239 240def t_asm_RBRACE(t): 241 r'\}' 242 t.lexer.begin('INITIAL') | 244 return t 245 246def t_asm_RBRACE(t): 247 r'\}' 248 t.lexer.begin('INITIAL') |
243 #print "t_asm_RBRACE %s" % t.value | |
244 return t 245 | 249 return t 250 |
251# At the top level, keep track of newlines only for line counting. |
|
246def t_INITIAL_NEWLINE(t): 247 r'\n+' 248 t.lineno += t.value.count('\n') | 252def t_INITIAL_NEWLINE(t): 253 r'\n+' 254 t.lineno += t.value.count('\n') |
249 #print "t_INITIAL_NEWLINE %s" % t.value | |
250 | 255 |
256# In the micro assembler, do line counting but also return a token. The 257# token is needed by the parser to detect the end of a statement. |
|
251def t_asm_NEWLINE(t): 252 r'\n+' 253 t.lineno += t.value.count('\n') | 258def t_asm_NEWLINE(t): 259 r'\n+' 260 t.lineno += t.value.count('\n') |
254 #print "t_asm_NEWLINE %s" % t.value | |
255 return t 256 | 261 return t 262 |
263# A newline or semi colon when looking for params signals that the statement 264# is over and the lexer should go back to looking for regular assembly. |
|
257def t_params_NEWLINE(t): 258 r'\n+' 259 t.lineno += t.value.count('\n') 260 t.lexer.begin('asm') | 265def t_params_NEWLINE(t): 266 r'\n+' 267 t.lineno += t.value.count('\n') 268 t.lexer.begin('asm') |
261 #print "t_params_NEWLINE %s" % t.value | |
262 return t 263 264def t_params_SEMI(t): 265 r';' 266 t.lexer.begin('asm') | 269 return t 270 271def t_params_SEMI(t): 272 r';' 273 t.lexer.begin('asm') |
267 #print "t_params_SEMI %s" % t.value | |
268 return t 269 270# Basic regular expressions to pick out simple tokens 271t_ANY_LPAREN = r'\(' 272t_ANY_RPAREN = r'\)' 273t_ANY_SEMI = r';' 274t_ANY_DOT = r'\.' 275 --- 22 unchanged lines hidden (view full) --- 298 299def p_rom_or_macros_0(t): 300 'rom_or_macros : rom_or_macro' 301 302def p_rom_or_macros_1(t): 303 'rom_or_macros : rom_or_macros rom_or_macro' 304 305def p_rom_or_macro_0(t): | 274 return t 275 276# Basic regular expressions to pick out simple tokens 277t_ANY_LPAREN = r'\(' 278t_ANY_RPAREN = r'\)' 279t_ANY_SEMI = r';' 280t_ANY_DOT = r'\.' 281 --- 22 unchanged lines hidden (view full) --- 304 305def p_rom_or_macros_0(t): 306 'rom_or_macros : rom_or_macro' 307 308def p_rom_or_macros_1(t): 309 'rom_or_macros : rom_or_macros rom_or_macro' 310 311def p_rom_or_macro_0(t): |
306 '''rom_or_macro : rom_block''' | 312 '''rom_or_macro : rom_block 313 | macroop_def''' |
307 | 314 |
308def p_rom_or_macro_1(t): 309 '''rom_or_macro : macroop_def''' 310 311# A block of statements 312def p_block(t): 313 'block : LBRACE statements RBRACE' 314 block = Block() 315 block.statements = t[2] 316 t[0] = block 317 | |
318# Defines a section of microcode that should go in the current ROM 319def p_rom_block(t): 320 'rom_block : DEF ROM block SEMI' 321 if not t.parser.rom: 322 print_error("Rom block found, but no Rom object specified.") 323 raise TypeError, "Rom block found, but no Rom object was specified." 324 for statement in t[3].statements: 325 handle_statement(t.parser, t.parser.rom, statement) --- 16 unchanged lines hidden (view full) --- 342 curop = t.parser.macro_type(t[3]) 343 except TypeError: 344 print_error("Error creating macroop object.") 345 raise 346 for statement in t[4].statements: 347 handle_statement(t.parser, curop, statement) 348 t.parser.macroops[t[3]] = curop 349 | 315# Defines a section of microcode that should go in the current ROM 316def p_rom_block(t): 317 'rom_block : DEF ROM block SEMI' 318 if not t.parser.rom: 319 print_error("Rom block found, but no Rom object specified.") 320 raise TypeError, "Rom block found, but no Rom object was specified." 321 for statement in t[3].statements: 322 handle_statement(t.parser, t.parser.rom, statement) --- 16 unchanged lines hidden (view full) --- 339 curop = t.parser.macro_type(t[3]) 340 except TypeError: 341 print_error("Error creating macroop object.") 342 raise 343 for statement in t[4].statements: 344 handle_statement(t.parser, curop, statement) 345 t.parser.macroops[t[3]] = curop 346 |
347# A block of statements 348def p_block(t): 349 'block : LBRACE statements RBRACE' 350 block = Block() 351 block.statements = t[2] 352 t[0] = block 353 |
|
350def p_statements_0(t): 351 'statements : statement' 352 if t[1]: 353 t[0] = [t[1]] 354 else: 355 t[0] = [] 356 357def p_statements_1(t): --- 7 unchanged lines hidden (view full) --- 365 t[0] = t[1] 366 367# A statement can be a microop or an assembler directive 368def p_content_of_statement_0(t): 369 '''content_of_statement : microop 370 | directive''' 371 t[0] = t[1] 372 | 354def p_statements_0(t): 355 'statements : statement' 356 if t[1]: 357 t[0] = [t[1]] 358 else: 359 t[0] = [] 360 361def p_statements_1(t): --- 7 unchanged lines hidden (view full) --- 369 t[0] = t[1] 370 371# A statement can be a microop or an assembler directive 372def p_content_of_statement_0(t): 373 '''content_of_statement : microop 374 | directive''' 375 t[0] = t[1] 376 |
377# Ignore empty statements |
|
373def p_content_of_statement_1(t): 374 'content_of_statement : ' 375 pass 376 377# Statements are ended by newlines or a semi colon 378def p_end_of_statement(t): 379 '''end_of_statement : NEWLINE 380 | SEMI''' 381 pass 382 | 378def p_content_of_statement_1(t): 379 'content_of_statement : ' 380 pass 381 382# Statements are ended by newlines or a semi colon 383def p_end_of_statement(t): 384 '''end_of_statement : NEWLINE 385 | SEMI''' 386 pass 387 |
388# Different flavors of microop to avoid shift/reduce errors |
|
383def p_microop_0(t): 384 'microop : labels ID' 385 microop = Microop() 386 microop.labels = t[1] 387 microop.mnemonic = t[2] 388 t[0] = microop 389 390def p_microop_1(t): --- 12 unchanged lines hidden (view full) --- 403 404def p_microop_3(t): 405 'microop : ID PARAMS' 406 microop = Microop() 407 microop.mnemonic = t[1] 408 microop.params = t[2] 409 t[0] = microop 410 | 389def p_microop_0(t): 390 'microop : labels ID' 391 microop = Microop() 392 microop.labels = t[1] 393 microop.mnemonic = t[2] 394 t[0] = microop 395 396def p_microop_1(t): --- 12 unchanged lines hidden (view full) --- 409 410def p_microop_3(t): 411 'microop : ID PARAMS' 412 microop = Microop() 413 microop.mnemonic = t[1] 414 microop.params = t[2] 415 t[0] = microop 416 |
417# Labels in the microcode |
|
411def p_labels_0(t): 412 'labels : label' 413 t[0] = [t[1]] 414 415def p_labels_1(t): 416 'labels : labels label' 417 t[1].append(t[2]) 418 t[0] = t[1] --- 7 unchanged lines hidden (view full) --- 426 427def p_label_1(t): 428 'label : EXTERN ID COLON' 429 label = Label() 430 label.is_extern = True 431 label.text = t[2] 432 t[0] = label 433 | 418def p_labels_0(t): 419 'labels : label' 420 t[0] = [t[1]] 421 422def p_labels_1(t): 423 'labels : labels label' 424 t[1].append(t[2]) 425 t[0] = t[1] --- 7 unchanged lines hidden (view full) --- 433 434def p_label_1(t): 435 'label : EXTERN ID COLON' 436 label = Label() 437 label.is_extern = True 438 label.text = t[2] 439 t[0] = label 440 |
441# Directives for the macroop |
|
434def p_directive_0(t): 435 'directive : DOT ID' 436 directive = Directive() 437 directive.name = t[2] 438 t[0] = directive 439 440def p_directive_1(t): 441 'directive : DOT ID PARAMS' --- 35 unchanged lines hidden --- | 442def p_directive_0(t): 443 'directive : DOT ID' 444 directive = Directive() 445 directive.name = t[2] 446 t[0] = directive 447 448def p_directive_1(t): 449 'directive : DOT ID PARAMS' --- 35 unchanged lines hidden --- |