0

Мой текущий проект (на самом деле это игрушечный язык) - это функциональный язык сценариев. И я хотел бы разрешить вызов метода без необходимости скобок для группировки.Вызов метода без круглых скобок

sum 1 2 3 

Вот улов, и я не уверен, что это обычная вещь или нет, если честно. Но на моем языке метод может определять параметры, которые ведут идентификатор.

def (a) plus (b) 
    a + b 
end 

Какой бы в конечном итоге

1 plus 2 

Но что, если бы я использовал переменные/функции для этих параметров? Как бы я знать, что, например, «плюс» метод, который я звоню и не «GetNum» в следующем

getnum plus 2 

и еще более, как я знаю, что GetNum является параметром плюс а не наоборот? (Это просто, проверяя сигнатуры параметров?) EDIT: Я просто повторил сам. К сожалению.

И, наконец, должен ли лексер делать что-то особенное для такого рода вещей? Если да, то как бы узнать, какой из них назвать «methodtoken»? Или лексер просто накачивает вещи, такие как «Identifiertoken» и «literaltoken», и оставляет их до времени выполнения, чтобы понять, что это вызов метода?

+1

Хуже того, что, если 'getnum' и' plus' являются * обеими функциями? В общем, звучит так, будто у вас будет двусмысленная грамматика. –

+1

Что я имею в виду, если у вас есть 'def f (x)' и 'def (x) g', то что должно' f g' разрешать? –

+0

Я думаю, что вложенные вызовы функций должны были бы использовать круглые скобки (или какой-либо другой набор символов группировки), если только он не может определить, основываясь на том, что getnum не принимает никаких параметров. – RoyalPotato

ответ

3

Ваша проблема - проблема синтаксического анализа. Однако, большая проблема заключается в том, что ваш язык не syntax-directed. Это означает, что синтаксис вашего языка не соответствует его семантике. Например, рассмотрим следующую программу на вашем языке:

f g 

Это может быть разобран в одном из двух способов, f применяется к g или g применительно к f. Однако синтаксис языка не делает очевидным, что будет создано одно из двух деревьев синтаксического анализа. Как правильно сказано в «EJP», «это больше, чем проблема синтаксического анализа, это проблема семантической обратной связи».

Итак, как вам сделать ваш язык синтаксисом? Давайте возьмем вызов от объектно-ориентированных языков.Например:

1 plus 2 

В объектно-ориентированный язык, как JavaScript, это может быть записано как:

Number.prototype.plus = function (n) { 
 
    return this + n; 
 
}; 
 

 
var sum = (1) .plus (2); 
 

 
alert(sum);

Сравнивая синтаксис двух языков, которые мы видим, что единственным крупным разница - это точка перед идентификатором plus. Это все, что нам нужно, чтобы ваш язык синтаксически ориентирован. Теперь, вы можете иметь нормальные функции:

.sum 1 2 3 

Однако, вы также можете иметь синтаксические направлены функции инфиксные:

1 .plus 2 

Теперь, следующие выражения уже не неоднозначные:

.f g 
f .g 

Однако вам все же потребуются скобки для устранения неоднозначности некоторых выражений:

(.getnum) .plus 2 

Это связано с тем, что getnum вызывается до применения plus. Это означает plus(getnum(), 2). С другой стороны, getnum .plus 2 будет означать plus(getnum, 2), что было бы ошибкой, потому что вы не можете применить plus к функции.

Подумайте о точке как о «применении» вашего языка. Использование точки даже позволяет иметь функции высшего порядка:

1 .(true .plus-or-minus) 2 

Это то же самое, как plus-or-minus(true)(1, 2).

Другой альтернативой является цитировать данные, подобные им в Лиспе. Этот синтаксис намного менее шумный:

  1. Приложение с нормальной функцией, sum 1 2 3.
  2. Приложение функции Infix, 1 plus 2.
  3. Идентификаторы кодов, f 'g средства f, применяемые к g и 'f g средства g применяются к f.
  4. Приложение с котировкой, 'getnum' plus 2, где 'getnum' неявно цитируется.
  5. Приложение для функции более высокого порядка, 1 (true plus-or-minus) 2.

Надеюсь, что это поможет.

+0

Итак, в основном период/кавычки указывают, кто мы звоним? – RoyalPotato

+0

... И когда требуется (Как во вложенных вызовах функций), мы можем просто отказаться от использования круглых скобок? – RoyalPotato

+0

Кроме того, извините, наверное, кажущееся невежественным. Язык-дизайн - это одна из многих областей компьютерной науки и программного обеспечения, которые меня интересуют, поэтому, хотя я еще не учился в колледже, мне показалось, что я с ним поиграю;). Не говорите мне, что я неопытный/необразованный, чтобы сделать это, потому что это мое время, и я могу тратить его, но я считаю нужным: p. – RoyalPotato

1

Что вы ищете, это operator precendence и operator associativity. В случае вызова метода без круглых скобок пустое пространство является оператором приложения функции.

Mixfix expressions затрудняет это, но в конце концов вам просто нужно разработать некоторые правила для вашего языка и запретить некоторые неоднозначные выражения. В вашем примере вы объявите plus в качестве инфиксного оператора и дадите все операторы infix более высоким приоритетом, чем префиксные операторы.

Это работа анализатора, а не токенизатор или лексер.

+0

Итак, тогда моему лексеру разрешат идти, вперед и разбор идентификатора/литерала в таких местах? На данный момент это то, как моя текущая реализация стоит. Но потом я остановился и задался вопросом, как я решаю вызов метода (просто притворяйтесь, что круглые скобки и запятые - это пробелы), как этот «метод (метод2 (123), somevariable)». Единственный способ, которым я мог подумать, - потратить время на проверку достоверности параметров/параметров. Это единственный способ? Я также чувствую, что полностью не хватает логического ярлыка, который я мог бы использовать. – RoyalPotato

+2

@RoyalPotato Lexers не разбираются. Вам сказали три отдельных человека, что это проблема синтаксического анализа, а не проблема лексического анализа. – EJP

+0

@RoyalPotato: Ваш лексер не должен знать, является ли это вызовом метода или нет. – Bergi