#!/usr/bin/env python3 import sys import ply.yacc as yacc from ply.lex import LexToken # Get the token map from the lexer. This is required. from lexer import tokens # Error rule for syntax errors def p_error(p: LexToken): if p: print(f"Unexpected {repr(p.value)} on line {p.lineno}") else: print("Unexpected end of file.") def p_program(p): '''program : instruction_list | empty''' pass def p_empty(p): '''empty :''' pass def p_inss(p): '''instruction_list : instruction_list line | line ''' if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[2]] # print(f"INSes: {len(p)}") # print(f" {p[1]}") # if len(p) > 2: # print(f" {p[2]}") pass def p_inss2(p): '''instruction_list2 : line instruction_list2 | line ''' if len(p) == 2: p[0] = [p[1]] else: p[0] = [p[1]] + p[2] print(f"INSes2: {len(p)}") print(f" {p[1]}") if len(p) > 2: print(f" {p[2]}") pass def p_line(p): '''line : instruction NL | NL ''' if len(p) == 2: pass else: p[0] = p[1] def p_instruction(p): '''instruction : noarg | onearg | twoarg | jumpdest | invalid_arg ''' print(f"INS: {p[1]}") p[0] = p[1] pass def p_jumpdest(p): '''jumpdest : SYMBOL COLON''' p[0] = (p[1], ) def p_twoarg(p): '''twoarg : op REG COMMA argument COMMA argument''' p[0] = (*p[1], p[2], p[4], p[6]) pass def p_argument(p): '''argument : number | REG | SYMBOL ''' pass def p_onearg(p): '''onearg : op REG COMMA argument''' p[0] = (*p[1], p[2], p[4], None) pass def p_noarg(p): '''noarg : op''' p[0] = (*p[1], None, None, None) pass def p_invalid_arg(p): '''invalid_arg : op argument''' print(f"Invalid opcode, destination missing: {p[1:]}") sys.exit(1) pass def p_op(p): '''op : OP DOT JUMP | OP ''' if len(p) == 2: p[0] = (p[1], None) else: p[0] = (p[1], p[3]) def p_number(p): '''number : NUMBER | HEXNUMBER ''' p[0] = p[1] parser = yacc.yacc()