Язык Си в примерах/Простая грамматика: различия между версиями
Содержимое удалено Содержимое добавлено
Greck (обсуждение | вклад) Нет описания правки |
Greck (обсуждение | вклад) Нет описания правки |
||
Строка 4:
описывать с помощью правил. Каждое правило состоит из левой и правой части, между которыми стоит
стрелка (<tt> -> </tt>).
Данную стрелку можно интерпретировать как «представляет собой»
или «состоит из». Например, правило
A -> B C D
можно прочитать как
:«Слово типа A '''представляет собой''' слияние слов типа B, слова типа C и слова типа D.»
Но в теории грамматик принята другая терминология:
:«Из символа A '''можно вывести''' последовательность B, C и D.»
Расмотрим три правила, в которых присутствует только один символ S (точнее один нетерминальный символ), и три терминальных (то есть нераскладываемых, таких символов, из которых ничего нельзя вывести кроме их самих) символов <tt>'0', '1', '2', '3'</tt>:
S -> '0'
Строка 50 ⟶ 67 :
Программный код можно максимально приблизить к самим правилам:
ReadS() {
scanf("%d", &n);
switch(c) {
'0': return 1;
'1': return ReadS();
Строка 58 ⟶ 75 :
'3': return (ReadS() && ReadS() && ReadS());
default: return 0;
}
}
Строка 68 ⟶ 85 :
B -> '[' A* ']'
Вертикальная черта «|» означает соединительный союз «или».
Здесь используется специальный символ
Запись <tt>B*</tt> означает любое количество слов типа <tt>B</tt> (слов, выводимых из символа <tt>B</tt>), либо пустое слово. Другими словами, символ «*» означает 0, 1, 2,... <math>\infty</math> раз.
Есть также специальные символы + и ?:
* <b>*</b> -- 0,1, ..., <math>\infty</math> раз.
Строка 87 ⟶ 104 :
ReadA() {
if((c=getchar()) != '(') {
ungetc(c);
}
//
while(ReadB()) {};▼
//
if((c=getchar()) != ')') {
ungetc(c);
return 0;
}
return 1;
}
ReadB() {
... // по аналогии с ReadA
▲ while(ReadB()) {};
▲ return 1;
}
ReadS() {
|