# 2010s 構文解析 class Parser: def __init__(self, text): # 空白で分割して字句(トークン)のリストを作成 # 実際は1文字ずつ解析しますが、図の定義に合わせ簡略化しています self.tokens = self._lexer(text) self.pos = 0 self.token = self.gettoken() def _lexer(self, text): # 記号の周りに空白を入れて分割しやすくする for symbol in ['=', '+', '-', '*', '/', ';']: text = text.replace(symbol, f' {symbol} ') return text.split() def gettoken(self): """字句解析関数: 次のトークンの種類を返す""" if self.pos >= len(self.tokens): return '$' # プログラム記述の終わり raw_token = self.tokens[self.pos] self.pos += 1 if raw_token == 'short': return 'S' if raw_token == 'long': return 'L' if raw_token.isdigit(): return 'N' if raw_token.isalnum(): return 'I' # 識別子 return raw_token # '=', '+', '-', '*', '/', ';' はそのまま # --- 構文解析関数群 --- def bun(self): """<文> の解析 (図3のエに基づき作成)""" if self.token == 'I': # <識別子> self.token = self.gettoken() else: return -1 # 【空欄 エ】 token と '=' が等しい if self.token == '=': self.token = self.gettoken() else: return -1 if self.shiki() == -1: return -1 if self.token == ';': self.token = self.gettoken() else: return -1 return 0 def shiki(self): """<式> の解析 (図3のオに基づき作成)""" # 【空欄 オ】 kou() がエラー(-1)を返すなら if self.kou() == -1: return -1 while self.token == '+' or self.token == '-': if self.token == '+': self.token = self.gettoken() if self.kou() == -1: return -1 elif self.token == '-': self.token = self.gettoken() if self.kou() == -1: return -1 else: return -1 return 0 def kou(self): """<項> の解析 (図2の定義に基づき作成)""" if self.因子() == -1: return -1 while self.token == '*' or self.token == '/': self.token = self.gettoken() if self.因子() == -1: return -1 return 0 def 因子(self): """<因子> の解析""" if self.token == 'N' or self.token == 'I': self.token = self.gettoken() return 0 return -1 # --- 実行テスト --- code = "aa = aa + 2 * b1 ;" parser = Parser(code) result = parser.bun() if result == 0 and parser.token == '$': print(f"解析成功: '{code}' は文法的に正しいです。") else: print(f"解析失敗: '{code}' に文法エラーがあります。")