контекстно-свободная самоописывающаяся грамматика
От: Arsen.Shnurkov  
Дата: 03.03.17 08:42
Оценка:
Помогите, пожалуйста, найти ошибки в коде:

       (* контекстно-свободная самоописывающаяся грамматика *)

(*А*) файл = [ маркер ] , [{ гм , правило }] , гм ;
(*Б*) маркер = "0шДЕ", "0шББ", "0шБЕ" ;
(*В*) гм = [ обм ] ; (* сгруппированное необязательное белое место *)
(*Г*) обм = { ябм | комментарий } ; (* обязательное белое место *)
(*Д*) ябм = { тп | новая строка } ; (* явно белое место *)
(*Е*) тп = { табуляция | пробел } ;
(*Ё*) табуляция = "0ш07" ;
(*Ж*) пробел = "0ш20" ;
(*З*) новая строка = перевод строки | возврат каретки , перевод строки | возврат каретки ;
(*И*) перевод строки = "0ш0А" ;
(*Й*) возврат каретки = "0ш0В" ;
(*К*) комментарий = "(*" , [ { . } ] - "*)" , "*)" ;
(*Л*) знак = 
       десятичная цифра | буква | буква с ударением | знак препинания
       | пробел | перевод строки | возврат каретки  | расширение текстореза ;
(*М*) десятичная цифра = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
(*Н*) буква = "а" | "б" | "в" | "г" | "д" | "е" | "ё" | "ж" | "з" | "и"
       | "й" | "к" | "л" | "м" | "н" | "о" | "п" | "р" | "с" | "т"
       | "у" | "ф" | "х" | "ц" | "ч" | "ш" | "щ" | "ъ" | "ы" | "ь"
       | "э" | "ю" | "я"
       | "А" | "Б" | "В" | "Г" | "Д" | "Е" | "Ё" | "Ж" | "З" | "И"
       | "Й" | "К" | "Л" | "М" | "Н" | "О" | "П" | "Р" | "С" | "Т"
       | "У" | "Ф" | "Х" | "Ц" | "Ч" | "Ш" | "Щ" | "Ъ" | "Ы" | "Ь"
       | "Э" | "Ю" | "Я" ;
(*О*) буква с ударением = "а́" | "е́" | "и́" | "о́" | "у́" | "ы́" | "э́" | "ю́" | "я́"
       | "А́" | "Е́" | "И́" | "О́" | "У́" | "Ы́" | "Э́" | "Ю́" | "Я́"
       | "а̀" | "ѐ" | "ѝ" | "о̀" | "у̀" | "ы̀" | "э̀" | "ю̀" | "я̀"
       | "А̀" | "Ѐ" | "Ѝ" | "О̀" | "У̀" | "Ы̀" | "Э̀" | "Ю̀" | "Я̀"
       ;
(*П*) знак препинания = 
       | "?" | "!" | "." | "…" | "," | ";" | двойная кавычка | "-"
       | "[" | "]" | "{" | "}" | "(" | ")" | "/" | "\"
       | "=" | "+" | "*" | "^" ;
(*Р*) расширение текстореза = "?" , [ { знак - "?" } ] , "?" ;
(*С*) двойная кавычка = "0ш22" ;
(*Т*) правило = имя , гм , "=" , гм , выражение , гм , ";" ;
(*У*) выражение = перечисление , [ { гм , "|" , гм , перечисление } ] ;
(*Ф*) перечисление = выбор , [ { гм , "," , гм , выбор } ] ;
(*Х*) выбор = имя | строка | утаивание | группировка | повторение | исключение | "." ;
(*Ц*) имя = часть имени, [ { тп , часть имени } ] ;
(*Ч*) часть имени = буква , [ { буква | цифра } ] ;
(*Ш*) строка = двойная кавычка , { символ в строке } , двойная кавычка ;
(*Щ*) символ в строке = символ из битов | ( любой символ - двойная кавычка ) ;
(*Ъ*) символ из битов = ( "0б" , 1…16 { двоичная цифра } ) | ( "0ш" , 1…4 { шестнадцатеричная цифра } ) ;
(*Ы*) двоичная цифра = "0" | "1" ;
(*Ь*) шестнадцатеричная цифра = десятичная цифра | "А" | "Б" | "В" | "Г" | "Д" | "Е" ;
(*Э*) любой символ = . ;
(*Ю*) утаивание = "[" , гм , выражение , гм , "]" ;
(*Я*) группировка = "(" , гм , выражение , гм , ")" ;
(*1*) повторение = [ количество повторений , гм  ] , "{" , гм , выражение , гм , "}" ;
      (* если количество повторений не указано, то подразумевается от одного до бесконечности *)
(*2*) количество повторений = диапазон | не менее | не более | десятичное число ;
(*3*) диапазон = десятичное число , гм , "…" , гм , десятичное число ;
(*4*) десятичное число = "0" | ( десятичная цифра - "0" , [ { десятичная цифра } ] ) ;
(*5*) не менее = десятичное число , гм , "…" ;
(*6*) не более = "…" , гм , десятичное число ;
(*7*) исключение = выражение , гм , "-" , гм , выражение ;


https://github.com/ArsenShnurkov/rus_gramm_norm/blob/master/rus_gramm_norm/Grammar/syntax1.ebnf
Отредактировано 10.03.2017 19:40 Arsen.Shnurkov . Предыдущая версия . Еще …
Отредактировано 10.03.2017 5:05 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 5:04 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 5:03 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 4:56 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 4:47 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 0:07 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 09.03.2017 23:47 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 09.03.2017 23:35 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 09.03.2017 23:26 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 09.03.2017 21:59 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 09.03.2017 21:45 Arsen.Shnurkov (добавлено правило про "не менее") . Предыдущая версия .
Отредактировано 09.03.2017 21:30 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 04.03.2017 13:53 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 19:06 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 17:28 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 16:32 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 15:47 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 11:24 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 11:19 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 11:04 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 10:15 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 10:13 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 10:12 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 9:34 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 9:33 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 9:31 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 9:13 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 9:12 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 9:11 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 9:08 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 9:00 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 8:59 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 8:52 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 8:51 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 03.03.2017 8:46 Arsen.Shnurkov . Предыдущая версия .
ebnf
Re: контекстно-свободная самоописывающаяся грамматика
От: Qulac Россия  
Дата: 03.03.17 10:24
Оценка: +1
Да запутано все. Нетерминал "любой символ" определен, а ни где не используется. Должен быть только один нетерминал используемый только в левой части правил — нетерминал самого языка. Типа: C#:=> ....
Программа – это мысли спрессованные в код
Re[2]: контекстно-свободная самоописывающаяся грамматика
От: Arsen.Shnurkov  
Дата: 03.03.17 10:53
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>Да запутано все. Нетерминал "любой символ" определен, а ни где не используется.


в правиле "Т"

Q>Должен быть только один нетерминал используемый только в левой части правил


стартовый нетерминал — "файл".
Отредактировано 03.03.2017 10:59 Arsen.Shnurkov . Предыдущая версия . Еще …
Отредактировано 03.03.2017 10:57 Arsen.Shnurkov . Предыдущая версия .
Re[3]: контекстно-свободная самоописывающаяся грамматика
От: Qulac Россия  
Дата: 03.03.17 10:57
Оценка: 8 (1)
Здравствуйте, Arsen.Shnurkov, Вы писали:

AS>Здравствуйте, Qulac, Вы писали:


Q>>Да запутано все. Нетерминал "любой символ" определен, а ни где не используется.


AS>в правиле "Т"


Q>>Должен быть только один нетерминал используемый только в левой части правил


AS>стартовый нетерминал — "файл". А насчёт того, что он должен быть один — это вызывающе неверное утверждение. Поясни, пожалуйста, что ты хотел сказать.


Нет, он должен быть частью другого правила, более высокого порядка. Типа X:= "любой символ" | тут что-то еще.
Программа – это мысли спрессованные в код
Re[4]: контекстно-свободная самоописывающаяся грамматика
От: Arsen.Shnurkov  
Дата: 03.03.17 10:58
Оценка:
Q>Нет, он должен быть частью другого правила, более высокого порядка. Типа X:= "любой символ" | тут что-то еще.

Ок, правило "Т" следует читать как

(*Т*) символ = любой символ — двойная кавычка | "0ш" , 1*2 { шестнадцатеричная цифра };

Поправил в стартовом сообщении.
Отредактировано 03.03.2017 11:04 Arsen.Shnurkov . Предыдущая версия .
Re: контекстно-свободная самоописывающаяся грамматика
От: Кодт Россия  
Дата: 07.03.17 11:59
Оценка: 10 (1)
Здравствуйте, Arsen.Shnurkov, Вы писали:

AS>Помогите, пожалуйста, найти ошибки в коде:


(*Е*) тп = табуляция
         | пробел , { табуляция | пробел } ;

Кажется, здесь нарушение приоритета.
тп — это или одинокая табуляция, или пробел с последующей серией пробелов и табуляций.

Должно быть
(*Е*) тп = (табуляция|пробел) , {табуляция|пробел} ;


AS>(*Ю*) повторение = [ количество повторений , гм  ] , "{" , гм , выражение , гм , "}" ;
AS>(*Я*) количество повторений = ( не менее , гм , "*" , гм , не более ) | десятичное число ;

Нет красивого способа задавать "не менее N повторений": N{expr}{expr}. Можно было использовать полуинтервал: N*{expr}
Нет пояснения, что без чисел — {expr} — означает от нуля до бесконечности.

(*4*) исключение = выражение , гм , "-" , гм , выражение ;

Плохая семантика, negative lookahead в общем случае. На ровном месте получаем из контекстно-свободной грамматики контекстно-зависимую. Хотя подразумевалась чисто регулярная фишка — классы символов.
Пример:
привет      = "п" , "р" , "и" , "в" , "е" , "т" ;
мир         = "м" , "и" , "р" ;
любое слово =  буква { буква } ;
любые слова = любое слово , { обм , любое слово } ;

привет но не мир = ( привет , обм , любые слова ) - ( любые слова , обм , мир ) ;
Перекуём баги на фичи!
Re[2]: контекстно-свободная самоописывающаяся грамматика
От: Arsen.Shnurkov  
Дата: 09.03.17 21:53
Оценка:
К> нарушение приоритета.

исправил (в исходном сообщении).

К>Нет красивого способа задавать "не менее N повторений"


кажется, поправил.

К> означает от нуля до бесконечности


у меня большое желание сделать от 1 до бесконечности, чтобы можно было писать
[{ . }] вместо 1… { . }
UPD: переделал, теперь от 1 до бесконечности

К>
К>(*4*) исключение = выражение , гм , "-" , гм , выражение ;
К>

К>Плохая семантика, negative lookahead в общем случае.

Чем она плохая? регэкспы же:
http://www.regular-expressions.info/lookaround.html

К> На ровном месте получаем из контекстно-свободной грамматики контекстно-зависимую.


Это специально. я хочу примерно как тут — http://stackoverflow.com/questions/406230/regular-expression-to-match-a-line-that-doesnt-contain-a-word

Мне нужна возможность записывать штуки типа

некий фрагмент = произвольный текст - многосимвольный маркер окончания фрагмента ;


я бы даже сказал:
строковая константа = начало строковой константы, тело строковой константы , конец строковой константы ;
начало строковой константы = двойная кавычка ;
тело строковой константы = [ { символ в строке } ] - конец строковой константы ;
  (* тело строковой константы не должно содержать "конец строковой константы" *)
символ в строке = значимый символ в строке | { бэкслеш , новая строка } ;
значимый символ в строке = . - бэкслеш ;
  (* бекслеши, которые в строке, должны вырезаться, а не превращаться в пробел *)
конец строковой константы = двойная кавычка ;

комментарий = начало комментария, тело комментария , конец комментария ;
начало комментария = [ тп ] , "#" ;
тело комментария = [ { символ комментария } ] - новая строка ;
символ комментария = . ;
  (* бекслеши в комментариях не обрабатываются *)
конец комментария = ; (* пустые правила элиминируются при анализе грамматики *)

(* далее определения пробелов определены таким образом, 
чтобы перенос строки (бекслеш перед концом строки) превращался в пробел *)

ябм = { тп | новая строка | бэкслеш , новая строка } ;
бэкслеш = "\" ;


К>Хотя подразумевалась чисто регулярная фишка — классы символов.


в этой грамматике действительно окончание комментария вида "*)" может быть записано классами символов, да.
А вообще, чем длинее маркер, тем тяжелее писать формулу.

К>Пример:

К>
К>привет      = "п" , "р" , "и" , "в" , "е" , "т" ;
К>мир         = "м" , "и" , "р" ;
К>любое слово =  буква { буква } ;
К>


запятая пропущена перед фигурной скобкой.

К>
К>любые слова = любое слово , { обм , любое слово } ;

К>привет но не мир = ( привет , обм , любые слова ) - ( любые слова , обм , мир ) ;
К>


И ? АА-А-А-А-а-а-а-а! Делать-то что, что делать?

Ещё есть засада в том, что буква с ударением — это не один символ, а двусимвольная строка из основного символа и модификатора.
Отредактировано 10.03.2017 6:29 Arsen.Shnurkov . Предыдущая версия . Еще …
Отредактировано 10.03.2017 5:13 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 5:02 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 4:52 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 4:50 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 4:49 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 4:48 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 4:41 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 4:39 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 4:33 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 4:32 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 4:28 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 4:25 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 0:21 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 0:12 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 0:11 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 10.03.2017 0:05 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 09.03.2017 23:27 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 09.03.2017 22:41 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 09.03.2017 22:03 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 09.03.2017 21:56 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 09.03.2017 21:55 Arsen.Shnurkov . Предыдущая версия .
Re[3]: контекстно-свободная самоописывающаяся грамматика
От: Кодт Россия  
Дата: 10.03.17 11:25
Оценка:
Здравствуйте, Arsen.Shnurkov, Вы писали:

AS>у меня большое желание сделать от 1 до бесконечности, чтобы можно было писать

AS>[{ . }] вместо 1… { . }
AS>UPD: переделал, теперь от 1 до бесконечности

Вот это ещё осталось
(*А*) файл = [ маркер ] , гм , правило , { гм , правило } , гм ;


К>>Плохая семантика, negative lookahead в общем случае.

AS>Чем она плохая? регэкспы же:
AS>http://www.regular-expressions.info/lookaround.html

К>> На ровном месте получаем из контекстно-свободной грамматики контекстно-зависимую.


Плохая только тем, что парсер более тяжеловесный.
Кстати, а без lookahead'а не регулярная ли вообще грамматика получается? В данном конкретном случае, разумеется.
Так-то, понятное дело, у тебя просто альтернативная запись старой доброй БНФ, которая, в общем случае, описывает контекстно-свободные грамматики.

AS>Это специально. я хочу примерно как тут — http://stackoverflow.com/questions/406230/regular-expression-to-match-a-line-that-doesnt-contain-a-word


Ну, если ты знаешь, куда применить лукохеды, то конечно.
Но тогда уж комментарий
комментарий = "(*", [{ . - "*)" }], "*)" ;

Кстати, интересный момент, про исключение. Его можно двояко трактовать:
— сопоставить от текущей позиции левую (положительную) часть и сопоставить её с правой (отрицательной) — в данном случае, очевидно, исключение не произойдёт, т.к. один символ (.) не сопоставится с двумя ("*)")
— сопоставить от текущей позиции правую (отрицательную) часть, и если не сопоставилось, — сопоставить от текущей позиции левую (положительную)

И ещё. Не хватает политики жадности-ленивости. Тот же комментарий на ленивом сопоставлении:
комментарий = "(*", [{ . }~], "*)" ;
расширение текстореза = "?", [{ знак }~], "?"

Не понял, что такое расширение текстореза, в твоей грамматике оно не используется, но раз "?" задействован, то для ленивости можно припахать суффикс "~" вместо классического "?".
А делать суффикс или префикс, тут я в задумчивости. Это надо смотреть, что удобнее для разбора и интерпретации.

Ну и если отрицательный лукохед есть, то почему бы и остальные не припахать? Сгорел сарай, гори и хата!

К>>Пример:

К>>
К>>привет      = "п" , "р" , "и" , "в" , "е" , "т" ;
К>>мир         = "м" , "и" , "р" ;
К>>любое слово =  буква { буква } ;
К>>

AS>запятая пропущена перед фигурной скобкой.

Ну, это я так, эскиз написал. Кстати, а зачем такая туча запятых? Чем "оператор пробел" не нравится?

К>>
К>>привет но не мир = ( привет , обм , любые слова ) - ( любые слова , обм , мир ) ;
К>>

AS>И ? АА-А-А-А-а-а-а-а! Делать-то что, что делать?

Ничего не делать. Просто знать о том, что лукохеды могут очень жёстко просадить производительность.
Сделать квадратичную — легко. Сделать кубическую — чуть сложнее (двойное отрицание). Экспоненту или факториал — тут помощник нужен (надо подумать, возможно ли вообще).

AS>Ещё есть засада в том, что буква с ударением — это не один символ, а двусимвольная строка из основного символа и модификатора.


Вот поэтому движки регекспов особым образом поддерживают юникод.
Тем более, что там бывают и мультибайтные кодировки, и композитные символы, набранные из основного символа и пачки модификаторов.
Перекуём баги на фичи!
Re[4]: контекстно-свободная самоописывающаяся грамматика
От: Arsen.Shnurkov  
Дата: 10.03.17 20:24
Оценка:
К> Не понял, что такое расширение текстореза

там

К> Чем "оператор пробел" не нравится?


там же.

К> лукохеды могут очень жёстко просадить производительность. Сделать квадратичную — легко. Сделать кубическую — чуть сложнее (двойное отрицание).


нет. при ненаивной реализации можно обеспечить линейную. И ненадо меня убеждать, что нельзя.
Re[4]: контекстно-свободная самоописывающаяся грамматика
От: Arsen.Shnurkov  
Дата: 10.03.17 21:11
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Arsen.Shnurkov, Вы писали:


AS>>у меня большое желание сделать от 1 до бесконечности, чтобы можно было писать

AS>>[{ . }] вместо 1… { . }
AS>>UPD: переделал, теперь от 1 до бесконечности

Перечитал исходный стандарт. Понял, что моя семантика операции "-" отличается от той, которая в стандарте.

Делать [{}] было не обязательно, потому что уже есть эквивалент
{.}-,

(т.е. от нуля до бесконечности, но без нуля)

поэтому я лучше минус сделаю как в стандарте (точное несовпадение правой части), а для своей операции буду вместо минуса использовать ~(не должно содержать правой части).

Про ленивость я не осознаю на данный момент.
Re[4]: контекстно-свободная самоописывающаяся грамматика
От: Arsen.Shnurkov  
Дата: 10.03.17 21:50
Оценка:
К> особым образом поддерживают

Образ я бы тоже хотел обсудить. Только не юникод, а директивы Include.
Получается, что с одной стороны, сама директива описывается КС-грамматикой (в частном случае регэкспом),
а с другой стороны, она вытягивает целое AST-дерево из другого файла.
Когда я об этом думаю, меню клинит (неясно, как это оформить кодом C#).

Мне тут подсказывают: "паттерн, паттерн используй". Компоновщик, итератор. Но клинит всё равно.
Re[5]: контекстно-свободная самоописывающаяся грамматика
От: Кодт Россия  
Дата: 13.03.17 09:52
Оценка:
Здравствуйте, Arsen.Shnurkov, Вы писали:

К>> Не понял, что такое расширение текстореза

AS>там

Оригинально перевёл special sequence!

К>> Чем "оператор пробел" не нравится?


AS>там же.


То есть, выбирая между слитно_записываемыми_идентификаторами и , идентификаторами с пробелами внутри , и , явной , разбивкой , на , лексемы , — был сделан выбор в пользу второго. Ну хозяин барин.

К>> лукохеды могут очень жёстко просадить производительность. Сделать квадратичную — легко. Сделать кубическую — чуть сложнее (двойное отрицание).

AS>нет. при ненаивной реализации можно обеспечить линейную. И ненадо меня убеждать, что нельзя.

Есть что почитать на эту тему? Или на пальцах объяснить?
Перекуём баги на фичи!
Re[5]: контекстно-свободная самоописывающаяся грамматика
От: Кодт Россия  
Дата: 13.03.17 10:09
Оценка:
Здравствуйте, Arsen.Shnurkov, Вы писали:

AS>Про ленивость я не осознаю на данный момент.


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

С жадностью придётся реализовывать ленивость вручную. По сути, ленивость — это такой неявный негативный лукохед: "если можешь сматчить следующий за квантификатором кусок, то всё, стоп!"
А если нет произвольного негативного лукохеда, а только строгое неравенство (классы символов — это частный случай), то ещё и его придётся руками расписать:
/.*?abc/

{ . - "a"
| "a" , . - "b"
| "ab" , . - "c"
}
"abc"

{ . - "a"
| "a" , ( . - "b"
        | "b" , ( . - "c" )
        )
}
"abc"
Перекуём баги на фичи!
Re[5]: контекстно-свободная самоописывающаяся грамматика
От: Кодт Россия  
Дата: 13.03.17 10:10
Оценка:
Здравствуйте, Arsen.Shnurkov, Вы писали:

К>> особым образом поддерживают


AS>Образ я бы тоже хотел обсудить. Только не юникод, а директивы Include.

AS>Получается, что с одной стороны, сама директива описывается КС-грамматикой (в частном случае регэкспом),
AS>а с другой стороны, она вытягивает целое AST-дерево из другого файла.
AS>Когда я об этом думаю, меню клинит (неясно, как это оформить кодом C#).

AS>Мне тут подсказывают: "паттерн, паттерн используй". Компоновщик, итератор. Но клинит всё равно.


Какие директивы Include? Это ты про что?
Перекуём баги на фичи!
Re[4]: контекстно-свободная самоописывающаяся грамматика
От: Arsen.Shnurkov  
Дата: 16.03.17 02:43
Оценка:
К> Ну, если ты знаешь, куда применить лукохеды, то конечно.

Рассмотрим файл, состоящий из директив двух видов:

include_directive = include_keyword , iws , include_path ;
include_keyword = ("i" | "I") , ("n" | "N") , ("c" | "C") , ("l" | "L") , ("u" | "U") , ("d" | "D") , ("e" | "E") ;
include_path = [ slash | backslash ] , part_of_path , { ( slash | backslash ) , part_of_path } , [ slash | backslash ] ;

other_directive = other_keyword, { other_directive_fragment } ;
other_keyword = ( other_directive_fragment — ( space | tab ), { other_directive_fragment — ( space | tab ) } ) — include_keyword ;
other_directive_fragment = . — ( cr | lf ) ;

Как, по-твоему, описать любую другую директиву, отличную от директивы Include ?

Если расписывать по буквам вручную, как ты выше предлагаешь,
то во что превратится этот процесс, если станет две директивы типа "include"? а если семь?
Отредактировано 16.03.2017 10:13 Arsen.Shnurkov . Предыдущая версия . Еще …
Отредактировано 16.03.2017 2:50 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 2:45 Arsen.Shnurkov . Предыдущая версия .
Re[6]: контекстно-свободная самоописывающаяся грамматика
От: Arsen.Shnurkov  
Дата: 16.03.17 03:04
Оценка:
К> То есть, выбирая между слитно_записываемыми_идентификаторами и , идентификаторами с пробелами внутри , и , явной , разбивкой , на , лексемы , — был сделан выбор в пользу второго. Ну хозяин барин.

Вариант синтаксиса без запятых — это ABNF из rfc 5234:
3.1.  Concatenation:  Rule1 Rule2


Если EBNF, то по стандарту только с запятыми.

название EBNF является более распиаренным, поэтому я выбрал вариант с запятыми.
Отредактировано 16.03.2017 4:17 Arsen.Shnurkov . Предыдущая версия . Еще …
Отредактировано 16.03.2017 3:36 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 3:36 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 3:09 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 3:08 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 3:06 Arsen.Shnurkov . Предыдущая версия .
Re[6]: контекстно-свободная самоописывающаяся грамматика
От: Arsen.Shnurkov  
Дата: 16.03.17 03:16
Оценка:
К> Какие директивы Include? Это ты про что?

рассмотрим класс Apache2 с двумя статическими методами
class Apache2 {
    public static string LoadConfig (string filename)
    {
       // парсим файл и ищем маски
       // вызываем LoadConfigsByMask()
       // вставляем строки вместо интервалов с директивами
       // возвращаем итоговую строку
    }
    public static string LoadConfigsByMask(string filemask)
    {
       // ищем файлы по маске
       // каждый файл читаем функцией LoadConfig()
       // склеиваем строки
       // результат возвращаем
    }
}


Тут плохо то, что:
1) потом после получения сконкатенированного контента парсить прийдётся ещё раз (по другой грамматике);
2) теряется информация про исходное положение символов в разных файлах (нужно не строки возвращать, а что-то более сложное).

Хотелось бы как-то учитывать результаты первого парсинга во время второго, чтобы повысить эффективность.

Допустим, что изменим прототипы методов, чтобы они возвращали узлы деревьев:
public static Pair<FileInfo,Node> LoadConfig (string filename)
public static List<Pair<FileInfo,Node>> LoadConfigsByMask (string filename)

Но тогда не ясно, что делать с узлами, описывающими директивы Include. Заменять их непосредственно нежелательно (потеряется информация о текстовом представлении директивы Include), значит список надо записывать в атрибут (аттрибутированная грамматика) узла Include.
но тогда, получается, что нужен какой-то дополнительный итератор, который учитывал бы, что могут существовать директивы Include.
Либо можно поступить наоборот — заменить узлы, а информацию об Include переместить в атрибут...

Или построить второе дерево из узлов типа MetaNode, каждый из которых будет ссылаться на свой Node, и работать уже с тем новым деревом.

Отдельная идея — не очень здо́рово хранить всё целиком в памяти, если можно обрабатывать по частям (DOM vs SAX). То есть, это неправильно, возвращать все узлы. Вместо этого надо возвращать итератор.

В общем, нет ясности как надо делать.
Отредактировано 16.03.2017 4:35 Arsen.Shnurkov . Предыдущая версия . Еще …
Отредактировано 16.03.2017 4:31 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 4:30 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 4:29 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 4:27 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 4:12 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 4:08 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 4:04 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 4:03 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 3:19 Arsen.Shnurkov . Предыдущая версия .
Отредактировано 16.03.2017 3:19 Arsen.Shnurkov . Предыдущая версия .
Re[5]: контекстно-свободная самоописывающаяся грамматика
От: Кодт Россия  
Дата: 16.03.17 10:49
Оценка:
Здравствуйте, Arsen.Shnurkov, Вы писали:

AS>Как, по-твоему, описать любую другую директиву, отличную от директивы Include ?


AS>Если расписывать по буквам вручную, как ты выше предлагаешь,

AS>то во что превратится этот процесс, если станет две директивы типа "include'? а если семь?

Тут проще ввести фактор приоритетности, — жадность/ленивость и отсечки.
Не знаю, как это на БНФ записать, — на регекспах это атомарные группы (?>blablabla)
Ну как-то так будет
directive = include_keyword, !, space, valid_path
          | exclude_keyword, !, space, valid_path
          | everything_else
          ;

Или вот так
directive = some_include | some_exclude | everything_else;

some_include = good_include | bad_include;
good_include = include_keyword, space, valid_path;
bad_include  = include_keyword, ERROR_BEGINS_HERE, bullshit_till_end_of_sentence, ERROR_ENDS_HERE;

(* или так *)
some_include = include_keyword,
               ( space, valid_path, {space}, [ unexpected ]
               | unexpected
               ),
               LOOKAHEAD_end_of_sentence; (* сопоставляется, но не съедает, признак конца *)

unexpected = ERROR_BEGINS_HERE,                 (* сопоставляется с пустой строкой, служит признаком для парсера *)
             bullshit_till_the_end_of_sentence,
             ERROR_ENDS_HERE;                   (* то же самое *)

bullshit_till_the_end_of_sentence = {.}, LOOKAHEAD_end_of_sentence;
(* или в более сложных случаях, может проглатывать парные скобки, если признак конца фразы может встретиться внутри фразы, под скобками) *)

Заодно научишь парсер восстанавливаться после ошибок.
Перекуём баги на фичи!
Re[6]: контекстно-свободная самоописывающаяся грамматика
От: Arsen.Shnurkov  
Дата: 16.03.17 11:00
Оценка:
К>Тут проще ввести фактор приоритетности

Не проще. Эти директивы могут быть в разных местах,
пример — https://github.com/ArsenShnurkov/Pliant-test-for-include/blob/4b784d2a960ba1d1d07e711c1c4328447a2482a3/main/Grammar/syntax6.ebnf
Re[6]: контекстно-свободная самоописывающаяся грамматика
От: Arsen.Shnurkov  
Дата: 05.04.17 00:23
Оценка:
К>Ну, можно просто задекларировать, что все операции повторения ленивые.
К>С жадностью придётся реализовывать ленивость вручную. По сути, ленивость — это такой неявный негативный лукохед: "если можешь сматчить следующий за квантификатором кусок, то всё, стоп!"

Ленивость, negative/positive lookahead, и то что мне нужно — это три разные вещи.

Почему не подойдёт ленивость, расписано тут —
https://learn.javascript.ru/regexp-greedy-and-lazy

вот это то что мне надо (только мне надо без расписывания):

К> если нет произвольного негативного лукохеда, а только строгое неравенство (классы символов — это частный случай), то ещё и его придётся руками расписать:

К>
К>/.*?abc/

К>{ . - "a"
К>| "a" , . - "b"
К>| "ab" , . - "c"
К>}
К>"abc"

К>{ . - "a"
К>| "a" , ( . - "b"
К>        | "b" , ( . - "c" )
К>        )
К>}
К>"abc"
К>


Т.е. прийдётся определить дополнительный синтаксис специально под мою операцию, а потом думать, как её разворачивать "как руками".
Это проблема, потому что неразрешима задача определения того, является ли КС-грамматика регулярной.
Отредактировано 05.04.2017 7:10 Arsen.Shnurkov . Предыдущая версия . Еще …
Отредактировано 05.04.2017 0:27 Arsen.Shnurkov . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.