Dalam dunia pemrograman dan ilmu komputer, istilah parser muncul cukup sering. Meskipun terdengar teknis, konsep dasarnya relatif sederhana: parser adalah sebuah komponen atau program yang memecah, menganalisis, dan menginterpretasikan data atau kode sumber menjadi struktur yang lebih mudah dipahami. Pada dasarnya, parser bertugas mengubah string (barisan karakter) menjadi representasi internal yang dapat diproses lebih lanjut oleh program lain.
Parser bekerja dalam dua tahap utama:
if, while), identifier, operator (+, -), atau literal.Terdapat beberapa tipe parser yang umum dipakai, masingmasing memiliki kelebihan dan kelemahan:
Parser jenis ini memulai proses penguraian dari simpul akar (root) dan bergerak ke bawah mengikuti aturan grammar. Contoh paling terkenal adalah recursivedescent parser. Kelebihan: mudah dipahami dan diimplementasikan. Kekurangan: sulit menangani grammar yang ambigu atau memiliki left recursion.
Berbeda dengan topdown, parser bottomup memulai dari token paling kiri dan menggabungkan mereka ke dalam struktur yang lebih besar hingga mencapai akar. Contohnya adalah LR parser ( termasuk SLR, LALR, dan canonical LR ). Kelebihan: dapat menangani grammar yang lebih kompleks. Kekurangan: implementasinya biasanya lebih rumit.
Untuk format data yang relatif sederhana (misalnya CSV, log, atau konfigurasi), sering kali digunakan regular expression untuk mengekstrak nilai tanpa membangun pohon sintaks. Ini bukanlah parser fullfeatured, namun cukup efektif untuk kebutuhan tertentu.
Banyak bahasa pemrograman menyediakan library khusus untuk parsing, seperti ANTLR, Bison, Boost.Spirit (C++), atau parsy (Python). Library ini biasanya menyertakan generator parser yang menerima grammar dalam format tertentu dan menghasilkan kode parser secara otomatis.
Parser adalah komponen kunci dalam banyak aplikasi:
JSON (JavaScript Object Notation) memiliki format yang sederhana sehingga dapat diparse dengan mudah menggunakan fungsi bawaan JSON.parse(). Berikut contoh penggunaannya:
const jsonString = '{"nama":"Andi","umur":30,"hobi":["membaca","berenang"]}';try { const data = JSON.parse(jsonString); console.log(data.nama); // Output: Andi console.log(data.hobi[1]); // Output: berenang} catch (e) { console.error('JSON tidak valid:', e);} Pada contoh di atas, JSON.parse() berperan sebagai parser yang mengubah string JSON menjadi objek JavaScript.
Berikut contoh miniparser yang membaca ekspresi aritmetika sederhana (1 + 2 * 3) menggunakan modul re untuk tokenisasi dan fungsi rekursif untuk parsing.
import re# 1. TokenisasiTOKEN_SPEC = [ ('NUMBER', r'\d+(\.\d*)?'), # Integer or decimal number ('PLUS', r'\+'), # Plus sign ('MINUS', r'-'), # Minus sign ('TIMES', r'\*'), # Multiplication ('DIVIDE', r'/'), # Division ('LPAREN', r'\('), # Left parenthesis ('RPAREN', r'\)'), # Right parenthesis ('SKIP', r'[ \t]+'), # Skip spaces and tabs ('MISMATCH', r'.'), # Any other character]TOK_REGEX = '|'.join('(?P<%s>%s)' % pair for pair in TOKEN_SPEC)def tokenize(code): for mo in re.finditer(TOK_REGEX, code): kind = mo.lastgroup value = mo.group() if kind == 'NUMBER': value = float(value) if '.' in value else int(value) elif kind == 'SKIP': continue elif kind == 'MISMATCH': raise SyntaxError(f'Karakter tidak dikenal: {value}') yield (kind, value)# 2. Parser (recursivedescent)class Parser: def __init__(self, tokens): self.tokens = list(tokens) self.pos = 0 def peek(self): return self.tokens[self.pos] if self.pos < len(self.tokens) else (None, None) def advance(self): self.pos += 1 def expr(self): # expr term ((PLUS|MINUS) term)* node = self.term() while True: tok_type, _ = self.peek() if tok_type in ('PLUS', 'MINUS'): op = tok_type self.advance() right = self.term() node = (op, node, right) else: break return node def term(self): # term factor ((TIMES|DIVIDE) factor)* node = self.factor() while True: tok_type, _ = self.peek() if tok_type in ('TIMES', 'DIVIDE'): op = tok_type self.advance() right = self.factor() node = (op, node, right) else: break return node def factor(self): # factor NUMBER | LPAREN expr RPAREN tok_type, value = self.peek() if tok_type == 'NUMBER': self.advance() return ('NUM', value) elif tok_type == 'LPAREN': self.advance() node = self.expr() if self.peek()[0] != 'RPAREN': raise SyntaxError('Tanda tutup kurung hilang') self.advance() return node else: raise SyntaxError('Token tidak diharapkan')def evaluate(node): if node[0] == 'NUM': return node[1] op, left, right = node if op == 'PLUS': return evaluate(left) + evaluate(right) if op == 'MINUS': return evaluate(left) - evaluate(right) if op == 'TIMES': return evaluate(left) * evaluate(right) if op == 'DIVIDE': return evaluate(left) / evaluate(right)# Contoh penggunaancode = "2 + 3 * (4 - 1)"tokens = tokenize(code)parser = Parser(tokens)ast = parser.expr()print('AST:', ast)print('Hasil:', evaluate(ast)) Contoh di atas memperlihatkan proses tokenisasi, pembuatan pohon sintaks (AST), dan evaluasi hasilnya. Meskipun sederhana, ia sudah mencerminkan prinsip dasar sebuah parser.
Parser adalah jembatan antara data mentah dan struktur yang dapat diproses. Dengan memecah teks menjadi token dan menyusunnya sesuai grammar, parser memungkinkan komputer memahami bahasa pemrograman, format data, atau bahkan bahasa alami pada tingkat tertentu. Baik Anda sedang membangun compiler, mengolah file konfigurasi, atau menulis aplikasi yang harus membaca JSON, pemahaman tentang cara kerja parser akan sangat membantu dalam menciptakan solusi yang efisien dan dapat diandalkan.
Jika Anda tertarik memperdalam topik ini, berikut beberapa sumber yang direkomendasikan:
