Токенизация строки, которая может быть кортежем или чем-то еще - PullRequest
0 голосов
/ 11 апреля 2020

Я создаю лексер (токенизатор) и синтаксический анализатор для базового языка программирования c, и одна из особенностей языка, о которой я думал, - это возможность разбирать строку в кортеж или выражение. Проблема в том, что я застрял в том, как по строке определить, должен ли он быть кортежем или нет. Сначала я подумал, что могу просто проверить, начинается ли строка с «(» и заканчивается «)», а также содержит «,» где-то внутри, но проблема с этим подходом состоит в том, что выражения также могут содержать кортежи.

Есть ли канонический или принятый способ определить, является ли строка кортежем?

1 Ответ

0 голосов
/ 11 апреля 2020

Лексер не определяет, является ли ( частью кортежа. Он просто распознает (. Это все, что нужно сделать.

Решить, что означает тот или иной символ, - работа парсера. Парсер будет использовать грамматическое описание языка для различения guish между кортежами, выражениями в скобках, списками параметров и всеми другими возможными значениями скобок.

Точная грамматика, конечно, зависит от синтаксиса языка, но простой пример может быть: (слабо адаптированный от Python, но пропускающий много синтаксиса)

expr  : term             /* Additive operators, lowest precedence */
      | expr '+' term
      | expr '-' term
term  : factor           /* Multiplicative operators */
      | term '*' factor
      | term '/' factor
factor: postfix          /* Unary prefix operators */
      | '-' factor
      | '+' factor
post  : unit             /* Postfix operators: call and subscript */
      | post '(' opt_expr_list ')'
      | postfix '[' expr ']'
unit  : CONSTANT         /* Values */
      | IDENTIFIER
      | tuple
      | '(' expr ')'     /* Parenthesised expression */
tuple : '(' ')'          /* Empty tuple */
      | '(' expr ',' ')' /* Single-element tuple eg. (1, ) */
      | '(' expr ',' expr_list opt_comma ')'
                         /* Two or more elements */
opt_comma
      : %empty
      | ','
expr_list
      : expr
      | expr_list ',' expr
opt_expr_list
      : %empty
      | expr_list

Обратите внимание, что синтаксис был тщательно разработан, чтобы позволить кортежам отличаться от выражений в скобках. Соглашение, которое используется, состоит в том, что кортежи могут записываться с , после последнего элемента, если кортеж не имеет ровно один элемент, и в этом случае запятая является обязательной. Это немного требует разбивки синтаксиса для кортежей на три произведения, но это не особенно сложно.

Обратите также внимание на то, что не нужно было перепрыгивать через этот конкретный h oop при описании грамматики для вызовов функций. Невозможно спутать (3) в sin(3) с выражением в скобках, так как выражения в скобках (как и другие значения) не могут сразу следовать за выражением без какого-либо оператора.

...