Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];

Вниз

Что большее зло: goto или while true do ?   Найти похожие ветки 

 
Дмитрий С ©   (2010-05-12 09:24) [0]

Subj. И то и то обычно считается злом, но что хуже/лучше и почему? И вообще откуда это взялось?


 
RWolf ©   (2010-05-12 09:40) [1]

из статьи Дейкстры «О вреде оператора GOTO».


 
Dimka Maslov ©   (2010-05-12 09:40) [2]

Из-за отсутствия "цикла c выходом посередине"


 
Ega23 ©   (2010-05-12 09:47) [3]


> И то и то обычно считается злом


Почему?
Ну с goto я ещё как-то могу понять, но почему while true?


 
icWasya ©   (2010-05-12 09:50) [4]

Не плыви по течению, не плыви против течения - плыви туда, куда тебе нужно.©


 
RWolf ©   (2010-05-12 09:51) [5]


> Ну с goto я ещё как-то могу понять, но почему while true?

считается, что, если в тексте программы не практикуется выход из циклов через Break и т. п., такой код читать легче.


 
boriskb ©   (2010-05-12 10:07) [6]


> Ega23 ©   (12.05.10 09:47) [3]
>Почему?

Насколько я помню, это идет из теории программирования. А именно - доказательства безошибочности алгоритма.
С указанными конструкциями доказать невозможно, без них возможно.

P.S.
Если паять меня подвела - старшие товарищи меня поправят :))


 
12 ©   (2010-05-12 10:13) [7]

откуда пошло - Э.Дейкстра “Go To Statement Considered Harmful”

Goto обычно можно переписать
<инициализация цикла>
WHILE  <условие ограничения поиска> AND (<условие окончания поиска>)  DO
END WHILE

проблема, имхо, в искусственности приема
писать надо
<инициализация цикла>
<условие ограничения поиска>
<условие окончания поиска>

причем <инициализация цикла> обычно дублирует <условие ограничения поиска> и/или <условие окончания поиска>
следовательно, исправив в одном месте, приходится исправлять и в другом

Ученик спросил Учителя:
- Учитель, плыть ли мне по жизни по течению или же против течения?
- Плыви туда, куда тебе надо.


 
Игорь Шевченко ©   (2010-05-12 10:18) [8]

boriskb ©   (12.05.10 10:07) [6]


> Насколько я помню, это идет из теории программирования.
> А именно - доказательства безошибочности алгоритма.
> С указанными конструкциями доказать невозможно, без них
> возможно.


Да, именно так. А про читаемость и проч. уже последователи пророка придумали, чтобы количество правоверных увеличивать.


 
RWolf ©   (2010-05-12 10:42) [9]

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


 
Leonid Troyanovsky ©   (2010-05-12 10:51) [10]


> boriskb ©   (12.05.10 10:07) [6]

> А именно - доказательства безошибочности алгоритма.

Наверное, конечности времени работы, или отсутствия зацикливания.
Кста, ЕМНИП, ссылки вперед допустимы.

--
Regards, LVT.


 
Игорь Шевченко ©   (2010-05-12 10:52) [11]

RWolf ©   (12.05.10 10:42) [9]


> и что, действительно можно доказать безошибочность?


как все запущено...можно


 
Юрий Зотов ©   (2010-05-12 11:06) [12]

> RWolf ©   (12.05.10 10:42) [9]

Насколько я понимаю, компиляторы именно это и делают, в той или иной степени. Но безошибочность алгоритма еще не означает безошибочности программы.


 
Mystic ©   (2010-05-12 11:10) [13]

Имхо, зло это бездумное следование догмам :)

Кстати, в Ada даже есть специальная конструкция для бесконечного цикла:


loop
 // ...
end loop;


Лично я большой сторонник бесконечных циклов, что делает код проще модифицируемым и однотипным.

Ну а goto в умеренных количествах использовать можно. Если имеется нетривиальная алгоритмическая логика, то вряд ли использование кучи флагов для организации нужного goto вряд ли делает код понятнее :)


 
Mystic ©   (2010-05-12 11:15) [14]

> и что, действительно можно доказать безошибочность?

Смотри в сторону функциональных языков (типа Haskell), там это иногда используется. Проблемы с доказательством больше создает императивность языка :)


 
Ega23 ©   (2010-05-12 11:18) [15]

loop
// ...
end loop;


Такое и Visual Basic вроде как есть.


 
Суслик__   (2010-05-12 11:47) [16]

я использую иногда и то и другое.
не вижу проблем.


 
Palladin ©   (2010-05-12 11:56) [17]

Суслик походу и второй пароль забыл )


 
brother ©   (2010-05-12 12:00) [18]

> Суслик походу и второй пароль забыл )

почему?


 
Palladin ©   (2010-05-12 12:01) [19]

уже два прочерка в конце ника


 
brother ©   (2010-05-12 12:06) [20]

так он не зарегеный, там пасов же нет?


 
Anatoly Podgoretsky ©   (2010-05-12 12:09) [21]

> Mystic  (12.05.2010 11:10:13)  [13]

loop = while true


 
Anatoly Podgoretsky ©   (2010-05-12 12:09) [22]

> Palladin  (12.05.2010 11:56:17)  [17]

Ты Суслика видишь, а он есть.


 
brother ©   (2010-05-12 12:11) [23]

> Ты Суслика видишь

я вижу - набор байт...


 
Anatoly Podgoretsky ©   (2010-05-12 12:11) [24]

> Palladin  (12.05.2010 12:01:19)  [19]

Надо звездочки рисовать, как на самолетах.


 
Плохиш ©   (2010-05-12 12:17) [25]


> И то и то обычно считается злом, но что хуже/лучше и почему?

Когда коту делать нечего он яйца чешет.


 
Mystic ©   (2010-05-12 12:22) [26]

> loop = while true

В Ada такой синтаксис:


 loop while I >= 0
   I := I - 1;
 end loop;


просто while необязателен.


 
oxffff ©   (2010-05-12 12:25) [27]

Отладчик в D2010 не хочет останавливаться на строчке

  while TRUE do  <- Здесь не брякается
  ..........
  end


 
oxffff ©   (2010-05-12 12:28) [28]

Вот кусок моего кода

while TRUE do
   case PascalLRAnalizer.DoOnSymbol(PASCAL_GRAMMAR.FinalTerminal,nil,0) of
        STATUS_CONTINUE:;
         STATUS_PASS:break;
....
        end
except
end;

Брякается только на строчке case в 2010, поскольку условие не проверяется. Оно вроде и понятно, но как то неудобно.


 
Anatoly Podgoretsky ©   (2010-05-12 15:16) [29]

> oxffff  (12.05.2010 12:25:27)  [27]

do перенесил на другую строку.


 
Игорь Шевченко ©   (2010-05-12 15:43) [30]

oxffff ©   (12.05.10 12:28) [28]


>  case PascalLRAnalizer


Англичане пишут Analyser


 
oxffff ©   (2010-05-12 15:55) [31]


> Игорь Шевченко ©   (12.05.10 15:43) [30]
> oxffff ©   (12.05.10 12:28) [28]
>
>
> >  case PascalLRAnalizer
>
>
> Англичане пишут Analyser


Исправил. :)


 
Mystic ©   (2010-05-12 18:11) [32]

> Англичане пишут Analyser

Ага, и colour.


 
Mystic ©   (2010-05-12 18:16) [33]

Кстати, вместо while true do всегда упорно пишу repeat until False;

И сейчас задумался, какую бы константу в своем модуля объявить для значения False?

например,


const
 Apocalypto = False;

repeat
 // ..
until Apocalypto;


Есть выражение "до нових вiникiв", но как-то писать


repeat
 // ...
until NewBroom;


не звучит... until TurningBlue?


 
turbouser ©   (2010-05-12 18:31) [34]


> Mystic ©   (12.05.10 18:16) [33]

until MorkovkinoZagovenie


 
Игорь Шевченко ©   (2010-05-12 18:34) [35]


> например,
>
>
> const
>  Apocalypto = False;
>
> repeat
>  // ..
> until Apocalypto;


кандидат на увольнение :)


 
Дмитрий С ©   (2010-05-12 19:04) [36]

лингва подсказывает:
until further_orders
until it_comes_to_the_push

Особенно понравилось:
until hell_freezes_over


 
_Юрий ©   (2010-05-12 20:46) [37]

until CancerWhistleOnHill ?


 
[true]TRIx ©   (2010-05-12 21:14) [38]

while true do  это же круто! как писать, если надо зациклить выполение?


 
Petr V. Abramov ©   (2010-05-12 22:53) [39]


> Mystic ©   (12.05.10 12:22) [26]


> loop
>  // ...
> end loop;


ага, а в PL/SQL (про который честно сказано, что он несколько содран с ada)
есть

loop
 // do smth
 exit when условие
 // do smth
end loop

в зависимости от того, где поставить exit when, получаем while ... do, repeat ... until и на что фантазии хватит.


 
GrayFace ©   (2010-05-13 08:35) [40]

И то, и другое - добро.

Mystic ©   (12.05.10 11:10) [13]
Ну а goto в умеренных количествах использовать можно. Если имеется нетривиальная алгоритмическая логика, то вряд ли использование кучи флагов для организации нужного goto вряд ли делает код понятнее :)

Слабо представляю такую логику.

Mystic ©   (12.05.10 18:16) [33]
Лучше
const
 True = False;

repeat
until True;


while true do читается гораздо проще, чем двойное отрицание в until false.


 
Mystic ©   (2010-05-13 20:34) [41]


> Petr V. Abramov ©   (12.05.10 22:53) [39]


Ну exit when в Ada выходит не только из циклов, но и из блоков begin..end. Т. е. можно так:


declare
 I: Integer;
begin
 -- Do something
 exit when I < 0;
end;


Также допустимы именованные блоки и циклы, так что можно писать


 Something_Difficult:
 declare
   -- variables
 begin
   Inner_Loop:
   loop
     -- Calculations
     exit Inner_Loop when I > 0;
     exit Something_Difficult when I = 0;
     exit when I < 0; -- выходим ил цикла
   end loop Inner_Loop;
 end Something_Difficult;


 
Mystic ©   (2010-05-13 20:36) [42]


> Слабо представляю такую логику.


Любой конечный автомат.


 
Mystic ©   (2010-05-13 20:45) [43]

Опять же, что-нить вроде такого


 repeat

   {
     А тут море всяких вложенных циклов и прочей радости,
     но у любой момент возможно либо принятие Current,
     либо мы можем определить, что он нам не подходит.
     Соответственно goto FindOk или goto Next выглядят
     вполне нормально
   }
 
FindOk:
   List.Add(Current);
Next:
   Current := GetNextExelemt(Current);

 until Current = nil;


Альтернативный вариант такой, но я не могу сказать, что он такой уж легко читаемый + производительность :)


 repeat

   try

     try
       {
         А тут море всяких вложенных циклов и прочей радости
       }
     except
       on E: EAccept do ;
     end;
 
     List.Add(Current);

   except
     on E: EReject do;
   end;

   Current := GetNextExelemt(Current);

 until Current = nil;



 
RWolf ©   (2010-05-14 00:55) [44]


> Mystic ©   (13.05.10 20:36) [42]
> Любой конечный автомат.
>

Конечные автоматы, кроме самых простых, лучше описывать в терминах предметной области — набор состояний, таблица переходов, — чем городить лес из goto. Так и понятнее, и багов меньше.
Простые автоматы прекрасно моделируются оператором case State of …, опять же, в goto необходимости нет.


 
RWolf ©   (2010-05-14 01:02) [45]

чтобы не быть голословным — на днях попался на глаза примерчик: http://rybalko.nm.ru/html/soft/dfmconv.dhtml
см. pars.pas


 
Игорь Шевченко ©   (2010-05-14 01:03) [46]

RWolf ©   (14.05.10 00:55) [44]

Не всегда и все так просто, как кажется.


 
Mystic ©   (2010-05-14 01:36) [47]


> Простые автоматы прекрасно моделируются оператором case
> State of …, опять же, в goto необходимости нет.


Конечно нет. Вполне можно написать так:


while (state != FINAL)
 switch(state)
 {
   case CASE_1:
     if (something)
     {
       state = CASE_3;
       break;      
     }
     state := CASE_2;
     break;
   // .........
 }


Вот только чем это лучше простого???


CASE_1:
 if (something) goto CASE_3;
 goto CASE_2;

...

FINAL:
 ...


Как по мне разница только в том, что в первом случае нет goto, а второй вариант лаконичнее.

Фокус в том, что любую программу с использование goto можно переписать без использования goto. Но встречаются случаи, когда потом мысленно, для того, чтобы разобраться, все равно надо приводить ее к виду с goto. Тогда возникает вопрос: смысл???


> чтобы не быть голословным — на днях попался на глаза примерчик:
>  http://rybalko.nm.ru/html/soft/dfmconv.dhtml


У меня LEX + YACC и не такие таблицы генерил. Вот только разбираться в этом... Ты серьезно думаешь, то этот код лучше понимаем, только потому что там нет goto???

const
 ParsTable : array [0..8,0..3] of smallint = (
           { "  A  #  1}
{за текст 0}( 1, 0, 4, 0),
{нач стр  1}( 3, 2, 2, 2),
{стр      2}( 3, 2, 2, 2),
{кон стр  3}( 1, 0, 6, 0),
{нач 0код 4}( 6, 6, 6, 5),
{0код     5}( 1, 0, 5, 5),
{нач 3код 6}( 6, 6, 6, 7),
{3код     7}( 1, 0, 7, 7),
{ошибка   8}( -1, -1, -1, -1)
 );

{ Events handlers }
procedure WriteChar(var s, code: string; ch: char); forward;
procedure BuffChar(var s, code: string; ch: char); forward;
procedure e31(var s, code: string; ch: char); forward;
procedure e36(var s, code: string; ch: char); forward;
procedure AddCode(var s, code: string; ch: char); forward;
procedure e51(var s, code: string; ch: char); forward;
procedure e50(var s, code: string; ch: char); forward;
procedure e55(var s, code: string; ch: char); forward;
procedure BuffCode(var s, code: string; ch: char); forward;
procedure e91(var s, code: string; ch: char); forward;
procedure e90(var s, code: string; ch: char); forward;
procedure e99(var s, code: string; ch: char); forward;
procedure NOP(var s, code: string; ch: char); forward;
procedure ERR(var s, code: string; ch: char); forward;

{ Event conditions }
const
 EventTable: array [0..8,0..3] of TEventProc = (
         {"   A  #  1}
{за текст}( WriteChar,  WriteChar,      NOP,            WriteChar),
{нач стр }( WriteChar,  WriteChar,      WriteChar,      WriteChar),
{стр     }( BuffChar,   WriteChar,      WriteChar,      WriteChar),
{кон стр }( e31,        e31,            e36,            e31),
{нач 0код}( ERR,        ERR,            ERR,            AddCode),
{0код    }( e51,        e50,            e55,            AddCode),
{нач 3код}( ERR,        ERR,            ERR,            AddCode),
{3код    }( e91,        e90,            e99,            AddCode),
{ошибка  }( NOP,        NOP,            NOP,            NOP)
 );


 
Германн ©   (2010-05-14 01:51) [48]

Интересно какой по счёту сей холивар на ДМ по поводу goto? И как часто они возникают? И нет ли сезонной зависимости?
Про while true и repeat until false тут обсуждения гораздо реже, но тоже интересна сезонная статистика.
:)


 
RWolf ©   (2010-05-14 09:03) [49]


> Ты серьезно думаешь, то этот код лучше понимаем, только
> потому что там нет goto???

он понятнее потому, что в одной таблице на виду все состояния и учтены все варианты перехода. А goto тут просто не нужно.


 
RWolf ©   (2010-05-14 09:15) [50]


> Как по мне разница только в том, что в первом случае нет
> goto, а второй вариант лаконичнее.Фокус в том, что любую
> программу с использование goto можно переписать без использования
> goto. Но встречаются случаи, когда потом мысленно, для того,
>  чтобы разобраться, все равно надо приводить ее к виду с
> goto. Тогда возникает вопрос: смысл???

смысл в том, что читающему исходник проще разобраться с алгоритмом.
Если написано while state != FINAL на несколько экранов, то читателю понятно, что управление не покинет этот цикл до состояния FINAL. С goto это неочевидно.


 
pasha_golub ©   (2010-05-14 09:45) [51]


> RWolf ©   (14.05.10 09:03) [49]


> он понятнее потому, что в одной таблице на виду все состояния
> и учтены все варианты перехода.

Ха :) На виду говорите? У меня вот после Yacc"a размер модуля 6,46Mb. Таблички себе представляете? ;) Так что, после некоторого порога уже пофигу реализация. Всё равно оком не окинешь.


 
RWolf ©   (2010-05-14 09:52) [52]

> [51]
безусловно, инструменты выбираются по задаче.


 
Омлет ©   (2010-05-14 10:20) [53]

until false быстрее while true


 
RWolf ©   (2010-05-14 10:46) [54]


> Омлет ©   (14.05.10 10:20) [53]

одинаково. простой jmp.


 
Mystic ©   (2010-05-14 11:15) [55]


> он понятнее потому, что в одной таблице на виду все состояния
> и учтены все варианты перехода.


Оно то на виду, только все достаточно однотипно. Все равно как ни крути, для понимания работы автомата нужно описание всех состоний. А тут оно размыто: часть дается таблицей, часть функцией переходов. Чтобы понять этот исходник, мне все равно приходится преобразовывать его в голове к чему-то вроде


 STATE_READ_STRING:
   if Input <> 0 then
   begin
     WriteChar();
     goto STATE_READ_STRING;
   end;

   WriteBuff();
   goto STATE_END_OF_STRING;


Ну и потом я просто проверяю отдельно каждое состояние у понимаю принцип работы автомата в целом.

Еще один минус демонстрируют функции переходов из пятого состояния (предлагаю поискать десять отличий).


procedure e51(var s, code: string; ch: char);
begin
 if IsUnicode(code) then begin
   BuffCode(s,code,ch);
   WriteChar(s,code,cQuote);
   WriteString(s,popall);
 end else begin
   if Length(buffer)<>0 then begin
     WriteChar(s,code,cQuote);
     WriteString(s,popall);
     WriteChar(s,code,cQuote);
   end;
   WriteString(s,"#"+code);
   code:= "";
   WriteChar(s,code,cQuote);
 end;
end;

procedure e50(var s, code: string; ch: char);
begin
 if IsUnicode(code) then begin
   BuffCode(s,code,ch);
   WriteChar(s,code,cQuote);
   WriteString(s,popall);
   WriteChar(s,code,cQuote); // <----  This is difference!!!
 end else begin
   if Length(buffer)<>0 then begin
     WriteChar(s,code,cQuote);
     WriteString(s,popall);
     WriteChar(s,code,cQuote);
   end;
   WriteString(s,"#"+code);
   code:= "";
 end;
 WriteChar(s,code,ch);
end;


Весьма характерная черта конечный автоматов в том, что обработка состояния происходит однотипно, за исключением мелких деталей на входе. А в табличном представлении с этим есть проблемы.

Еще можно посмотреть, как этот автомат изментся в случае, когда нужны будут еще строки с шестнадцатеричными кодами: например #$0A. В случае goto нам надо будет дописать одно-два новых состояний и забыть. А тут, нам надо разбить вход A-Z a-z _ на две группы: A-F и все остальное. Которое будет заметно толко для шестнадцатеричных констант. И т. д. и т. п.

Ну и в целом, 319 строк только для того, чтобы разпарсить (неполностью) Delphi строку? Честно говоря, многовато...


 
RWolf ©   (2010-05-14 12:12) [56]

> Оно то на виду, только все достаточно однотипно. Все равно
> как ни крути, для понимания работы автомата нужно описание
> всех состоний. А тут оно размыто: часть дается таблицей,
>  часть функцией переходов.


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

Ну и потом я просто
> проверяю отдельно каждое состояние у понимаю принцип работы
> автомата в целом.


> Еще один минус демонстрируют функции переходов из пятого состояния

Согласен, исходник не идеален, я его привёл просто для предметного обсуждения.

>  Весьма характерная черта
> конечный автоматов в том, что обработка состояния происходит
> однотипно, за исключением мелких деталей на входе. А в табличном
> представлении с этим есть проблемы.


Это поправимо — разбиением на подфункции, скажем.

> Еще можно посмотреть,
>  как этот автомат изментся в случае, когда нужны будут еще
> строки с шестнадцатеричными кодами: например #$0A. В случае
> goto нам надо будет дописать одно-два новых состояний и
> забыть. А тут, нам надо разбить вход A-Z a-z _ на две группы:
>  A-F и все остальное. Которое будет заметно толко для
> шестнадцатеричных констант.


Добавится один столбец для входного символа $, один для A-F и одна строка для нового состояния «принимаю 16-ичную константу». Обработчики событий останутся те же, с поправкой на распознавание 16-ичных чисел.
Т. е. исходник легко модифицируется и не становится при этом запутанным.


 
Mystic ©   (2010-05-14 13:16) [57]


> Т. е. исходник легко модифицируется и не становится при
> этом запутанным.


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


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


Избыточно представлены. А ошибиться с номером состояния, в которое надо переходить, раз плюнуть. И в этой толпе цифр разбираться что к чему крайне неприятно. С таким заданием автомата есть печальный опыт работы, после чего я плюнул на него, и стал использовать while State <> FINAL do case... Стало проще. А потом я пришел к выводы, что у меня те же goto получились, только в профиль, да еще и с лишним синтаксическим оверхедом.

Вот набросок того, как бы все эти 300 строк кода выглядели с goto:


ENTRY_POINT:
 Ch := ReadChar();
 if Ch = QUOTE goto INSIDE_QUOTAS;
 if Ch = SHARP goto CHAR_CODE;
 Fail("No string");

OUTSIDE_QUOTAS:
 Ch := ReadChar();

OUTSIDE_QUOTAS_WITH_CHAR:
 if Ch = QUOTE goto INSIDE_QUOTAS;
 if Ch = SHARP goto CHAR_CODE;
 // if Ch <> END_OF_STREAM then Fail("Extra characters");
 Result := JobDone();
 Exit;

INSIDE_QUOTAS:
 Ch := ReadChar();
 if Ch = QUOTA goto CLOSED_QUOTA;

INSIDE_QUOTAS_ACCEPT_CHAR:
 if Ch in [END_OF_STREAM, END_OF_LINE] then Fail("Unterminated string");
 WriteChar(Ch);
 goto INSIDE_QUOTAS;

CLOSED_QUOTA:
 Ch := ReadChar();
 if Ch = QUOTA goto INSIDE_QUOTAS_ACCEPT_CHAR;
 goto OUTSIDE_QUOTAS_WITH_CHAR;

CHAR_CODE:
 CharCode := 0;
 Ch := ReadChar();
 // if Ch = DOLLAR then goto CHAR_HEX_CODE_LOOP;

CHAR_CODE_LOOP:
 if NotDigit(Ch) then
 begin
   WriteChar(CharCode);
   goto OUTSIDE_QUOTAS_WITH_CHAR;
 end;
 CharCode := CharCode * 10 + Integer(Ch) - Integer("0");
 Ch := ReadChar();
 goto CHAR_CODE_LOOP;


 
RWolf ©   (2010-05-14 13:43) [58]

Звучит убедительно.

> Как по мне, такие таблицы должны генерить специальные тулзы.

Кстати, интересно было бы глянуть на этот же алгоритм в исполнении flex+yacc, re2c или другого лексера (сам пока только присматриваюсь к этим инструментам).


 
Mystic ©   (2010-05-14 14:21) [59]


> Кстати, интересно было бы глянуть на этот же алгоритм в
> исполнении flex+yacc, re2c или другого лексера (сам пока
> только присматриваюсь к этим инструментам).


Там там обычное регулярное выражение. Что стоит написать


(\^[A-Z]|["][^"]*?["]|#[0-9]+|#$[0-9A-Fa-f])+            
 begin
   ConstType := STRING_TYPE;
   ConstAsString := ParseString(yytext);
   return(CONST_VALUE);
 end;
               

А ParseString уже конечным автоматом закрыть. Мне так проще. С другой стороны, можно и там сверху прикрутить еще один LEX+YACC. Еще можно все завернуть в один единственный LEX+YACC, но там будет война с пробелами между :) Delphi не пропускает конструкцию

const XXX = "123" #13;

надо так:

const XXX = "123"#13;

+ потенциальные конфликты с интерпретацией ^


 
Andy BitOff ©   (2010-05-14 14:42) [60]


> Германн ©   (14.05.10 01:51) [48]
> но тоже интересна сезонная статистика.

Это к хаяму ;)


 
Омлет ©   (2010-05-14 15:41) [61]

> RWolf ©   (14.05.10 10:46) [54]
> > Омлет ©   (14.05.10 10:20) [53]одинаково. простой jmp.

Я имел в виду онтологический план. В repeat-until можно выйти на первой же итерации, даже не узнав, какое там условие цикла. А в while-do минимум 1 раз на условие наткнешься.


 
Anatoly Podgoretsky ©   (2010-05-14 16:06) [62]

> Омлет  (14.05.2010 15:41:01)  [61]

repeat-until легко залететь, это опасная ненужная конструкция. Всегда надо
использовать while. Единственная ее польза, что она не по Виртовски сделана,
многострочная, а не однострочная, в соотвествии с его идеологии.


 
GrayFace ©   (2010-05-14 20:19) [63]

Mystic ©   (13.05.10 20:45) [43]
Альтернативный вариант такой, но я не могу сказать, что он такой уж легко читаемый + производительность :)

Не, это уж слишком жесто. Я в этом случае всегда использую goto, но можно вынести то, что в скобках, во вложенную функцию.

Anatoly Podgoretsky ©   (14.05.10 16:06) [62]
repeat-until легко залететь, это опасная ненужная конструкция. Всегда надо
использовать while. Единственная ее польза, что она не по Виртовски сделана,
многострочная, а не однострочная, в соотвествии с его идеологии.

Так для того и сделана, залезать. В чем опастность, если 1 раз залезть точно надо? Ненужная - возможно.
А идеология, наоборот, Виртовская, только более новая - в Модуле и Обероне у него IF - END IF и т.п. (или как-то так)


 
Mystic ©   (2010-05-14 20:29) [64]


> А идеология, наоборот, Виртовская, только более новая -
> в Модуле и Обероне у него IF - END IF и т.п. (или как-то
> так)


Мне кажется, что верх выразительности паскалевского синтаксиса это адский синтаксис.


 
GrayFace ©   (2010-05-14 20:33) [65]

А я никогда серьезным парсингом не занимался, но мне кажется, что лучше формальные грамматики без всяких автоматов.


 
Mystic ©   (2010-05-14 20:47) [66]

> GrayFace ©   (14.05.10 20:33) [65]

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

Плюс проблема с разделителями и комментариями. Например, если я создам что-то следующее:


 \^[A-Z]               return(STRING_CONST_PART)
 "[^"]*"               return(STRING_CONST_PART)
 #[0-9]+               return(STRING_CONST_PART)
 #$[A-Fa-f0-9]+        return(STRING_CONST_PART)


И потом


 STRING_CONST  : STRING_CONST_PART
               | STRING_CONST_PART STRING_CONST


то я не уверен в отсутствии конфликтов, плюс между частями строки возможны пробелы и комментарии (которые устраняет lexer). Так что проще все эти части вынести в одно большое регулярное выражение, и потом его распарсить, чем потом разруливать.


 
GrayFace ©   (2010-05-14 21:04) [67]

Хотя, да, подобное я парсил конечным автоматом.



Страницы: 1 2 вся ветка

Форум: "Прочее";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.66 MB
Время: 0.063 c
2-1272264722
timekiller
2010-04-26 10:52
2010.08.27
TMemoryStream vs Microsoft Word


3-1240933824
Александр из Перми
2009-04-28 19:50
2010.08.27
Как изменять данные в 2-х таблицах малой кровью


2-1270570317
dis12345
2010-04-06 20:11
2010.08.27
горячие клавиши F1 F2


15-1266102977
OneYoungMan
2010-02-14 02:16
2010.08.27
Куб рабочего стола


15-1264333660
Новичок
2010-01-24 14:47
2010.08.27
Электронный словарь в Delphi





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский