Токенизация многоточия в языке программирования для избежания плавающих точек - PullRequest
0 голосов
/ 28 февраля 2012

Я разрабатываю язык, на котором хочу использовать .. для определения целочисленного диапазона. Проблема в том, что 0..10 является токенизированным, как поплавки 0. и .10.

Как мне разрешить поддержку этого синтаксиса с помощью flex? Это просто, как сделать 0. недопустимым с плавающей точкой?

Ответы [ 2 ]

2 голосов
/ 09 марта 2012

9 марта 2012 г.:

Если вы не хотите делать 0. недопустимым с плавающей точкой, вы можете использовать конечный контекст Lex:

[0-9]+[.]/[^.]  { /* recognize <digits>. only if not followed by another . */ }

Так что это правило будетотклонено из-за несоответствия конечного контекста, и токен совпадает только как целочисленная константа.Тогда следующий ввод - .., который может быть распознан как токен-точка-точка.

20 марта 2012 г .:

Мне нужно будет сейчас воспользоваться моим собственным советом!

Регрессия от добавления поддержки с плавающей запятой:

$ ./txr -v -l -c '@(bind a (1..3))'
spec:
(((bind a (1.0 0.3))))  # oops, should be (cons 1 3)
bindings:
nil
(a 1.0 0.3)

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

Мое предлагаемое решение не будет таким простым для применения, потому что токен с плавающей запятой сопоставляется с одним сложным регулярным выражением, где совпадение для десятичной точки находится где-то посередине, перед некоторыми необязательными цифрами ираздел экспоненты.Конечный контекст lex может быть только в конце.

Необходимо изменить выражение, чтобы оно не распознавало 123. как действительный токен, и распознавать 123. с дополнительным правилом.который имеет конечный контекст.

Рабочее исправление из фактического кода:

diff --git a/parser.l b/parser.l
index d8fd915..449cc14 100644
--- a/parser.l
+++ b/parser.l
@@ -149,8 +149,12 @@ static wchar_t num_esc(char *num)
 %option noinput

 SYM     [a-zA-Z0-9_]+
-NUM     [+\-]?[0-9]+
-FLO     [+\-]?([0-9]+[.]?[0-9]*|[0-9]*[.][0-9]+)([eE][+-]?[0-9]+)?
+SGN     [+\-]
+EXP     [eE][+\-]?[0-9]+
+DIG     [0-9]
+NUM     {SGN}?{DIG}+
+FLO     {SGN}?{DIG}*[.]({DIG}+{EXP}?|{EXP})
+FLODOT  {SGN}?{DIG}+[.]
 BSCHR   [a-zA-Z0-9!$%&*+\-<=>?\\^_~]
 BSYM    {BSCHR}({BSCHR}|#)*
 NSCHR   [a-zA-Z0-9!$%&*+\-<=>?\\^_~/]
@@ -190,7 +194,8 @@ UONLY   {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U}
   return NUMBER;
 }

-<SPECIAL,NESTED,BRACED>{FLO} {
+<SPECIAL,NESTED,BRACED>{FLODOT}/[^.] |
+<SPECIAL,NESTED,BRACED>{FLO}         {
   val str = string_own(utf8_dup_from(yytext));

   if (yy_top_state() == INITIAL

Таким образом, плавающие константы теперь имеют две формы:

  1. необязательный знак, за которым следуют ноль или более цифр и десятичная точка, за которой следует либо показатель степени, либо цифры и, возможно, показатель степени.

  2. цифр, за которыми следует точка, с последующим контекстом, утверждающим, что следующаяchar - это не точка.

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

PATTERN1 |
PATTERN2 |
...
PATTERNN { action; }

Шаблоны могут индивидуально иметь конечный контекст или нет.

PS Если я передумал и запретил 123., я просто удалил все следы FLODOT.

Ошибка:

Этот код хаs для обращения:

<SPECIAL,NESTED,BRACED>{FLODOT}/[^.] |
<SPECIAL,NESTED,BRACED>{FLO}         {

Т.е.

<SPECIAL,NESTED,BRACED>{FLO}         |
<SPECIAL,NESTED,BRACED>{FLODOT}/[^.] {

Похоже, flex рассматривает сопоставленный конечный контекст для части длины совпадения.Т.е. 3.0 считается совпадением из трех символов в случае FLODOT, хотя извлеченный токен равен 3..Таким образом, мы должны поставить этот случай на второе место, чтобы 3.0 вышло через FLO match.

1 голос
/ 28 февраля 2012

Это действительно зависит от того, как вы определяете свой лексер.Если вы определяете многоточие как токен, состоящий из двух периодов, а также правильно определяете числа с плавающей запятой, конфликт не должен возникать.Просто убедитесь, что токен для многоточия определен первым в вашей спецификации.И да, 0. должно быть недопустимым с плавающей точкой.

...