Посоветуйте тулзу для убиения комментариев в коде
grep?
/*
bla-bla
-- bla-bla
/*
bla-bla
*/
grep под винду не сложно найти
Я виндузятник, греюсь в биореакторе. Не уверен, что напишу корректную регулярку, которая вот, например, такие приколы будет обходить
code:
/*
bla-bla
— bla-bla
/*
bla-bla
*/
Мб тогда стоит сначала написать регулярку, которая будет искать такие ошибки?
Я виндузятник, греюсь в биореакторе
Не то, чтобы очень рекомендую, но мб поможет RegexBuddy или Editpad pro (первое скорее для построения и применения регэкспов, а второе - редактор, в котором это не так уж и плохо прикручено).
Скока всяких тулзов понаписали, а такого нету. Для VB есть, а для PL/SQL не нашел.
Скока всяких тулзов понаписали, а такого нету. Для VB есть, а для PL/SQL не нашел.
Или ты первый, или плохо искал.
Блин, неужто так необходимо regexp курить то?
А он один раз раскуривается. а потом от него тащишься-тащишься-тащишься-тащишься-тащишься-
Пока не наткнешься на задачу, которой он не того
Правда (для какого-нибудь С) будут жестокие проблемы с:
#define COMMENT_START /*
#define COMMENT_END */
COMMENT_START text COMMENT_END
(кстати, а будет ли такой код там корректным?)
Но тут тебе с регулярными выражениями придёт полный пиздец, а с проходчиком по строке - дело просто усложнится, надо будет ещё уметь обрабатывать директивы #define.
#/\*.*?\*/#m
#--.*?$#
(именно в такой последовательности)
Единственный уточняющий момент: /*/ считается валидным комментарием или нет?
Может править прямо в буфере.
P.S. Слишком редко попадаются задачи, где нужен regexp, потому успеваю забывать что умел.
основная идея в регэкспах не забывается после пары раз толкового вкуривания в доку
но вообще курить регэкспы конечно необязательно, можно просто вооружиться гуглом, и нагуглить что нить вроде этого
Блин, придется regexp покурить :/
Это на перле. Он даже под венду есть.
perl и php мне не катят, поскольку я с ними не знаком, а из-за такой задачки смотреть что там к чему - наф-наф.
P.S. Тока не надо говорить, что я ленивый. Книги по профессии (Oracle/Informatica) регулярно ботаю.
там же уже готовое все. можно даже perl -e делать, если склеить в строку.
Мне перл устанавливать надо. Помнится как то хотел поучить SQL. Почитал доки по MySQL, подумал что это супер БД, установил... Потыкался, офигел, удалил. С тех пор такие сомнительные опыты не ставлю. Как вариант пока рассматриваю скачать аналог грепа и взботнуть regexp - по любому именно эта хрень потребуется.
да этот перл ставится моментально, потом пользуешься как cscript
у вендузятнегов определенно альтернативное сознание. они могут программировать без grep! ;]
это не та задача, где надо 10 дней думать, как сделать лучше
а вообще, ты со своей "ленью" перебарщиваешь имхо
свой кругозор надо расширять
Ну как бы большого кодинга у меня нет. То что в этом случае, так это чел такой попался... Обычно размер пакета не превосходит 1 000 строк - в данном случае их 10 000, и более 90% из них камменты (руки оторвал бы за такое, была бы моя воля )
более 90% из них камменты (руки оторвал бы за такое, была бы моя воля )а я б наоборот памятник поставил, если комментарии по делу
чем они тебе вообще не угодили, что ты их так упорно хочешь порезать?
Блин, я за все время пытался учить всякого г столько, что самому уже тошно, поскольку оно нафиг никому не надо: WinAPI, Delphi, BDE API, OpenGL, COM, VBA, WSH, C++ (под Win/WinCE lua + что то там еще. Может кому то и покажется это маленьким списком, но я ни разу не был прогером (Oracle - там PL/SQL - это скорее скриптовый язык).
Большая часть камментов это просто старый код. Оставшаяся большая часть - это либо совсем бестолковые, либо могут быть устранены разумным названием переменных, а не i, j, AllDate.
например, переться от каждой новой изученной фенечки
имхо это довольно сложно, особенно если речь идет о каком-нибудь COM.
но шо ж делать, иногда приходится =)
Да и что то не вижу я света в конце тунеля "прогерство", бесполезный навык по зп обычно
а то как то это для меня непонятно
комментарии из кода вырезать, винапи, тратата, и не прогер 0.о
ps
Я не резиновый, мне и текущих за глаза.старость не в радость что ли? =) а что будет через 5 лет? через 10? =)
ты если не секрет чем занимаешься то?Ну написал же выше - Oracle (SQL, PL/SQL Informatica (Хранилища данных вообщем).
Про код, написал выше, что это не обычный пакет, написанный необычным челом.
а что будет через 5 лет? через 10? =)Надеюсь по работе больше прогать не придется. Большая часть перечисленных левых скилов, относятся к моему текущему хобби (писанине игрухи на КПК).
Надеюсь по работе больше прогать не придется. Большая часть перечисленных левых скилов, относятся к моему текущему хобби (писанине игрухи на КПК).портируй сразу под Android, чтоб перестраховаться.
Это новая платформа что ли? Че та с развитием мелких компов с обычным, не ARM/MIPS, процами и обычной ОС (WinXP для меня сомнительно будущее мобильных платформ.
Че та с развитием мелких компов с обычным, не ARM/MIPS, процами и обычной ОС (WinXP для меня сомнительно будущее мобильных платформ.это верно, только звонить с помощью таблеток пока не удобно, а остальное — еще слишком далекое будущее.
про обычную ОС — лол. =)
2Муртаза, включи прием личных сообщений, да?
Android — это линукс.
Мля Начать что ли Linux смотреть... Неее! Бум считать, что я этого не видел
будем считать, что ты и этого не видел:
Угу, у некоторых отцов COM так и не получилось осилить
да, пианист иногда это вспоминает с ужасом. =)
вы с ума сошли?
какая нах регулярка?
что она будет делать в таких случаях
select 1 "/* lala */" from dual
select 1
-- /*
from /*
-- comment */
dual
а?
вот тут бы как раз мускуль порулил со своими исходниками.
А нафига тут регэкспы? Здесь никакие регэкспы, здесь надо тупо идти по строке с одним из трёх состояний - никаких комментариев, комментарий первого типа, комментарий второго типа, и в зависимости от текущего символа (и мб следующего) переходить между состояниями и писать/не писать в выходную строку.Ты идиот, клинический, теперь я в этом убедился. То, что ты написал, называется "конечный автомат", регекспы являются наиболее удобным языком описания конечных автоматов для работы с текстом.
И языка С ты нифига не знаешь конечно же, но проблема даже не в этом, а в том, что практически у любого языка (и С, как и sql, входит в их число) лексер, бьющий поток на лексемы и выдирающий комменты, написан на регексах же. Директивы обрабатываются после того, как комменты вырезаны.
Значит, ей придётся ещё и строчки обрабатывать.
Со вторым примером нет ни малейшей проблемы.
То, что ты написал, называется "конечный автомат", регекспы являются наиболее удобным языком описания конечных автоматов для работы с текстом.regex не является полноценным языком описания конечных автоматов.
'"' bla "/*" bla '+' bla '*/' bla "\"" ?
имхо тут какая-то рекурсивная регулярка нужна, если обычной и хватит то выглядеть она бедет ниибически.
пытался учить всякого г столько, что самому уже тошно, поскольку оно нафиг никому не надо+1
вообще, тебе нужно два регулярных выражения, по которым будет вырезаться текст, вот вариант (синтаксис PCRE, для grep-а надо будет адаптировать, не уверен, что получится):И что будет на такой тривиальный случай, как
#/\*.*?\*/#m
#--.*?$#
(именно в такой последовательности)
--/*
doSomething;
--*/
?
Ты идиот, клинический, теперь я в этом убедился. То, что ты написал, называется "конечный автомат"Теперь модно считать клиническими идиотами тех, кто может додуматься до/знает какое-то понятие, но не знает его общепринятого обозначения?
регекспы являются наиболее удобным языком описания конечных автоматов для работы с текстом.Во-первых, они необязательно будут наиболее удобным языком в каком-то конкретном случае.
Во-вторых, в общем случае то, что я описал, не может быть выражено регэкспами. В каких-то частных случаях - да, но не в общем.
практически у любого языка (и С, как и sql, входит в их число) лексер, бьющий поток на лексемы и выдирающий комменты, написан на регексах же.Да ну?
практически у любого языка (и С, как и sql, входит в их число) лексер, бьющий поток на лексемы и выдирающий комменты, написан на регексах же.ага, тож не понял что он хотел сказать
Но в том, что это делается на регэкспах - ну просто дикие сомнения. Не делают такие вещи на регэкспах. Зачем делать то, что можно написать несколькими строчками дополнительного кода в проходчике строки, десятиэтажными регулярками, в которых никто не разберётся, которые будут мешать друг другу, у которых будут всякие побочные эффекты, и которые не всегда вообще можно написать?
Что он хотел сказать - понятно (если я правильно понял, в PHP это называется tokenizer)т.е. в пхп tokenizer "выдирает комментарии"?
я всегда думал что он только разбивает строчку, а о такой сущности как коммент ваще не знает
открывающий_тэг строка открывающая_скобка строка_в_кавычках закрывающая_скобка коммент_до_конца_строки многострочный_коммент закрывающий_тэг.
ага, тож не понял что он хотел сказатьВ теории компиляторов, текст изначально бъётся на лексемы. Соответственно есть проги, генерящие лексические анализаторы (flex, например). На вход получают файл с набором регулярных выражений, соответствующих лексемам.
А ты заранее проверь наличие подобной фигни. Задачка то разовая, придумывать ради неё универсальное средство - время зря терять.
ну дык разве регвыражения существовали когда создавался Си?
потом я как-то использовал чтото такое, вроде lcc
дык там регулярками и не пахло
Именно для такой задачи гораздо легче написать нормальный обработчик, а не трахаться с регэкспами.
<?php
class CommentDescription {
public $sOpening;
public $sEnding;
public $sReplaceWith;
public function __construct($sOpening, $sEnding, $sReplaceWith) {
$this->sOpening = $sOpening;
$this->sEnding = $sEnding;
$this->sReplaceWith = $sReplaceWith;
}
}
function stripComments($sCodeWithComments) {
$sCode = '';
$arrComments = array(
new CommentDescription('/*','*/',''
new CommentDescription('--',chr(0x0dchr(0x0d
new CommentDescription('--',chr(0x0achr(0x0a
);
$bInComment = false;
$iCommentType = null;
$l = strlen($sCodeWithComments);
for($i=0;$i<$l;$i++) {
if($bInComment) {
if(substr($sCodeWithComments,$i,strlen($arrComments[$iCommentType]->sEnding == $arrComments[$iCommentType]->sEnding) {
$bInComment = false;
$i += strlen($arrComments[$iCommentType]->sEnding) - 1;
$sCode .= $arrComments[$iCommentType]->sReplaceWith;
continue;
} else {
continue;
}
} else {
foreach($arrComments as $key => $oComment) {
if(substr($sCodeWithComments,$i,strlen($arrComments[$key]->sOpening == $arrComments[$key]->sOpening) {
$bInComment = true;
$iCommentType = $key;
break;
}
if($bInComment) {
$i += strlen($arrComments[$iCommentType]->sOpening) - 1;
continue;
} else {
$sCode .= substr($sCodeWithComments,$i,1);
}
}
}
}
return $sCode
}
?>
Сколько там ушло, 12 минут?
ЗЫ: Не тестил, возможны мелкие баги.
минуты 2.
всякие йобнутые случаи не находит (один хрен их не будет с вероятностью 95%) но для одноразового скрипта идеальный вариант, если возникают проблемы модифицируется еще за минуту
вот мне тож показалось что он компиляторы имел ввиду, а не токенайзерыНу может не в форме perlre, но наверняка теория уже была. Взять ту же форму Бэкуса-Наура.
ну дык разве регвыражения существовали когда создавался Си?
я к тому, что какая разница, были ли регэкспы когда придумывался си?
perl -ne 'print unless m/^--/' | perl -e 'while (<>) {$line .= $_;}; $line =~ s/\/\*.*?\*\///sg; print $line;'Говно какое-то, честное слово.
Да ещё и нерасширяемое нихуя; оно не только с вложенными комментами работать никогда не сможет, но и с
insert into `table` values('/*stringtoinsert*/');
http://stuff.thedeemon.com/nocom.exe (119 КБ)
Читает из стандартного ввода, выводит на стандартный вывод, т.е. запускать
nocom.exe <infile.sql >outfile.sql
Знает два вида комментариев, три вида строк (в одинарных, двойных и обратных кавычках знает, что внутри строки две кавычки подряд не заканчивают строку. Соответственно, комментарии внутри строк не вырезаются.
На тестовом примере
simple text: a1a aa1a
single line comment: aa2a --bbb
other comment: aa3a /* bbb*/ aa3a
multiline comment: aa4a /*bbbb
bbbb
bbbb */ aa4a
single in multi: a5aa /* bbb--ccc */ aa5a
simple string: a6aa 'dddd' aaa6
simple string with one apostr.: aaa7 'dd''dd' aaa7
comments in string: aaa8 'd/*ee*/d --ff''f' aaa8
comments in string: aaa9 "d/*ee*/d --ff""f" aaa9
comments in string: aaa10 `d/*ee*/d --ff``f` aaa10
comments around strings: aaa14 /* 'd/*ee*/d --fff' "ddd" `ddd` */ aaa14
strings in single line comments: aaa15-- "d/*ee*/d --fff" 'ddd' `ddd` bbb
nested strings: "aaa16 /*zz*/ 'bbb `dd /*zz*/ dd` /*zz*/ bb -- bb'aaa" /*bbb*/ aa16
Выводится:
simple text: a1a aa1a
single line comment: aa2a
other comment: aa3a aa3a
multiline comment: aa4a aa4a
single in multi: a5aa aa5a
simple string: a6aa 'dddd' aaa6
simple string with one apostr.: aaa7 'dd''dd' aaa7
comments in string: aaa8 'd/*ee*/d --ff''f' aaa8
comments in string: aaa9 "d/*ee*/d --ff""f" aaa9
comments in string: aaa10 `d/*ee*/d --ff``f` aaa10
comments around strings: aaa14 aaa14
strings in single line comments: aaa15
nested strings: "aaa16 /*zz*/ 'bbb `dd /*zz*/ dd` /*zz*/ bb -- bb'aaa" aa16
Escape-последовательности не реализовывал, на них гипотетически могут быть глюки.
Исходник в 20 строк на Окамле:
type t = Out | OneLine | MultiLine | Quote of t * char | Q1 of t * char;;
let isquote c = (c='\'') || (c='"') || (c='`');;
let rec filter state =
try
let c = input_char stdin in
let newstate, out = match state, c with
| Out, '-' -> let c2 = input_char stdin in if c2 = '-' then OneLine, false
else (print_char c; print_char c2; Out, false)
| Out, '/' -> let c2 = input_char stdin in if c2 = '*' then MultiLine, false
else (print_char c; print_char c2; Out, false)
| Out, _ -> (if isquote c then Quote(Out, c) else Out true
| OneLine, '\n' -> Out, true
| OneLine, _ -> OneLine, false
| MultiLine, '*' -> let c2 = input_char stdin in if c2 = '/' then Out, false else MultiLine, true
| MultiLine, _ -> (if isquote c then Quote(MultiLine, c) else MultiLine false
| Quote(st, ch _ -> (if ch=c then Q1(st, c) else Quote(st, ch (st = Out)
| Q1(st, ch _ -> (if ch=c then Quote(st, c) else st (st = Out)
in (if out then print_char c; filter newstate)
with End_of_file ->
in filter Out;;
Простой конечный автомат. У кого есть желание записать его в виде регэкспа?
чувак перловский интерпретатор боится ставить, а ты окамл =)
Я дал ссылку на exe, там вообще ничего ставить не надо - запустил и пользуйся.
рекурсия не хвостовая кажись
ч0рт, зачот =)
Псиб, после праздников погоняю
Можно проверить на длинном файле. Если вдруг не хвостовая, будет переполнение стека..
Теперь исправил, заодно убрал лишнее состояние и сократил до 17 строк:
type t = Out | OneLine | MultiLine | Quote of t * char;;
let isquote c = (c='\'') || (c='"') || (c='`');;
let rec filter state =
let c = input_char stdin in
let newstate, out = match state, c with
| Out, '-' -> let c2 = input_char stdin in if c2 = '-' then OneLine, false
else (print_char c; print_char c2; Out, false)
| Out, '/' -> let c2 = input_char stdin in if c2 = '*' then MultiLine, false
else (print_char c; print_char c2; Out, false)
| Out, _ -> (if isquote c then Quote(Out, c) else Out true
| OneLine, '\n' -> Out, true
| OneLine, _ -> OneLine, false
| MultiLine, '*' -> let c2 = input_char stdin in if c2 = '/' then Out, false else MultiLine, true
| MultiLine, _ -> (if isquote c then Quote(MultiLine, c) else MultiLine false
| Quote(st, ch _ -> (if ch=c then st else Quote(st, ch (st = Out)
in (if out then print_char c; filter newstate)
in try filter Out with End_of_file -> ;;
Теперь точно хвостовая, 15-меговый файл съедает легко. Ехе-шник обновил.
Поясни мысль, пожалуйста. Я, видишь ли, могу по произвольному регексу построить автомат и наоборот, по произвольному автомату построть регекс, поэтому меня как-то удивляет такое заявление. Хотя я согласен, что некоторые автоматы описывать регексами будет нелегко, да и практические задачи (типа "убрать все комменты") может оказаться тяжелее перефигачить на понимаемые регексами "принадлежит ли слово языку и если да, то как оно матчится", чем на конечные автоматы.
Вот такая штука:
^(?'capture' "[^"]*") | (?[^\n\r]*
если матчится, то кэпчурит в группу "capture" всё до первого коммента, то есть если сделать Replace("${capture}" то выкусится первый коммент. Соответственно, нужно дописать вокруг немножко кода, который всё заматчит и зареплейсит (а то и подпатчить регекс, чтобы он в эту группу кэпчурил много кэпчуров, которые потом отдельный код сконкатенировал и вернул бы). А ещё это не совсем чистый регекс, потому что писать negative lookahead на чистом регексе я бы умер (хотя, насколько я понимаю, компилится оно всё равно в конечный автомат без наворотов).
Окей, мне тоже код на окамле нравится больше, хоть регекс и короче в двадцать раз =)
2Пенартур: человек, считающий себя программистом и при этом вынужденный придумывать своё определение конечного автомата, является клиническим идиотом.
2алл: регексы вообще-то придумали в пятидесятых годах, затем Кен Томпсон добавлял соответствующий синтаксис в разные редакторы, затем этот кусок из одного из них вытащили и сделали отдельной прогой (которую назвали grep потому что именно такой командой оно запускалось в редакторе затем Томпсон сделал язык B, а затем уже Керниган и Риччи сделали вначале BCPL, а потом и C. God bless Wikipedia!
Я, видишь ли, могу по произвольному регексу построить автомат и наоборот, по произвольному автомату построть регекс, поэтому меня как-то удивляет такое заявлениеутверждение: по произвольному автомату можно построить regex - неверно.
у автомата есть память - в regex-ах памяти нет.
соответственно: контекстно зависимые или рекурсные вещи на regex-ах хрен сделаешь
ps
также regex-ы неудобны с эксплуатационной точки зрения:
1. нет повторного использования
2. нет разбиения на отдельные части
3. предыдущие пункты + более мелкие - приводят к низкой читабельности regex-ов, что приводит к большому кол-ву ошибок в них
по произвольному автомату построть регексИли всё-таки то, о чём я говорил, называется не автоматом, или тебе как минимум придётся пользоваться новомодными рекурсивными регэкспами, которые появились сравнительно недавно.
человек, считающий себя программистом и при этом вынужденный придумывать своё определение конечного автомата, является клиническим идиотомЯсно, то есть, ты считаешь клиническими идиотами тех, у кого нет каких-то конкретных знаний.
А мне вот кажется, что знания приложаться, и, больше того - по-твоему, клиническими идиотами надо вообще считать всех, кроме ботанов-задротов, да и с ботанами-задротами тоже не всё понятно.
Или ты почему-то считаешь, что я под "конечными автоматами" имею в виду конечные автоматы с магазинной памятью, а то и двумя? Нет, я ничего такого не имею в виду!
Да, я согласен, что приведённый окамлокод понятней и удобней для поддержки, чем мой регекс.
2Пенартур: фу, какая предсказуемая предсказуемость тупизны. Нет, ты дебил не потому, что у тебя не хватает знаний, а потому, что ты за все эти долгие годы не удосужился восполнить данный конкретный пробел, например.
встречный вопрос:
почему ты считаешь, что грамматику языка (а в данном треде речь идет именно о возможности описания грамматики языка на regex-ах) можно описать с помощью конечного автомата без памяти?
Нет, ты дебил не потому, что у тебя не хватает знаний, а потому, что ты за все эти долгие годы не удосужился восполнить данный конкретный пробел, например.И чем же этот конкретный пробел лучше других?
Я вообще-то всю жизнь тем и занимаюсь, что восполняю пробелы. Пробелов - их всегда куча, чем больше их восполняешь, тем больше открывается
---
Наверное, потому, что в данном треде идёт речь о конкретном языке, грамматику которого в данном треде уже два раза описали при помощи конечного автомата без памяти, на окамле и на регексах. Не знаю, как тебе, но мне было с самого начала совершенно очевидно, что это можно сделать.
Не знаю, как тебе, но мне было с самого начала совершенно очевидно, что это можно сделать.также очевидно, что парсер для данной задачи можно написать на ассемблере или на машине тьюринга.
но вот нужно ли?
ps
имхо, парсеры надо писать на что-нибудь типа lexx-а, а не изобретать велосипеды в виде regex-ов или ocaml-а
Во-первых, lex, а не lexx (если, конечно, ты не имеешь в виду ограниченно разумный космический корабль со множеством сексуальных расстройств во-вторых, ему на вход подаётся список вида "регулярное выражение" - "код выполняемый в случае успешного матча", так что я не очень понял эту вот ремарку про регекс как изобретение велосипеда =)
ему на вход подаётся список вида "регулярное выражение" - "код выполняемый в случае успешного матча", так что я не очень понял эту вот ремарку про регекс как изобретение велосипеда =)На основе статьи в википедии, можно составить что-то уродское вроде
\/\*
{
if(!bInComment) {
bInMultilineComment = true;
bInComment = true;
}
}
\*\/
{
if(bInMultilineComment) {
bInMultilineComment = false;
bInComment = false;
} else {
echo '*/';
}
\/\/
{
if(!bInComment) {
bInSinglelineComment = true;
bInComment = true;
}
}
[\n\r]
{
if(bInSinglelineComment) {
bInComment = false;
bInSinglelineComment = true;
}
echo '${0}';
}
{
if(!bInComment) echo '${0}';
}
(если я правильно понял )
я не очень понял эту вот ремарку про регекс как изобретение велосипеда =)соответственно получается, что регекс - это способ описания какого-то маленького кусочка грамматики,
и не надо изобретать велосипед и пытаться описать на regex-е всю грамматику
также одно дело, когда мы явно фиксируем, что:
/* - это есть токен "начало комментария"
и совсем другое дело - когда пишется невообразимая конструкция из слэшей, из который фиг понимается, что хотел сказать автор.
и то, и другое описание - можно считать регулярным выражением, но в одном языке явно фиксируется информация, который хотел высказать автор, а в другом случае - фиксируется какая-то низкоуровневая херотень, которая никакого отношения к мысли автора не имела.
ps
привязка кода - это уже фича, а не основная особенность
program: (code|comment)*
comment = multi_line_comment | single_line_comment
multi_line_comment = '/*' any_char* '*/'
single_line_comment = '//' symbol* line_break
line_break = '\n' | '\r\n'
code: (token space)*
token: \w+
space: \b+
вот с таким описанием уже можно работать, и вот на такое описание и стоит тратить свое время.
заморочки же с регекспами или с чистым кодом - не стоят потраченного на них время.
ps
в описании есть неточности.
в описании есть неточности.В описании - критические неточности, вроде того, что оно не знает про то, что бывают строки '/*test*/'. А если их фиксить, если у тебя в code будут допустимы все эти символы - то я очень сильно сомневаюсь, что оно будет правильно распознавать всякие сложные случаи, которых в этом треде уже много было. Ну или же придётся для такой элементарной задачи, как вырезание комментов, полностью описывать весь язык целиком.
program: (code|comment)*
comment = multi_line_comment | single_line_comment
multi_line_comment = '/*' any_char* '*/'
single_line_comment = '//' symbol* line_break
line_break = '\n' | '\r\n'
code: token|string) space)*
token: \w+
space: \b+
string: string1 | string2
string1: '\'' [^']* '\''
string2: '"' [^"]* '"'
А ещё надо помнить про то, что в строках могут быть escape-последовательности, что допустимы ещё и всякие запятые, скобки, плюсы-минусы итд... в результате, тебе придётся определять здесь полностью весь синтаксис языка, и будет очень больно, если что-нибудь забудешь. Тогда как мой код делает только то, что нужно - отбрасывает все комментарии (и ещё парой строчек добавляется правило "не рассматривать то, что внутри строк").
так у меня же написано, что любой символ кроме кавычки может быть внутри строки
если же речь идет о поддержке последовательности \' - то ее в любом случае надо добавлять, что в код, что в декларацию.
токен - это любая последовательность непробельных символов (за исключением кавычек соответственно все плюсы/минусы/скобки и т.д. - в это входит
фактически ты эти правила и описываешь, только на своем "птичьем" языке, а не в виде стандартной декларации
так у меня же написано, что любой символ кроме кавычки может быть внутри строкиЯ неправильно выразился.
a=b*(c+d);
под твои определения вообще никак не подойдёт, там противоречий больше, чем символов.
1. Где у тебя вообще поддержка строк?
2. что будет, если надо будет добавить такие варианты строк:?
''''
""""
'\''
"\"'
3. что будет если надо добавить обработку ошибок?
с точки зрения данной задачи - это один токен
program: (code|comment)*
comment = multi_line_comment | single_line_comment
multi_line_comment = '/*' any_char* '*/'
single_line_comment = '//' symbol* line_break
line_break = '\n' | '\r\n'
code: token|string) space)*
token: любой_символ_кроме_пробельных_и_кавычек+
space: \b+
string: string1 | string2
string1: '\'' [^']* '\''
string2: '"' [^"]* '"'
Сейчас напишу окончательный полностью рабочий вариант.
тебе надо полностью описать весь язык.это ты так думаешь, а в моем описание - весь код (кроме строк и комментариев) - это один большой токен
<?php
abstract class StructureDescription {
public $sOpening;
public $sEnding;
public function __construct($sOpening, $sEnding) {
$this->sOpening = $sOpening;
$this->sEnding = $sEnding;
}
}
class StringDescription extends StructureDescription {
public $arrEscapeTokens;
public function __construct($sOpening, $sEnding, $arrEscapeTokens = array {
parent::__construct($sOpening, $sEnding);
$this->arrEscapeTokens = $arrEscapeTokens;
}
}
class CommentDescription extends StructureDescription {
public $sReplaceWith;
public function __construct($sOpening, $sEnding, $sReplaceWith = '') {
parent::__construct($sOpening, $sEnding);
$this->sReplaceWith = $sReplaceWith;
}
}
function stripComments($sCodeWithComments) {
$sCode = '';
$arrComments = array(
new CommentDescription('/*','*/',''
new CommentDescription('--',chr(0x0dchr(0x0d
new CommentDescription('--',chr(0x0achr(0x0a
);
$arrEscapeTokens = array(
// '\\\\0x[0-9a-f]{2}',
'\\\\.',
);
$arrStrings = array(
new StringDescription('\'','\'',$arrEscapeTokens
new StringDescription('"','"',$arrEscapeTokens
);
$bInComment = false;
$iCommentType = null;
$bInString = false;
$iStringType = null;
$l = strlen($sCodeWithComments);
for($i=0;$i<$l;$i++) {
if($bInComment) {
if(substr($sCodeWithComments,$i,strlen($arrComments[$iCommentType]->sEnding == $arrComments[$iCommentType]->sEnding) {
$bInComment = false;
$i += strlen($arrComments[$iCommentType]->sEnding) - 1;
$sCode .= $arrComments[$iCommentType]->sReplaceWith;
continue;
} else {
continue;
}
} else {
if($bInString) {
$sRest = substr($sCodeWithComments,$i);
$bMatched = false;
foreach($arrStrings[$iStringType]->arrEscapeTokens as $sEscapeToken) {
if(preg_match('/^'.$sEscapeToken.'/s',$sRest,$arrMatches {
$sCode .= $arrMatches[0];
$i += strlen($arrMatches[0]) - 1;
$bMatched = true;
break;
}
}
if($bMatched) continue;
if(substr($sCodeWithComments,$i,strlen($arrStrings[$iStringType]->sEnding == $arrStrings[$iStringType->sEnding]) {
$sCode .= $arrStrings[$iStringType]->sEnding;
$i += strlen($arrStrings[$iStringType]->sEnding) - 1;
continue;
}
$sCode .= substr($sCodeWithComments,$i,1);
continue;
}
foreach($arrStrings as $key => $oString) {
if(substr($sCodeWithComments,$i,strlen($oString->sOpening == $oString->sOpening) {
$bInString = true;
$iStringType = $key;
$sCode .= $oString->sOpening;
$i += strlen($oString->sOpening) - 1;
break;
}
}
if($bInString) continue;
foreach($arrComments as $key => $oComment) {
if(substr($sCodeWithComments,$i,strlen($arrComments[$key]->sOpening == $arrComments[$key]->sOpening) {
$bInComment = true;
$iCommentType = $key;
$i += strlen($arrComments[$iCommentType]->sOpening) - 1;
break;
}
if($bInComment) continue;
$sCode .= substr($sCodeWithComments,$i,1);
}
}
}
return $sCode
}
?>
Обрати внимание, что я тут не имею ни малейшего представления о том, как устроен язык за пределами комментариев и строк (да и на строки смотреть приходится только потому, что комменты, которые в них - не комменты.
program: (code|comment)*Я тебя поздравляю.
comment = multi_line_comment | single_line_comment
multi_line_comment = '/*' any_char* '*/'
single_line_comment = '//' symbol* line_break
line_break = '\n' | '\r\n'
code: token|string) space)*
token: любой_символ_кроме_пробельных_и_кавычек+
space: \b+
string: string1 | string2
string1: '\'' [^']* '\''
string2: '"' [^"]* '"'
И как же ты собираешься понять,
/*test*/- это code или comment?
подходит под правило multi_line_comment - значит комментарий
Нифига, подходит под правило token - значит, код.
code: (token space)*space-то что? Совсем не обязательно, что вокруг строки whitespace'ы стоят!
это вот одна из тех неточностей, с которой не хотелось разбираться
И, кроме того - это не критическая неточность.
давай для простоты (хотя можно делать и хитрее) договоримся, что если между правилами есть конфликт, то выбирается первое.
критические неточности на твой взгляд еще есть?
критические неточности на твой взгляд еще есть?Да.
У тебя там написано
(code|comment)*Где тут конфликт между _двумя_ правилами?
a /*b*/ cможно представить как code comment code, как code code code, двумя способами как code code, и как code. И как же понять, как правильнее?
правильное описание - это что-то типа:Почему ты утверждаешь, что оно единственно правильное и не стоит заморачиваться регэкспами? Небольшой экскурс в теорию компиляторов и формальных грамматик:
program: (code|comment)*вот с таким описанием уже можно работать, и вот на такое описание и стоит тратить свое время.
comment = multi_line_comment | single_line_comment
multi_line_comment = '/*' any_char* '*/'
single_line_comment = '//' symbol* line_break
line_break = '\n' | '\r\n'
code: (token space)*
token: \w+
space: \b+
заморочки же с регекспами или с чистым кодом - не стоят потраченного на них время.
Детерминированный конечный автомат без памяти не может матчить КС-грамматику. А когда говорят автомат, то подразумевается именно автомат без памяти.
Текст программы сначала разбивается на лексемы, а синтаксис строится уже поверх лексем. Обычно лексемы описываются только регулярными языками, а синтаксис - контекстно-свободными.
Это делается из-за того, что матчить регулярный язык можно за линейное время и O(1) памяти, а КС - уже за нелинейное в общем случае (нужно извращаться не меньше чем с регэкспами и строить LR и подобные). Именно поэтому и надо заморачиваться с регэкспами.
Упомянутый lex - как раз и занимается 1-й задачей - разбить текст на лексемы. Если ты хочешь полноценные языки описывать, то тебе уже синтаксические анализаторы понадобятся, типа yacc, bison.
В общем, для данной задачи, использование КС - избыточно и регулярные выражения/конечные автоматы и так легко и прекрасно с этой задачей справятся. В данной задаче нужно просто отфильтровать лексемы.
Почему ты утверждаешь, что оно единственно правильное и не стоит заморачиваться регэкспами?оно наиболее эффективное по затратам сил и времени (а не единственное правильное)
ps
кстати как много ты можешь привести качественных решений, использующие парсеры на основе регексов?
имхо, регекс - это хрень, для быстрого создания низкокачественного неподдерживаемого решения.
оно наиболее эффективное по затратам сил и времени (а не единственное правильное)А я утверждаю, что на конечном автомате/регэксе более эффективно по тем же параметрам.
Кому верить?
кстати как много ты можешь привести качественных решений, использующие парсеры на основе регексов?Ээээ.... так уже сколько раз повторял - лексемы большинства языков программирования описываются регулярными выражениями.
имхо, регекс - это хрень, для быстрого создания низкокачественного неподдерживаемого решения.
Кстати, я так и не увидел решения данной задачи на preg_replace. Даже если забыть о существовании строк, в которых то, что кажется комментами, таковыми не является.
лексемы большинства языков программирования описываются регулярными выражениями.так вот именно, что отдельные лексемы, а не вся грамматика.
так вот именно, что отдельные лексемы, а не вся грамматика.Ну так естественно. Т.к. грамматику языка программирования (не рассматривая отдельные исключения) просто невозможно описать регэкспом, но не из-за того, что регэксп предназначен для "грязных, кратковременных решений", а потому что регэксп - это средство из мира регулярных грамматик, а у языка синтаксис описывается контекстно свободной.
И даже этот факт, что для описания языка всё равно нужен КС-парсер не уменьшает "пользу", приносимую регулярными грамматиками.
дык, зло в regexp-ах, а не в самих регулярных грамматиках
дык, зло в regexp-ах, а не в самих регулярных грамматикахА в чём зло-то?
Вот, как минимум лексические анализаторы lex, flex используют такую нотацию. Не удивлюсь, если в других системах генерации компиляторов тоже используются они.
Многие утилиты обработки текста используют регулярные выражения.
Да и в теории компиляторов на ВМК даже преподаются алгоритмы построения ДКА по регулярному выражению.
Что ты можешь предложить для обработки текста, что было бы удобнее, если говоришь, что регулярные выражения зло?
зло именно regex - а именна та реализация (та нотация что пошла с перла
сами по себе регулярные выражения полезны и записывать их лучше в виде того же Бэкуса-Наура
зло именно regex - а именна та реализация (та нотация что пошла с перлаА вот и нет. Там где я говорил про регулярные выражения (lex, теория) имелись в виду как раз подобные перловским. Ну там на самом деле особо мудрить и не получится, т.к. они всё равно идеологически все будут похожи.
сами по себе регулярные выражения полезны и записывать их лучше в виде того же Бэкуса-НаураА вот формы Бэкуса-Наура уже не особо похожи на регулярные выражения. Они больше напоминают запись (в общем случае) КС-грамматики. А писать регулярную грамматику сложнее, чем регулярное выражение. Вот, например, грамматика, которую ты писал - не является регулярной.
Кстати, я так и не увидел решения данной задачи на preg_replace. Даже если забыть о существовании строк, в которых то, что кажется комментами, таковыми не является.Ну от себя могу предложить только вот такое. (Долго не думал, так что это не идеальное решение, т.е. это не повод обобщать его убогость на весь мир )
Имеем такие регулярные выражения:
комментарий: /\*.*?\*/|--.*?\n
строка: "([^"]|""|\\")*"
символ: .
Псевдокод:
if (/^${комментарий}/)
{
skip;
}
else
{
/^(${строка}|${символ})/
print;
}
а именна та реализация (та нотация что пошла с перлаКстати, по поводу нотаций. Базовое в регулярных выражениях только: группировка - альтернатива - |, повторение - *. Всё остальное - syntax sugar и в этом ничего плохого нет. Разве только есть всякие нерегулярные расширения типа некоторых видов бектресинга, но это уже отдельный предмет обсуждения.
Так что именно тебе в перловской нотации не нравится?
Кстати, я так и не увидел решения данной задачи на preg_replace. Даже если забыть о существовании строк, в которых то, что кажется комментами, таковыми не является.Эм. Чувак, я вообще-то написал совершенно полное решение, с корректной обработкой строк и всем таким. Только оно либо удалит все комменты за квадратичное время, либо нужно будет его ещё раз взять в скобки и поставить звёздочку, чтобы потом ручками вытащить и сконкатенировать все матчи из группы. Ничего лучше сделать нельзя, потому что для определения того, является ли произвольный данный кусок кода комментом, нужно прочитать весь предыдущий код, а встроенной объединялки различных матчей одной и той же группы в стандартном реплейсе практически наверняка нет.
Так что именно тебе в перловской нотации не нравится?
также regex-ы неудобны с эксплуатационной точки зрения:
1. нет повторного использования
2. нет разбиения на отдельные части
3. нет группового отделения команд от текста
4. предыдущие пункты + более мелкие - приводят к низкой читабельности regex-ов, что приводит к большому кол-ву ошибок в них
Лексу на вход подаётся набор "регулярка" - "действие". Он объединяет все регулярки в один конечный автомат, хитроумно разруливая неоднозначности/специализации (типа что я могу написать регулярку для комментов, ниже — регулярку для токенов (по идее матчащую и комменты тоже а он при объединении сделает так, что токен будет матчится только если до того не заматчился коммент (этого не мог понять пенартурег, известно почему!.
Точнее синтаксиса я не знаю, возможно он даже позволяет писать что-то БНФ-подобное, но БНФом не являющееся (достаточно запретить рекурсию).
Вот! Эта штука позволяет разбивать регекс на маленькие именованные независимые кусочки, что очень хорошо. Но получается в результате тот же самый регекс, что, кстати, ещё лучше! Правда, на этом повод для спора исчёрпывается?
Лексу на вход подаётся набор "регулярка" - "действие". Он объединяет все регулярки в один конечный автомат, хитроумно разруливая неоднозначности/специализации (типа что я могу написать регулярку для комментов, ниже — регулярку для токенов (по идее матчащую и комменты тоже а он при объединении сделает так, что токен будет матчится только если до того не заматчился коммент (этого не мог понять пенартурег, известно почему!.И где я туплю? Я где-то утверждал обратное?
1. нет повторного использованияПоясни. Чего тебе повторно использовать надо?
2. нет разбиения на отдельные частиОпять поясни чего ты разбивать хочешь?
3. нет группового отделения команд от текстаЧто есть команды и текст? *, |, [] - это команды? Их ты хочешь отделить от текста? Что значит "групповое отделение"?
4. предыдущие пункты + более мелкие - приводят к низкой читабельности regex-ов, что приводит к большому кол-ву ошибок в нихНе пиши большие регекспы, а пиши маленькие и объединяй их потом.
Когда ты пишешь код на своём любимом ЯП, то там тоже, если напишешь функцию больше чем на страницу - она станет нечитабельной. Это проблема ЯП? Отчасти да, т.к. может есть ЯП, где можно записать короче, но ты ведь из-за этого не отказываешься от этого ЯП.
Вот кстати я теперь стал неуверен, а самому проверять влом: это я правду написал про разруливание специализаций? Или всё-таки нужно в явном виде запретить токену начинаться с комментосимволов, например? Просто как бы оно же конечный автомат, поэтому если оно, например, считывает строчку "/*abc ", ему нужно сразу решить, это токен (и его нужно вернуть) или потенциальное начало коммента (и тогда надо читать дальше). А не слишко ли много он на себя возьмёт, если самостоятельно запретит такие токены?
Ты не понимал ДаркГрея! И спорил не с ним, а со своим непониманием! Это называется "тупить"!Хрена се. Может ты не понимаешь чего он имеет в виду? По крайней мере мне (и надеюсь ему) наша дискуссия кажется осмысленной. Он утверждает, что описывать регулярные грамматики посредством регулярных выражений неудобно. А я ему доказываю, что все так делают и что это более удобный способ, чем остальные. Пока конкретно не покажешь где я по-твоему туплю - я буду считать, что ступил ты.
Вот кстати я теперь стал неуверен, а самому проверять влом: это я правду написал про разруливание специализаций? Или всё-таки нужно в явном виде запретить токену начинаться с комментосимволов, например? Просто как бы оно же конечный автомат, поэтому если оно, например, считывает строчку "/*abc ", ему нужно сразу решить, это токен (и его нужно вернуть) или потенциальное начало коммента (и тогда надо читать дальше). А не слишко ли много он на себя возьмёт, если самостоятельно запретит такие токены?flex вроде себя ведёт так: прочитывает очередную самую длинную возможную лексему, а если она подпадает под несколько вариантов, то берёт тот, что встречается раньше в списке.
---
Ты уверен, что правильно понимаешь, что он имеет в виду?
Он утверждает (и я с ним согласен что неудобно описывать регулярную грамматику при помощи одного длинного регулярного выражения, из которого, после очередного матча, можно вытащить содержимое надцатой скобки и, если оно не пусто, считать, что распозналась соответствующая лексема, иначе проверить содержимое надцатьпервой скобки и далее. Ну это реально неудобно, не правда ли?
В качестве альтернативы он предлагает использовать мета-язык поверх регулярных выражений, позволяющий описывать грамматику небольшими независимыми кусочками (которые, тем не менее, компилируются в одну большую регулярку). И ты предлагаешь то же самое! Это означает, что вы друг друга не понимаете, не правда ли?
flex вроде себя ведёт так
---
Эм. А как это работает? Вот в данном случае, если коммент — это любые символы внутри скобок, а токен — это любые символы до пробела. Оно видит открывающую скобку и какие-то символы, читает, читает, потом хуяк, кончается файл. Тогда оно должно понять, что ему следовало бить на токены, вернуться и продолжить, но тогда это уже совсем не конечный автомат. А если найдёт закрывающую скобку, то следует вернуть коммент. Не понимаю!
Он утверждает (и я с ним согласен что неудобно описывать регулярную грамматику при помощи одного длинного регулярного выражения, из которого, после очередного матча, можно вытащить содержимое надцатой скобки и, если оно не пусто, считать, что распозналась соответствующая лексема, иначе проверить содержимое надцатьпервой скобки и далее. Ну это реально неудобно, не правда ли?А, ну это если собирать всё в одно. Это конечно не тот вариант, тут соглашусь. Но тут всё же имеем не один регулярный язык, а набор (язык, представляющий комментарии, язык представляющий строки, ...). Получается некоторое искажённое применение и из-за этого возникает геморрой.
Тут надо смотреть задачу. Для компиляторов (и не только) - есть lex, который позволяет строить такие автоматы.
Эм. А как это работает? Вот в данном случае, если коммент — это любые символы внутри скобок, а токен — это любые символы до пробела. Оно видит открывающую скобку и какие-то символы, читает, читает, потом хуяк, кончается файл. Тогда оно должно понять, что ему следовало бить на токены, вернуться и продолжить, но тогда это уже совсем не конечный автомат. А если найдёт закрывающую скобку, то следует вернуть коммент. Не понимаю!Ну для такого там, видимо, что-то вроде ungetc применяется. Сейчас поставил эксперимент - маленький файл разбил на токены при незакрытом комментарии, а скормил большой ~50MB - очень надолго задумался, пока ещё не отошёл. Бегло проглядел документацию - конкретно про эту проблему не нашёл, но там можно сделать что-нибудь вроде:
".*<EOF> print "Незакрытая строка"
Я же говорил про те решения, которые состоят из одного длинного preg_replace, вроде
return preg_replace('/(\\/\\*.*\\*\\/|\\/\\/.*[\\r\\n])/s','',sCodeWithoutComments);
(с которым, кстати, даже если не думать о гадостях вроде вложенных комментов, неподготовленному читателю/писателю надо ещё долго думать, чтобы понять, где тут писать .*, где .*?, где [^\\r\\n]* и с какими ключами писать это регулярное выражение, чтобы оно захавало не так много, как смогло, а, наоборот, так мало, как только можно).
(Я правильно понимаю, что то, что ты написал - надо завернуть в цикл?)
Чувак, я вообще-то написал совершенно полное решение, с корректной обработкой строк и всем таким.Ты про
^(?'capture' "[^"]*") | (?[^\n\r]*?
Я не отношусь к категории людей, которые общаются на многоэтажных регэкспах, целиком ниасилил, но двойку тебе можно поставить сразу, хотя бы только за это:
("[^"]*")Так что давай, исправляй такие ошибки - а потом, если у тебя это получится, посмотрим на размер и читабельность твоего выражения (навряд ли они будут лучше, чем сейчас).
один и тот же кусок регулярного выражения - два раза
> Опять поясни чего ты разбивать хочешь?
одно большое регулярное выражение
> Что есть команды и текст? *, |, [] - это команды? Их ты хочешь отделить от текста? Что значит "групповое отделение"?
например, один раз сказать, что вот этот кусок - текст, или вот этот кусок - команды
обычно это делается через те же кавычки
вот такая запись в отличие от стандартного regex-а, и делает разбиение регулярного выражения на три группы с помощью пробелов, и с помощью кавычек отделяет текст от команд:
'/*' .* '*/'
> Не пиши большие регекспы, а пиши маленькие и объединяй их потом
так именно про это я и толкую, что regex - зло, потому что не позволяет так делать.
т.к. объединять их на уровне своего любимого языка - это многое потерять от регулярных выражений, сразу начинают идти множественные проходы по строке, самому надо разбираться с вариантами, бактракингом и т.д.
соответственно хочется цеплять regex-ы вместе на каком-нибудь спец. мета языке, например, на том же бэкусе-науре
ps
_FJ как раз правильно передал своими словами мою позицию
но двойку тебе можно поставить сразу, хотя бы только за этоlolwut?
Если что, я его оттестил на разных примерах. Он работает. Синтаксис .net regex engine с врубленными настройками singleline, ignore whitespaces, compiled (может, ещё что забыл). Проверял в Expresso.
ггг
EDITED: а ещё в нём мог быть баг с поеданием кавычки как обычного символа, так что добавил и её туда
EDITED2: Ах, если хочется эскейпов внутри строчки (а не только паскаль-стайл вложенные кавычки, как в sql, то так) (и заодно тогда пусть все кавычки будут single, а не double, раз уж мы про sql!спасибо, Мадкроз!)
^
(?'capture' # chunk of code before comment
(
(' ([^'\\] | \\.)* ') # quoted string
|
(?!-- | /\* ) [^'] # any char (not starting a comment or quote)
)*
)
(
( /\* ?!\*/).)* \*/ ) # multiline comment
|
(--[^\n\r]*) # singleline comment
)
comments around strings: aaa /* 'd/*ee*/d --fff' */ aaa
?
"capture": aaa
Я таки не понял, что ви имеете в виду.
Вообще, хотелось бы увидеть законченное решение, которое можно запустить, натравить на некий файл и увидеть результат. Я выше приводил тест, мне кажется, результат тут будет другим.
И чем вот это конкретное решение принципиально отличается от моего варианта?Извини, но твоё решение я не смотрел или не помню уже. Просто ответил на поставленный тобою вопрос. Можно, наверное, написать решение из одного длинного выражения, которое будет сразу выводить текст перед очередным комментарием (вроде как раз то, что fj делает но его всё равно придётся применять в цикле.
Я же говорил про те решения, которые состоят из одного длинного preg_replace, вроде
return preg_replace('/(\\/\\*.*\\*\\/|\\/\\/.*[\\r\\n])/s','',sCodeWithoutComments);
(с которым, кстати, даже если не думать о гадостях вроде вложенных комментов, неподготовленному читателю/писателю надо ещё долго думать, чтобы понять, где тут писать .*, где .*?, где [^\\r\\n]* и с какими ключами писать это регулярное выражение, чтобы оно захавало не так много, как смогло, а, наоборот, так мало, как только можно).
(Я правильно понимаю, что то, что ты написал - надо завернуть в цикл?)Да, несомненно. Без цикла решить эту задачу просто невозможно. Ключ "g" в регулярном выражении - тот же самый цикл.
> один и тот же кусок регулярного выражения - два раза
Можно. В perl как минимум.
>> Опять поясни чего ты разбивать хочешь?
> одно большое регулярное выражение
Разбивать куда? Пример желаемого можно?
>> Что есть команды и текст? *, |, [] - это команды? Их ты хочешь отделить от текста? Что значит "групповое отделение"?
> например, один раз сказать, что вот этот кусок - текст, или вот этот кусок - команды
обычно это делается через те же кавычки
> вот такая запись в отличие от стандартного regex-а, и делает разбиение регулярного выражения на три группы с помощью пробелов, и с помощью кавычек отделяет текст от команд:
> '/*' .* '*/'
Предложение интересное. Хз... может что и есть такое, не думал над этим. Может такого нет из-за того, что не стоит писать большие регулярные выражения. Потом, в том же perl, например, можно строки вставлять через переменные - они уже смогут содержать любые символы, хотя для маленьких кусков текста это не будет удобно, наверное.
>> Не пиши большие регекспы, а пиши маленькие и объединяй их потом
> так именно про это я и толкую, что regex - зло, потому что не позволяет так делать.
> т.к. объединять их на уровне своего любимого языка - это многое потерять от регулярных выражений, сразу начинают идти множественные проходы по строке, самому надо разбираться с вариантами, бактракингом и т.д.
Нет, просто ты хочешь от инструмента того, для чего он не предназначен. Наверное они просто так хорошо делает именно свою работу, что хочется их обобщить на близкие задачи.
Ну то есть я хочу сказать, что ты не прав, говоря, что они - зло. Правильнее было бы сказать, что отстойно то, что нет какого-нибудь распространённого общепринятого способа "мультиплексирования" регэкспов. Но сами эти способы, вообще говоря, есть - тот же flex, perl, sed, ...
> соответственно хочется цеплять regex-ы вместе на каком-нибудь спец. мета языке, например, на том же бэкусе-науре
Формы бэкуса-наура трудно представить как сюда подойдут, т.к. они описывают КС-грамматики, а тебе нужно что-то более "линейное". Если тебе КС нужны - то смотри генераторы синтаксических анализаторов. И будет тебе регуляки+КС. Но из-за отсутствия КС в регулярных выражениях, называть их злом ещё более неверно.
Вот сейчас подумал - наверное на sed это реально выглядело бы достаточно просто.
aaa /* 'd/*ee*/d --fff' */ aaa
aaa d --fff' */ aaa
aaa d
И это, по-моему, совершенно правильно. Комменты не бывают вложенными, по крайней мере ни в одном из известных языков мне такого ужаса нет.
Да, и ещё, мне кажется, или твой код вообще-то КС-грамматику разбирает? Он же кавычки парно матчит?
Если что, я его оттестил на разных примерах. Он работает.Проверка:
"\""
~\{/{0,1}?:\^?\$|%\w+(?:\[(?:\d+|(?:"[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*')|\w[\w\d]*|(?:\^?\$|%)\w[\w\d]*(?:\.?(?:\^?\$|%)\w[\w\d]*)*(?:\.\w[\w\d]*)*)\])*(?:\.(?:\^?\$|%)?\w+(?:\[(?:\d+|(?:"[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*')|\w[\w\d]*|(?:\^?\$|%)\w[\w\d]*(?:\.?(?:\^?\$|%)\w[\w\d]*)*(?:\.\w[\w\d]*)*)\])*)*(?:(?:[\+\*\/\%]|(?:-(?!>?:(?:\-?\d+(?:\.\d+)?)|[\$\w\.\+\-\*\/\%\d\>\[\]])*)?:\|@?\w+(?::(?:\w+|(?:\-?\d+(?:\.\d+)?)|?:\^?\$|%\w+(?:\[(?:\d+|(?:"[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*')|\w[\w\d]*|(?:\^?\$|%)\w[\w\d]*(?:\.?(?:\^?\$|%)\w[\w\d]*)*(?:\.\w[\w\d]*)*)\])*(?:\.(?:\^?\$|%)?\w+(?:\[(?:\d+|(?:"[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*')|\w[\w\d]*|(?:\^?\$|%)\w[\w\d]*(?:\.?(?:\^?\$|%)\w[\w\d]*)*(?:\.\w[\w\d]*)*)\])*)*(?:(?:[\+\*\/\%]|(?:-(?!>?:(?:\-?\d+(?:\.\d+)?)|[\$\w\.\+\-\*\/\%\d\>\[\]])*)?)|(?:"[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*'*)*)/{0,1}\}~
geht und slotermeyer?
ja! ba yerhund das oder
die flipperwaldt gespuhrt!
В той версии эскейпов предусмотрено не было, подразумевалось, что кавычки квотятся удвоением. И, кстати, Мадкроз сказал, что прочитал в интернетах, что эскейпов в sql нет, а есть в postgressSQL (хотя в интернетах пишут неправду, да и Мадкроз тоже - - -).
Тем не менее в продвинутой версии я эскейпы добавил.
Хочу ааа ааа.
Мне кажется странным в твоем дизайне, что комментарий не может начинаться внутри строки,
но может в ней заканчиваться. Что строки могут содержать комментарии, когда они - часть
кода, но не могут, когда их самих закомментили. Получается, что или мы не можем закомментить
произвольную часть кода, или не можем иметь комментарии внутри строки.
>Комменты не бывают вложенными, по крайней мере ни в одном из известных языков мне
такого ужаса нет.
В SQL комменты действительно не могут быть вложенными, но вот прозрачны ли там строки -
не знаю. А "такой ужас", как вложенные комменты, есть в том же окамле.
>Да, и ещё, мне кажется, или твой код вообще-то КС-грамматику разбирает?
> Он же кавычки парно матчит?
Встретив кавычку, переходит в состояние Строка и остается в нем до встречи следующей такой
же кавычки. Про КС не скажу, третий курс давно был.
Получается, что или мы не можем закомментитьда, не можем
произвольную часть кода,
Я не хочу начинать флеймвор на такую дурацкую тему, но, по-моему, традиционный парсинг комментов правилен.
Особой пользы от вложенных комментов я не вижу. Двух видов комментов в сочетании с нормальным, позволяющим (un)comment selection редактором вполне хватает на маленькие штуки, а если нужна штука больше, то лучше всё-таки уже воспользоваться специально для этого предназначенной системой контроля версий.
Комменты внутри строк... Ну это вообще маразм, по-моему. Польза крайне сомнительна, зато геморроя добавится немало.
Ну да, кажется, что получилось немножко неортогонально. Если подумать, то ещё очень большой вопрос, знаешь ли, это на самом деле так, или кажется. Ты смотришь на комменты и кавычки и видишь КС-язык типа математических скобок, поэтому несбалансированности тебе кажутся странными. А зачем ты так смотришь? Вложенные кавычки бессмысленны. Нет в них смысла вообще ни одного. Ты их можешь сколько угодно оформлять наподобие операторных скобок, смысл от этого не появится. Вложенные комменты, в общем-то, тоже. Либо код компилируется, либо нет. Ну и получается, что простой конечный автомат, линейно проходящий по тексту и раскрашивающий его в разные "цвета" является вполне удовлетворительной мысленной моделью. Не, остаются, конечно, неудобные нелогичные штуки, вроде нелокальности: поставив кавычку (или коммент) в начале программы ты непредсказуемо и весьма забавно перекрашиваешь её всю. Но КС-грамматика от этого не спасает.
Не очень понял про вложенные кавычки и комменты и мой код. Мой вариант отличается по поведению от твоего только тем, что строки непрозрачны внутри комментов, что строк несколько видов (см. синтаксис PL/SQL и что все обрабатывается за один проход. Вложенных комментов и строк у меня нет. Никаких грамматик, просто конечный автомат.
А, мне просто показалось, что оно у тебя иногда уходит в рекурсию.
Сейчас проверил в MySQL, C# и C++, везде коммент не может начаться внутри строки, но может в ней закончиться.
В смысле если я напишу на c++
i = 0; //hui
то у меня будет ошибка компиляции?
i=0; /* "hui */ " */
то будет.
ну так а чего проверять-то, каммент заканчивается на первых */
я тоже перестал понимать содержание постов в этом топике после регекспа, который запостил пенартур.
Я решил пропустить содержание этих постов
МБ мой регэксп разрушил их мозг?
Теперь хочу проверить код от и .
Что там надо установить подскажите плиз (т.е. что для пых-пыха надо?)
http://stuff.thedeemon.com/nocom2.exe (исходник там же).
Исправил один баг со звездочкой и сделал строки прозрачными внутри комментов, как обсуждали выше. Если после этого будут глюки, то скорее всего из-за отсутствия обработки escape-последовательностей.
Вот еще вариант: Исправил один баг со звездочкой и сделал строки прозрачными внутри комментов, как обсуждали выше. Если после этого будут глюки, то скорее всего из-за отсутствия обработки escape-последовательностей.
Что там надо установить подскажите плиз (т.е. что для пых-пыха надо?)php.net.
Но вообще, у меня сильное подозрение, что мой код может быть с лёгкостью переписан для любого высокоуровнего языка такого типа, например, C# или Java
Возможно, с этим даже справился бы машинный переводчик, даже на тех же регэкспах
Исправленный вариант: http://stuff.thedeemon.com/nocom2.exe (исходник там же).
Пока вопрос закрыт - использую прогу от
Оставить комментарий
0000
Надо из PL/SQL кода почистить, но может от других языков подойдет...Вот правила образования
— дальше строка считается комментарием
/* комментарий внутри */
Зачем:
Дали пакет длиной в пару километров из-за того, что старый код не удалялся, а комментился (это нормально, но не в таком масштабе а так же из-за того, что автор либитель писать вот такое
Хочу почистить код Поиск по инету ничего не дал.