Таблица 2 направлений (строка <-> токен) в разборе
Я определил хеш-таблицу keyword_table
хранить все ключевые слова моего языка. Вот часть кода:
(* parser.mly *)
%token CALL CASE CLOSE CONST
...
reserved_identifier:
| CALL { "Call" }
| CASE { "Case" }
| CLOSE { "Close" }
| CONST { "Const" }
...
(* lexer.mll *)
{let hash_table list =
let tbl = Hashtbl.create (List.length list) in
List.iter (fun (s, t) -> Hashtbl.add tbl (lowercase s) t) list;
tbl
let keyword_table = hash_table [
"Call", CALL; "Case", CASE; "Close", CLOSE; "Const", CONST;
... ]}
rule token = parse
| lex_identifier as li
{ try Hashtbl.find keyword_table (lowercase li)
with Not_found -> IDENTIFIER li }
Поскольку ключевых слов много, я действительно хотел бы как можно больше избегать повторного кода.
В parser.mly
, Кажется, что %token CALL CASE ...
не может быть упрощено, потому что каждый токен должен быть определен явно. Однако для reserved_identifier
часть, возможно ли вызвать функцию для возврата строки из токена вместо жесткого кодирования каждой строки?
Таким образом, это говорит о том, что, вероятно, хеш-таблица не подходит для этой цели. Какая структура данных является лучшим выбором для поиска с обеих сторон (мы предполагаем, что каждый ключ с обеих сторон уникален)? В результате мы хотим реализовать find_0 table "Call"
возвращает токен CALL
(используется в lexer.mll
) а также find_1 table CALL
возвращается "Call"
(используется в parser.mly
).
Кроме того, если это table
можно определить, где я должен поставить его так, чтобы parser.mly
можно использовать это?
1 ответ
Вы можете получить строку, пока вы находитесь в лексере, именно в той точке, которая соответствует токену (например, Lexing.lexeme
). Слишком поздно пытаться получить его в парсере. Мы не хотим, чтобы поток токенов сохранял все строки в памяти, поскольку это сильно увеличило бы потребление памяти (на практике большинству токенов никогда не требуется их строковое представление).
Почему бы вам не построить обратную таблицу из значений ключевых слов (или значений токенов) в строку, в то же время создавая первое отображение? hash_table
может быть переименован в hash_tables
и верните две обратные карты.
Вероятно, его нужно определить в парсере, если вы хотите, чтобы он был виден как парсером, так и лексером.