Лексер не определяет, является ли (
частью кортежа. Он просто распознает (
. Это все, что нужно сделать.
Решить, что означает тот или иной символ, - работа парсера. Парсер будет использовать грамматическое описание языка для различения 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)
с выражением в скобках, так как выражения в скобках (как и другие значения) не могут сразу следовать за выражением без какого-либо оператора.