You have already implemented a lexical analyzer in Assignment #1 and a parser to recognize grammatical rules in Assignment #2. In this assignment, you will be adding semantics to the design of a small programming language to help implement blockchain. The goal of blockchain is to allow digital information to be recorded and distributed, but not edited. In this way, a blockchain is a foundation for immutable records of transactions that cannot be altered, deleted, or destroyed. The semantics that you must implement in this assignment is as follows: 1. Each time a new blockchain is created, you must extract attributes and verifies if each attribute has a valid type. Returns false if at least one is invalid or returns true otherwise. 2. When the add operator (keyword) is used, the data must be stored in a dictionary. 3. When errors are detected, the parser must describe the error, including the line of the code where it occurs. 4. When arithmetic expressions are used, the parser will implement the corresponding arithmetic operations. For simplicity purposes, the blockchain only will store arithmetic expressions and strings. import ply.lex as lex import ply.yacc as yacc tokens = ( 'ID', 'BLOCK', 'VAR', 'ADD', 'PRINT', 'VIEW', 'RUN', 'MINE', 'EXPORT', 'STRING', 'INT', 'LONG', 'FLOAT', 'LIST', 'TUPLE', 'DICT', 'NUMBER', 'ASSIGN', 'TYPEASSIGN', 'SEPARATOR', 'LPAREN', 'RPAREN', 'NE', 'LT', 'GT', 'LE', 'GE', 'PLUS', 'MINUS', 'STAR', 'SLASH', 'PCT', 'COMMENT', 'WHITESPACE' ) t_ASSIGN = r'\=' t_TYPEASSIGN = r'\:' t_SEPARATOR = r'\,' t_LPAREN = r'\(' t_RPAREN = r'\)' t_NE = r'\!=' t_LT = r'\<' t_GT = r'\>' t_LE = r'\<=' t_GE = r'\>=' t_PLUS = r'\+' t_MINUS = r'\-' t_STAR = r'\*' t_SLASH = r'\/' t_PCT = r'\%' t_ignore_COMMENT = r'\#.' t_ignore_WHITESPACE = r'\s+' keywords = { 'BLOCK': 'KEYWORD', 'VAR': 'KEYWORD', 'ADD': 'KEYWORD', 'PRINT': 'KEYWORD', 'VIEW': 'KEYWORD', 'RUN': 'KEYWORD', 'MINE': 'KEYWORD', 'EXPORT': 'KEYWORD', 'STR':'KEYWORD', 'INT': 'KEYWORD', 'LONG': 'KEYWORD', 'FLOAT': 'KEYWORD', 'LIST': 'KEYWORD', 'TUPLE': 'KEYWORD', 'DICT':'KEYWORD', } tokens1 = ['ID', 'BLOCK','VAR','ADD','PRINT','VIEW','RUN','MINE','EXPORT','STRING','LONG','FLOAT','L IST','TUPLE','DICT','NUMBER','ASSIGN','TYPEASSIGN','SEPARATOR','LPAREN','RPARE N','NE','LT','GT','LE','GE','PLUS','MINUS','STAR','SLASH', 'PCT', 'COMMENT','WHITESPACE']\ + list(keywords.values()) # dictionary to store values values = {} def t_KEYWORD(t): r'DEF | VAR | INT | IF | ELSE' t.type = keywords.get(t.value, 'KEYWORD') return t def t_ID(t): r'[a-zA-Z_][a-zA-Z_0-9]*' t.type = keywords.get(t.value, 'ID') return t def t_NUM(t): r'[0-9]+' t.type = keywords.get(t.value, 'INT') return t def t_COMMENT(t): r'//.' t.type = keywords.get(t.value, 'COMMENT') pass def t_newline(t): r'\n+' t.lexer.lineno += len(t.value) def t_error(t): print("Illegal character '%s'" % t.value[0]) t.lexer.skip(1) def p_block(p): """ block : BLOCK ID ASSIGN LPAREN attributes RPAREN | ADD ID ASSIGN LPAREN new_atts RPAREN | PRINT I.