Язык Си в примерах/Простая грамматика: различия между версиями

Содержимое удалено Содержимое добавлено
Нет описания правки
Нет описания правки
Строка 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() {
while(ReadA())int {}c;
if((c=getchar()) != '(') {
ungetc(c);
return 10;
}
//
while(ReadB()) {};
//
if((c=getchar()) != ')') {
ungetc(c);
return 0;
}
return 1;
}
ReadB() {
... // по аналогии с ReadA
while(ReadB()) {};
return 1;
}
ReadS() {