[docs]classTokenizer:"""Lexical analyzer for tokenizing logical expressions."""TOKEN_MAP={"AND":r"\∧|\bAND\b","OR":r"\∨|\bOR\b","IMPLIES":r"→|\bIMPLIES\b","IFF":r"↔|\bIFF\b","NOT":r"¬|\bNOT\b","FORALL":r"∀|\bFORALL\b","EXISTS":r"∃|\bEXISTS\b","LPAREN":r"\(","RPAREN":r"\)","VAR":r"[a-zA-Z][a-zA-Z0-9_]*",}
[docs]@staticmethoddeftokenize(expression:str)->List[str]:"""Tokenizes a logical expression into components."""token_regex="|".join(f"(?P<{key}>{value})"forkey,valueinTokenizer.TOKEN_MAP.items())tokens=[]formatchinre.finditer(token_regex,expression):tokens.append((match.lastgroup,match.group()))returntokens
[docs]@staticmethoddefvalidate_syntax(tokens:List[str])->bool:"""Performs basic syntax validation."""ifnottokens:returnFalsebalance=0# Track parenthesis balancelast_token=Nonefortoken_type,_token_valueintokens:iftoken_type=="LPAREN":balance+=1eliftoken_type=="RPAREN":balance-=1ifbalance<0:returnFalseif(last_tokenandlast_token==token_type):# No two same token types in sequence (except VAR)returnFalselast_token=token_typereturnbalance==0# Ensure all parentheses are closed