forked from jkubin/m4root
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathintro.mc
1789 lines (1470 loc) · 81.1 KB
/
intro.mc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
__HEADER([Josef Kubin], [2019/12/03], [m4root])
___DESCR([the introductory part])
VERSION(0, 0, 0)
CAPTION([dnl czech
[SERIES_NAME: úvod],
dnl english: _next_language_
[SERIES_NAME: introduction],
])
PEREX_IMG([img/m4tux.png], [https://i.iinfo.cz/images/154/m4tux-1-prev.png])
PEREX([defn([PEREX_CS])[dnl czech
Úvodní díl seriálu obsahuje jeho historii, základní principy jazyka, příklady použití a[]NB()nutné předpoklady pro jeho zvládnutí.
],
defn([PEREX_EN])[dnl english: _next_language_
The introductory part of the series contains its history, the basic principles of language, examples of usage and prerequisites for its mastery.
]])
CHAPTER([dnl czech
[Úvod],
dnl english: _next_language_
[Introduction],
])
PARA([[dnl czech
Čtenáři tohoto seriálu se naučí psát skripty pro strojové generování kódu.
Strojově generovaný kód může být libovolně složitý a[]NB()může obsahovat další vnitřní závislosti.
Vzájemně závislé soubory se složitým kódem jsou pro člověka jen těžce udržitelné v[]NB()konzistentním stavu.
Je už nutné použít nějaký mechanismus pro generování kódu.
Generování kódu provádí nástroj určený pro transformaci textu – BO([makro procesor]).
],
[dnl english: _next_language_
Readers of this series will learn how to write scripts for machine code generation.
The machine-generated code can be arbitrarily complex and can contain other internal dependencies.
Interdependent files with complex code are hardly sustainable for humans in a[]NB()consistent state.
It is necessary to use some code generation mechanism.
The code generation is performed by a[]NB()tool for text transformation – BO([a[]NB()macro processor]).
]])
PARA([what_is_the_series_about], [[dnl czech
Seriál je zaměřen na praktické použití BO([univerzálního makro procesoru M4]) (dále jen M4) pomocí malých příkladů.
Popisuje také teoretický základ všech implementací.
Cílem seriálu je seznámit čtenáře s[]NB()tímto SPAN([nástrojem], [m4 – je program příkazové řádky], [dot]) a[]NB()také programovacím SPAN([jazykem], [M4 – je programovací jazyk], [dot]).[]BR()
LINK([Na co se používá], [main_uses_of_m4]), jak se v[]NB()něm programuje a[]NB()jaké jsou jeho LINK([výhody], [why_to_use_m4]) a[]NB()LINK([nevýhody], [why_not_use]).
],
[dnl english: _next_language_
The series focus on the practical use of the BO([universal macro processor M4]) (hereafter M4) using small examples.
It also describes the theoretical part of all its implementations.
The aim of the series is to acquaint the reader with this SPAN([tool], [m4 – is a command line program], [dot]) and also the programming SPAN([language], [M4 – is a programming language], [dot]).
LINK([What is it used for], [main_uses_of_m4]), how to program in it and its LINK([advantages], [why_to_use_m4]) and LINK([disadvantages], [why_not_use]).
]])
# same tip box for each part
the_series_is_generated()
PARA([[dnl czech
Úvodní díl popisuje základní principy jazyka na jednoduchých příkladech.
Všechny příklady používají přepisovací pravidla LINK([bezkontextové gramatiky], [context_free_grammar]).
Později se naučíme používat LINK([výstupní fronty], [output_queues]),
LINK([automaty], [automata_descr]), asociativní paměti, zásobníky a[]NB()zásobníkové automaty.
Naučíme se také psát LINK([testovací automaty], [testing_automaton]) pro testování vstupních dat.
],
[dnl english: _next_language_
The introductory part describes the basic principles of the language with simple examples of use.
All examples use rewriting rules of LINK([context-free grammar], [context_free_grammar]).
Later we will learn how to use LINK([output queues], [output_queues]),
LINK([automata], [automata_descr]), associative memories, stacks and pushdown automata.
We will also learn how to write LINK([testing automata], [testing_automaton]) to test input data.
]])
SECT1([dnl czech
[Příklady pro čtenáře],
dnl english: _next_language_
[Examples for readers],
])
PARA([[dnl czech
Příklady pro čtenáře tvoří komplementární část seriálu a[]NB()budou do jisté míry vytvářeny na základě podnětů v[]NB()diskuzi pod článkem.
Na začátku každého dílu je popsána nějaká část jazyka M4 doplněná sadou příkladů na konci.
Každý díl je možné číst v[]NB()libovolném pořadí.
],
[dnl english: _next_language_
The examples are a[]NB()complementary part of the series and will be based to some extent on the discussion below the article.
At the beginning of each episode, some parts of the M4 language will be described and supplemented with a[]NB()set of examples at the end.
Each part can be read in any order.
]])
ITEMIZEDLIST_WRAP([
LISTITEM_MONO([[LINK([code_generation_examples], [code_generation_examples])]])
LISTITEM_MONO([[LINK([preproc_examples], [preproc_examples])]])
LISTITEM_MONO([[LINK([m4_on_examples], [m4_on_examples])]])
LISTITEM_MONO([[LINK([questions_and_answers], [questions_and_answers])]])
LISTITEM([dnl czech
[AH([http://github.com/jkubin/m4root], defn([SERIES_NAME]), [http://github.com/jkubin/m4root]) – složitější projekt generující HTML5 tohoto seriálu],
dnl english: _next_language_
[AH([http://github.com/jkubin/m4root], defn([SERIES_NAME]), [http://github.com/jkubin/m4root]) – a[]NB()project generating HTML5 of this series],
])
])dnl ITEMIZEDLIST_WRAP
CHAPTER([dnl czech
[Historie makro jazyků],
dnl english: _next_language_
[History of macro languages],
])
PARA([[dnl czech
Makro jazyky byly vynalezeny v[]NB()době, kdy dominoval jazyk symbolických adres – ABBR([JSA], [Jazyk Symbolických Adres – assembler]).
Zdrojový kód JSA velmi často obsahuje shodné sekvence instrukcí odlišující se pouze hodnotami operandů.
Shodné sekvence instrukcí je možné seskupit do jednoho slova, nebo-li BO([makro instrukce]).
Jméno obvykle popisuje účel skryté sekvence instrukcí.
Makro instrukce se přeloží makro procesorem na původní sekvenci instrukcí, která se posléze přeloží do spustitelného strojového kódu.
Programování v[]NB()JSA pomocí makro instrukcí je jednodušší, rychlejší a[]NB()méně náchylné k[]NB()lidským chybám.
],
[dnl english: _next_language_
Macro languages were invented when the assembly language (ASM) dominated.
ASM source code usually contains identical instruction sequences that differ only in operand values.
Identical instruction sequences can be grouped into one word or a[]NB()BO([macro instruction]).
The name usually describes the purpose of the hidden sequence of instructions.
These macro instructions are translated by the macro processor to the original instruction sequences, which are then translated into the executable machine code.
Programming in ASM using macro instructions is simpler, faster and less prone to human errors.
]])
PARA([[dnl czech
Později byly makro jazyky použity k[]NB()rozšíření kompilovaných programovacích jazyků, protože umožnily psát zdrojový kód na vyšší úrovni abstrakce než jakou poskytuje samotný programovací jazyk.
Rychlost, výkonnost a efektivita složitého programovacího jazyka nižší úrovně je zachována díky makro jazykům.
Avšak je důležité dobře rozumět všem vrstvám kódu.
],
[dnl english: _next_language_
Later, macro languages were used to extend compiled programming languages because they made it possible to write a source code at the higher level of abstraction than offered by the programming language itself.
The speed, performance and efficiency of a[]NB()complex lower-level programming language is maintained through macro languages.
However, it is important to understand all layers of code well.
]])
BRIDGEHEAD_MONO([dnl monolingual
[GPM (General Purpose Macro-generator)],
])
PARA([[dnl czech
Základní myšlenku přepisování textových řetězců s[]NB()argumenty, které se přepíší do dalších rekurzivně přepisovatelných řetězců, představil
AH([PERSON([Christopher Strachey])], [Wikipedie], [https://en.wikipedia.org/wiki/Christopher_Strachey]) ve svém
ABBR([GPM], [General Purpose Macro-generator])[]REF([A[]NB()General Purpose Macro-generator], [Computer Journal 8, 3 (1965), 225–41], [http://dx.doi.org/10.1093/comjnl/8.3.225]) v[]NB()roce 1965.
Další generace makro procesorů M3 a[]NB()M4 původní ABBR([GPM], [General Purpose Macro-generator]) v[]NB()podstatě už jen rozšiřovaly.
Základní myšlenka původního návrhu ale zůstala stejná.
],
[dnl english: _next_language_
AH([PERSON([Christopher Strachey])], [Wikipedia], [https://en.wikipedia.org/wiki/Christopher_Strachey]) introduced the basic idea of rewritable strings with arguments which recursively rewrite to other strings in his
ABBR([GPM], [General Purpose Macro-generator])[]REF([A[]NB()General Purpose Macro-generator], [Computer Journal 8, 3 (1965), 225–41], [http://dx.doi.org/10.1093/comjnl/8.3.225]) in 1965.
The next generation of M3 and M4 macro processors basically just expanded the original ABBR([GPM], [General Purpose Macro-generator]).
The basic idea of the original proposal remained the same.
]])
BRIDGEHEAD_MONO([dnl monolingual
[M3],
])
PARA([[dnl czech
AH([PERSON([Dennis Ritchie])], [Wikipedie], [https://cs.wikipedia.org/wiki/Dennis_Ritchie]) převzal základní myšlenku ABBR([GPM], [General Purpose Macro-generator]) a[]NB()napsal vylepšený makro procesor pro generování zdrojového kódu programovacího jazyka C (1972), který sám navrhl.
Nový BUN([m])akro procesor napsal pro minipočítač AP-BUN([3]) – odtud jméno BO([M3]).
Tento přímý předchůdce současného M4 dokázal výrazně ušetřit těžkou a[]NB()časově náročnou práci, čímž zaujal vývojáře programující v[]NB()jiných jazycích (ABBR([FORTRAN], [FORmula TRANslation]), ABBR([COBOL], [COmmon Business-Oriented Language]), ABBR([PL/I], [Programming Language One]), …).
Vývojáři upravovali M3 pro tyto jazyky čímž ho proměnili na univerzálně použitelný makro procesor M4.
],
[dnl english: _next_language_
AH([PERSON([Dennis Ritchie])], [Wikipedia], [https://en.wikipedia.org/wiki/Dennis_Ritchie]) took over the basic idea of ABBR([GPM], [General Purpose Macro-generator]) and wrote an improved macro processor for generating source code of C[]NB()(1972) language, which he himself designed.
The new BUN([m])acro processor was written for the minicomputer AP-BUN([3]) – hence the name BO([M3]).
This direct ancestor of the current M4 managed to significantly save heavy and time-consuming work and attract developers programming to other languages (ABBR([FORTRAN], [FORmula TRANslation]), ABBR([COBOL], [COmmon Business-Oriented Language]), ABBR([PL/I], [Programming Language One]), …).
Developers have customized M3 for these languages turning it into a[]NB()universally usable M4 macro processor.
]])
NOTE_WRAP(, [m4 ∈ ]LANG([{množina nástrojů UNIX-u}], [{set of UNIX tools}]), [
PLAIN_TEXT([[dnl czech
PERSON([Dennis Ritchie]) byl také spolutvůrcem operačního systému UNIX a[]NB()proto:
],
[dnl english: _next_language_
PERSON([Dennis Ritchie]) was also a[]NB()co-creator of UNIX and therefore:
]])
ITEMIZEDLIST_WRAP([
LISTITEM([[dnl czech
M4 je minimalistický a[]NB()rychlý, AH([dělá jednu věc a[]NB()tu dělá dobře], [Filosofie UNIX-u], [https://cs.wikipedia.org/wiki/Filosofie_Unixu])
],
[dnl english: _next_language_
M4 is minimalist and fast, AH([it does one thing and it does well], [UNIX philosophy], [https://en.wikipedia.org/wiki/Unix_philosophy])
]])
LISTITEM([[dnl czech
výhradně spoléhá na neinteraktivní rozhraní příkazové řádky
],
[dnl english: _next_language_
it relies solely on the non-interactive command line interface
]])
LISTITEM([[dnl czech
parametry a[]NB()závislosti M4 skriptů popisuje CODE([Makefile])
],
[dnl english: _next_language_
parameters and dependencies of M4 scripts are described by CODE([Makefile])
]])
LISTITEM([[dnl czech
znakem CODE_M4([#]) začíná jednořádkový komentář jako v[]NB()UNIX-ovém shell-u
],
[dnl english: _next_language_
the CODE_M4([#]) character begins with a[]NB()one-line comment like in a[]NB()UNIX shell
]])
LISTITEM([[dnl czech
proměnné CODE([$[@]]), CODE([$[*]]), CODE([$[#]]), CODE([$[0]]), CODE([$[1]]), CODE([$[2]]), … mají podobný význam jako v[]NB()shell-u
],
[dnl english: _next_language_
variables CODE([$[@]]), CODE([$[*]]), CODE([$[#]]), CODE([$[0]]), CODE([$[1]]), CODE([$[2]]), … have similar meanings as in a[]NB()UNIX shell
]])
LISTITEM([[dnl czech
oddělovač argumentů je čárka
],
[dnl english: _next_language_
the argument delimiter is comma
]])
])dnl ITEMIZEDLIST_WRAP
])dnl NOTE_WRAP
PARA([[dnl czech
Makro procesor M3 rozšířil také PERSON([Jim E. Weythman]), autor programové konstrukce, která se používá téměř v[]NB()každém M4 skriptu:
],
[dnl english: _next_language_
The M3 macro processor was also extended by PERSON([Jim E. Weythman]), the author of program construction, which is used in almost every M4 script:
]])
PROGRAMLISTING(, LANG([idiomatický kód M4], [idiomatic M4 code]), [[
divert(-1)
…
define(…)
…
divert(0)dnl
…
]])dnl PROGRAMLISTING
NOTE([[dnl czech
Klíčové slovo CODE([[divert](AH([ℤ], [celé číslo], [https://cs.wikipedia.org/wiki/Cel%C3%A9_%C4%8D%C3%ADslo]))], [divert(-1), divert(0), divert(1), …, divert(2147483647)], [dot]) přepíná výstupní fronty.
Argument CODE([-1]) zcela vypne jakýkoliv textový výstup.
Argument CODE([0]) přepne výstup na CODE_M4([stdout]) (standardní výstup).
],
[dnl english: _next_language_
The CODE([[divert](AH([ℤ], [integer], [https://en.wikipedia.org/wiki/Integer]))], [divert(-1), divert(0), divert(1), …, divert(2147483647)], [dot]) keyword switches output queues.
Argument CODE([-1]) completely disables any text output.
Argument CODE([0]) switches output to CODE([stdout]) (standard output).
]])
BRIDGEHEAD_MONO([dnl monolingual
[M4],
])
PARA([[dnl czech
AH([PERSON([Brian Kernighan])], [Wikipedie], [https://cs.wikipedia.org/wiki/Brian_Kernighan]) makro procesor M3 rozšířil na AH([preprocesor], [Wikipedie], [https://cs.wikipedia.org/wiki/Preprocesor]) jazyka FORTRAN 66,
aby mohl vytvořit hybridní jazykovou nadstavbu pojmenovanou ABBR([BO([RATFOR])], [RATional FORtran])[]REF([RATFOR — A Preprocessor for a Rational Fortran], [Brian W. Kernighan], [https://wolfram.schneider.org/bsd/7thEdManVol2/ratfor/ratfor.pdf]).
Základní programové konstrukce této nadstavby (podmínky, cykly) jsou stejné jako v[]NB()jazyce C.
Programování v[]NB()RATFOR-u se tak podobá programování v[]NB()QUOTE([céčku]).
Makro procesor zdrojový kód překládá zpátky do FORTRAN-u, poté kompilátor provede překlad do strojového kódu.
],
[dnl english: _next_language_
AH([PERSON([Brian Kernighan])], [Wikipedia], [https://en.wikipedia.org/wiki/Brian_Kernighan]) has enhanced the M3 macro processor to the FORTRAN 66
AH([preprocessor], [Wikipedia], [https://en.wikipedia.org/wiki/Preprocessor]) to create a[]NB()hybrid language extension named ABBR([BO([RATFOR])], [RATional FORtran])[]REF([RATFOR — A Preprocessor for a Rational Fortran], [Brian W. Kernighan], [https://wolfram.schneider.org/bsd/7thEdManVol2/ratfor/ratfor.pdf]).
The basic program constructions of this extension (conditions, cycles) are the same as in C[]NB()language.
Programming in RATFOR is similar to C[]NB()programming.
The macro processor converts the source code back to FORTRAN, then the compiler performs the usual compilation to machine code.
]])
NOTE_WRAP([], LANG([jazyk M4 doplňuje jazyk C], [M4 language complements C language]), [
PLAIN_TEXT([[dnl czech
Všimněte si LINK([téměř dokonalé symbiózy], [cpp_and_m4]) s[]NB()jazykem C
],
[dnl english: _next_language_
Note the LINK([almost perfect symbiosis], [cpp_and_m4]) with the C[]NB()language:
]])
ITEMIZEDLIST_WRAP([
LISTITEM([[dnl czech
direktivy ABBR([CPP], [Preprocesor jazyka C]) CODE_M4([#define]), CODE_M4([#include]), CODE_M4([#ifdef]), … jsou pro M4 komentáře
],
[dnl english: _next_language_
ABBR([CPP], [C preprocessor]) directives CODE_M4([#define]), CODE_M4([#include]), CODE_M4([#ifdef]), … are comments for M4
]])
# LI([této vlastnosti využívají LINK([bezpečnější makra], [safer_macros]) definovaná uživatelem])
# LI([this feature uses LINK([safer user-defined macros], [safer_macros])])
LISTITEM([[dnl czech
klíčová slova oddělená od závorek mezerou, ztrácí svůj původní význam
UL([
LI([M4 například ignoruje funkci CODE_M4([void define (char c, int i) {…}])])
])
],
[dnl english: _next_language_
most keywords separated from parentheses by a[]NB()white character lose meaning
UL([
LI([for example, M4 ignores CODE_M4([void define (char c, int i) {…}])])
])
]])
LISTITEM([[dnl czech
argumenty maker oddělují čárky stejně jako argumenty funkcí jazyka[]NB()C
UL([
LI([je-li definováno makro CODE_M4([FUNC(char c, int i)]), jeho proměnné jsou:[]BR()
CODE([$[#] → 2]), CODE([$[0] → FUNC]), CODE([$[1] → char c]), CODE([$[2] → int i])
])
])dnl UL
],
[dnl english: _next_language_
macro arguments separate commas just like commas in C[]NB()functions
UL([
LI([if the CODE_M4([FUNC(char c, int i)]) macro is defined, its variables are:[]BR()
CODE([$[#] → 2]), CODE([$[0] → FUNC]), CODE([$[1] → char c]), CODE([$[2] → int i])
])
])dnl UL
]])
LISTITEM([[dnl czech
BO([levý]) LINK([řídící znak], [expansion_control]) CODE([LQ()]) pro neterminály není součástí syntaxe rodiny jazyků[]NB()C
],
[dnl english: _next_language_
BO([the left]) LINK([control character], [expansion_control]) CODE([LQ()]) is not a[]NB()part of the C[]NB()family syntax
]])
LISTITEM([[dnl czech
BO([pravý]) řídící znak CODE([']) nevadí, není-li součástí makra
UL([LI([oba řídící znaky lze skrýt do uživatelsky definovaných maker CODE_M4([LQ()]), CODE_M4([RQ()])])])
],
[dnl english: _next_language_
BO([the right]) control character CODE([']) does not matter if it is not part of the macro[]BR()
UL([LI([both control characters can be hidden into user-defined macros CODE_M4([LQ()]), CODE_M4([RQ()])])])
]])
LISTITEM([[dnl czech
makra se píší CODE([VELKYMI_PISMENY]), stejně jako AH([neterminální symboly], [Wikipedie], [https://cs.wikipedia.org/wiki/Termin%C3%A1ln%C3%AD_a_netermin%C3%A1ln%C3%AD_symbol])
UL([LI([tím je vymezen jejich jmenný prostor])])
],
[dnl english: _next_language_
macros are written CODE([IN_UPPERCASE]), just like AH([nonterminal symbols], [Wikipedia], [https://en.wikipedia.org/wiki/Terminal_and_nonterminal_symbols])
UL([LI([this delimits their namespace])])
]])
])dnl ITEMIZEDLIST_WRAP
])dnl NOTE_WRAP
PARA([[dnl czech
Uživatelský manuál[]REF([The M4 Macro Processor], [Bell Laboratories (1977)], [https://wolfram.schneider.org/bsd/7thEdManVol2/m4/m4.pdf]) zmiňuje ještě další, zde neuvedené spoluautory.
Bylo by tedy značně nespravedlivé napsat, že autory makro procesoru M4 (1977) jsou EM([pouze]) dva lidé.
],
[dnl english: _next_language_
The user manual[]REF([The M4 Macro Processor], [Bell Laboratories (1977)], [https://wolfram.schneider.org/bsd/7thEdManVol2/m4/m4.pdf]) mentions other co-authors not mentioned here.
So it would be fairly unfair to write that the authors of the M4 macro processor (1977) are EM([only]) two people.
]])
IMAGEDATA([the_authors],dnl id
[Christopher Strachey, Dennis Ritchie, Brian Kernighan],dnl title
[],dnl class
[],dnl style
[],dnl anything
[img/authors.jpg, https://i.iinfo.cz/images/283/authors-of-m4-1.jpg],dnl src
[[dnl czech
Christopher Strachey[]REF([Christopher Strachey], [Computer Hope – Free computer help since 1998], [https://www.computerhope.com/people/christopher_strachey.htm]),
Dennis Ritchie[]REF([Dennis Ritchie], [Zomrel tvorca Unixu a[]NB()jazyka[]NB()C], [https://pc.zoznam.sk/novinka/zomrel-tvorca-unixu-jazyka-c]),
Brian Kernighan[]REF([Brian Kernighan], [An Interview with Brian Kernighan], [https://www.cs.cmu.edu/~mihaib/kernighan-interview/])
],
[dnl english: _next_language_
Christopher Strachey[]REF([Christopher Strachey], [Computer Hope – Free computer help since 1998], [https://www.computerhope.com/people/christopher_strachey.htm]),
Dennis Ritchie[]REF([Dennis Ritchie], [Zomrel tvorca Unixu a[]NB()jazyka[]NB()C], [https://pc.zoznam.sk/novinka/zomrel-tvorca-unixu-jazyka-c]),
Brian Kernighan[]REF([Brian Kernighan], [An Interview with Brian Kernighan], [https://www.cs.cmu.edu/~mihaib/kernighan-interview/])
]])
BRIDGEHEAD_MONO([dnl monolingual
[GNU M4],
])
PARA([[dnl czech
Dnes existuje několik implementací lišící se od původní implementace spíše drobnostmi.
Nejrozšířenější implementace M4 je BO([GNU M4]) používaná pro AH([Autotools], [Wikipedie], [https://en.wikipedia.org/wiki/GNU_Build_System])
a[]NB()pro překlad jednoduchého konfiguračního souboru CODE([sendmail.mc]) na složitý CODE([sendmail.cf]).
Autorem této implementace z[]NB()roku 1990 je AH([PERSON([René Seindal])], [https://www.seindal.dk/rene/gnu/]).
Následující příkaz nainstaluje BO([m4], [s malým „m“], [dot]):
],
[dnl english: _next_language_
Today, there are several implementations that differ from the original implementation rather by small details.
The most common implementation of M4 is the BO([GNU M4]) used for AH([Autotools], [Wikipedia], [https://en.wikipedia.org/wiki/GNU_Build_System])
and for translating the simple CODE([sendmail.mc]) configuration file to complex CODE([sendmail.cf]).
The author of this implementation (1990) is AH([PERSON([René Seindal])], [https://www.seindal.dk/rene/gnu/]).
To install BO([m4], [with small letter „m“], [dot]), type the following command:
]])
COMMAND([install], LANG([příkaz nainstaluje také další důležité balíčky], [the command also installs other important packages]), [
ROO() BO([dnf -y install make m4 pinfo])
])dnl COMMAND
PARA([[dnl czech
Podrobný popis klíčových slov se nachází v[]NB()dokumentaci[]REF([GNU M4 - GNU macro processor], [Free Software Foundation], [https://www.gnu.org/software/m4/manual/]):
],
[dnl english: _next_language_
A[]NB()detailed description of the keywords can be found in the documentation[]REF([GNU M4 - GNU macro processor], [Free Software Foundation], [https://www.gnu.org/software/m4/manual/]):
]])
COMMAND([
CMD() BO([pinfo m4])
CMD() BO([man m4])
CMD() BO([m4 --help])
])dnl COMMAND
CHAPTER([dnl czech
[Základy jazyka M4],
dnl english: _next_language_
[Basics of M4],
])
PARA([[dnl czech
Základem jazyka M4 je BO([bezkontextová gramatika]), BO([automaty]), BO([zásobníky]) a[]NB()BO([výstupní fronty]).
Pro pochopení jazyka M4 je proto velmi důležité rozumět základním pojmům teorie formálních jazyků –
co jsou AH([terminální symboly], [Wikipedie], [https://cs.wikipedia.org/wiki/Termin%C3%A1ln%C3%AD_a_netermin%C3%A1ln%C3%AD_symbol]) (stručně BO([terminály])) a[]NB()neterminální symboly (stručně BO([neterminály])).
Zmíněné pojmy si podrobněji vysvětlíme někdy později.
Cílem tohoto úvodního dílu je hlavně ukázat praktické použití M4 na příkladech.
],
[dnl english: _next_language_
M4 is based on BO([context-free grammar]), BO([automata]), BO([stacks]) and BO([output queues]).
To understand M4, it is therefore crucial to understand the basic concepts of formal language theory –
AH([terminal symbols], [Wikipedia], [https://en.wikipedia.org/wiki/Terminal_and_nonterminal_symbols]) (briefly BO([terminals])) and nonterminal symbols (briefly BO([nonterminals])).
These terms will be explained later in more detail.
The objective is to show the basic practical use of M4 language on examples.
]])
SECT1([context_free_grammar], [dnl czech
[Bezkontextová gramatika],
dnl english: _next_language_
[Context-free grammar],
])
PARA([[dnl czech
Bezkontextová gramatika (krátce ABBR([CFG], [Context-Free Grammar – bezkontextová gramatika])) je LINK([formální gramatika], [formal_grammar_chomsky]), ve které mají všechna přepisovací pravidla tvar CODE([A[]NB()→[]NB()β]).
Neterminál CODE_M4([A]) se přepíše na libovolně dlouhý řetězec ABBR([CODE([β])], [pravá strana přepisovacího pravidla]) složený z[]NB()terminálů CODE([{Σ}]) nebo neterminálů CODE([{N}]).
AH([Kleene hvězda], [Wikipedie], [https://en.wikipedia.org/wiki/Kleene_star]) CODE([*]) znamená, že se neterminál CODE_M4([A]) může přepsat na ABBR([CODE([ε])], [epsilon – prázdný symbol]) (přepisovací pravidlo: CODE([A[]NB()→[]NB()ε])).
],
[dnl english: _next_language_
Context-free grammar (shortly ABBR([CFG], [Context-Free Grammar])) is a[]NB()LINK([formal grammar], [formal_grammar_chomsky]) in which all rules for rewriting have the CODE([A[]NB()→[]NB()β]) form.
The nonterminal CODE_M4([A]) is rewritten to an arbitrarily long ABBR([CODE([β])], [the right side of the rewriting rule]) string composed of terminals CODE([{Σ}]) or nonterminals CODE([{N}]).
AH([Kleene star], [Wikipedia], [https://en.wikipedia.org/wiki/Kleene_star]) CODE([*]) means that nonterminal CODE_M4([A]) can be rewritten to ABBR([CODE([ε])], [epsilon – empty symbol]) (rewriting rule: CODE([A[]NB()→[]NB()ε])).
]])
PROGRAMLISTING(, LANG([přepisovací pravidla bezkontextové gramatiky], [context-free grammar rewriting rules]), [[
P: A → β
A ∈ N
β ∈ (N ∪ Σ)*
]])dnl PROGRAMLISTING
BRIDGEHEAD([m4_rules], [dnl czech
[Přepisovací pravidla M4],
dnl english: _next_language_
[M4 rewriting rules],
])
PARA([[dnl czech
Přepisovací pravidla M4 jsou stejná jako přepisovací pravidla bezkontextové gramatiky.
],
[dnl english: _next_language_
The rules for rewriting are the same for context-free grammar and M4.
]])
The M4 rewriting rules are the same as context-free grammar rewriting rules.
PROGRAMLISTING(, LANG([přepisovací pravidla M4], [M4 rewriting rules]), [[
# A → β
define(`A', `β')
# A → ε
define(`A')
define(`A', `')
]])dnl PROGRAMLISTING
PARA([[dnl czech
Všechna klíčová slova M4 jsou neterminály (makra), provedou nějakou akci a[]NB()přepíší se na ABBR([CODE([ε])], [epsilon – prázdný symbol]) nebo jiný symbol.
Všechna klíčová slova mohou být přejmenována nebo úplně vypnuta.
Tato vlastnost je velmi důležitá pro režim preprocesoru.
],
[dnl english: _next_language_
All M4 keywords are nonterminals (macros), which take action and are rewritten to ABBR([CODE([ε])], [epsilon – empty symbol]) or another symbol.
All keywords can be renamed or turned off completely.
This feature is crucial for the preprocessor mode.
]])
PROGRAMLISTING(, LANG([klíčová slova M4 jsou neterminály], [M4 keywords are nonterminals]), [[
divert(ℤ) → ε
define(`A', `β') → ε
ifelse(`', `', `yes', `no') → yes
…
]])dnl PROGRAMLISTING
BRIDGEHEAD([expansion_control], [dnl czech
[Řízení expanze neterminálů],
dnl english: _next_language_
[Nonterminal expansion control],
])
PARA([[dnl czech
Výchozí dvojice znaků CODE([`']) v[]NB()M4 řídí expanzi neterminálů.
Klíčové slovo CODE_M4([changequote()]) je může změnit na jiné znaky, například {CODE_M4([[]]), BO([CODE([␂␆])]), CODE([〖〗])}.
Neterminály, které nechceme (ihned) expandovat, jsou obklopeny touto dvojicí znaků.
Při průchodu makro procesorem jsou všechny symboly mezi touto dvojicí znaků BUN([terminálními symboly]) a[]NB()vnější dvojice znaků je odstraněna.
Další průchod již způsobí expanzi původně chráněných neterminálů.
Dvojice řídících znaků se nastavuje na začátku kořenového souboru.
],
[dnl english: _next_language_
The default character pair CODE([`']) in M4 controls the expansion of nonterminals.
The keyword CODE_M4([changequote()]) can change them to other characters, for example {CODE_M4([[]]), BO([CODE([␂␆])]), CODE([〖〗])}.
The nonterminals that we do not want to (immediately) expand are surrounded by this pair of characters.
When passing through the macro processor, all the symbols between this character pair are BUN([terminal symbols]) and the outer character pair is removed.
The next pass will cause the expansion of the originally protected nonterminals.
The control character pair is set at the beginning of the root file.
]])
SECT1([automata_descr], [dnl czech
[Automaty],
dnl english: _next_language_
[Automata],
])
PARA([[dnl czech
Automaty používají přepisovací pravidla gramatiky jako uzly a[]NB()mění své stavy podle vstupních symbolů.
Aktuálně používané přepisovací pravidlo produkuje do výstupní fronty (nebo do několika výstupních front)
specifický kód, dokud automat nepřejde do jiného uzlu s[]NB()jiným přepisovacím pravidlem.
Automaty slouží jako QUOTE([přepínače]) pravidel gramatiky.
Příklady LINK([generujících automatů], [generating_automaton]) jsou ukázány v[]NB()příloze.
],
[dnl english: _next_language_
Automata use the grammar rules for rewriting as nodes and change their states according to input symbols.
The currently used rule produces a specific code to the output queue (or several output queues) until the automaton moves to another node with a[]NB()different rule.
Automata serve as QUOTE([switches]) of grammar rules.
The examples of LINK([generating automata], [generating_automaton]) are in appendix.
]])
SECT1([output_queues], [dnl czech
[Výstupní fronty],
dnl english: _next_language_
[Output queues],
])
PARA([[dnl czech
Výstupní fronty jsou dočasné úložiště pro části výsledného kódu.
Tyto části výsledného kódu jsou produkovány přepisovacími pravidly gramatiky, které přepisují vstupní symboly.
Klíčové slovo CODE_M4([divert(ℤ)]) nastavuje aktuální výstupní frontu.
Na závěr jsou všechny neprázdné fronty vypsány ve vzestupném pořadí na standardní výstup a[]NB()složí výsledný kód z[]NB()částí kódu.
LINK([Výstupní fronty], [output_queues_html]) jsou ukázány v[]NB()příloze.
],
[dnl english: _next_language_
The output queues temporarily store the portions of the resulting code.
These parts are formed using the grammar rules for rewriting which subsequently rewrite input symbols.
The CODE_M4([divert(ℤ)]) keyword sets the output queue.
Finally, all non-empty queues are dumped in ascending order to the standard output and compose the final code.
The examples of the LINK([output queues], [output_queues_html]) are in the appendix.
]])
These parts of the resulting code are created by rewriting rules of grammar that rewrite input symbols.
NOTE([[dnl czech
BO([Zásobníky]) si ukážeme později.
],
[dnl english: _next_language_
BO([Stacks]) will be described later.
]])
CHAPTER([main_uses_of_m4], [dnl czech
[Hlavní použití M4],
dnl english: _next_language_
[Main uses of M4],
])
PARA([[dnl czech
M4 se používá ke generování zdrojového kódu libovolného programovacího jazyka nebo jako preprocesor jakéhokoliv zdrojového kódu.
],
[dnl english: _next_language_
M4 is used to generate the source code of any programming language or as a[]NB()preprocessor for any source code.
]])
SECT1([code_generation], [dnl czech
[Generování kódu],
dnl english: _next_language_
[The code generation],
])
PARA([[dnl czech
M4 transformuje vstupní data ze souborů ABBR([CODE([.mc])], [Macro Configuration]) na výsledná data následujícím příkazem:
],
[dnl english: _next_language_
M4 transforms input data from ABBR([CODE([.mc])], [Macro Configuration]) files to output data with the following command:
]])
COMMAND([files_on_command_line], [← ]LANG([nejobecnější.m4 … nejspeciálnější.m4], [the_most_general.m4 … the_most_special.m4])[ →], [
CMD() BO([m4 root.m4 stem.m4 branch.m4 leaf.m4 input1.mc input2.mc > output.file])
])dnl COMMAND
PARA([[dnl czech
Během načítání souborů jsou prováděny dvě základní operace:
],
[dnl english: _next_language_
Two basic operations are performed during file loading:
]])
ORDEREDLIST_WRAP([
LISTITEM([[dnl czech
čtení transformačních pravidel ze souborů s[]NB()příponou CODE([.m4])
],
[dnl english: _next_language_
the reading transformation rules from files with the CODE([.m4]) extension
]])
LISTITEM([[dnl czech
expanze maker uvnitř souborů s[]NB()příponou CODE([.mc])
],
[dnl english: _next_language_
the expansion of macros inside CODE([.mc]) files
]])
])dnl ORDEREDLIST_WRAP
PARA([[dnl czech
Soubory CODE([input1.mc]) a[]NB()CODE([input2.mc]) obsahují BO([vstupní data]) ve specifickém formátu, který umožňuje jejich transformaci na BO([výstupní data]) podle pravidel v[]NB()předchozích CODE([.m4]) souborech.
Datové soubory CODE([.mc]) obvykle neobsahují žádná transformační pravidla.
],
[dnl english: _next_language_
The CODE([input1.mc]) and CODE([input2.mc]) files contain the BO([input data]) in a[]NB()format that allows them to be transformed into BO([output data]) according to the rules in the previous CODE([.m4]) files.
The CODE([.mc]) data files usually do not contain any transformation rules.
]])
PARA([[dnl czech
Vstupní data mohou také přicházet z[]NB()kolony:
],
[dnl english: _next_language_
The input data may also come from the pipeline:
]])
COMMAND(, LANG([vstupní kód → generování zdrojového kódu → soubor], [input code → source code generation → file]), [
CMD() BO([cat input.mc | m4 root.m4 stem.m4 branch.m4 leaf.m4 - > output.file])
])dnl COMMAND
COMMAND(, LANG([vstupní kód → generování zdrojového kódu → program], [input code → source code generation → program]), [
CMD() BO([cat input.mc | m4 root.m4 stem.m4 branch.m4 leaf.m4 - | gcc -x c -o progr -])
])dnl COMMAND
PARA([[dnl czech
define([try_it_yourself], [Vyzkoušejte:])try_it_yourself() LINK([code_generation_examples], [code_generation_examples])
],
[dnl english: _next_language_
define([try_it_yourself], [Try:])try_it_yourself() LINK([code_generation_examples], [code_generation_examples])
]])
SECT1([m4_as_preproc], [dnl czech
[Preprocesor],
dnl english: _next_language_
[The preprocessor],
])
PARA([[dnl czech
M4 může pracovat v[]NB()režimu preprocesoru.
Vstupní zdrojový kód jím prochází beze změny s[]NB()výjimkou neterminálních symbolů.
Nalezené neterminály jsou expandovány na terminály a[]NB()odchází spolu se zdrojovým kódem na výstup.
M4 může rozšířit jakýkoliv jiný jazyk, kde je preprocesor nedostatečný (bez rekurze) nebo žádný.
Důležité je zvolit vhodný levý znak pro řízení expanze neterminálů, který nesmí kolidovat se znakem vstupního zdrojového kódu.
Kolize znaku je ale snadno řešitelná regulárním výrazem.
],
[dnl english: _next_language_
M4 can operate in the preprocessor mode.
The input source code passes unchanged through except for nonterminal symbols.
The nonterminals found are expanded to terminals and the output along with the source code.
M4 can extend any other language where the preprocessor is insufficient (no recursion) or none.
It is important to select the left character for nonterminal expansion control, which must not collide with the input source code character.
However the character collision is easily solved by a regex.
]])
COMMAND(, LANG([M4 jako preprocesor – obecně], [M4 as preprocessor – in general]), [
CMD() BO([m4 root.m4 stem.m4 branch.m4 leaf.m4 file.c > preproc.file.c])
])dnl COMMAND
COMMAND(, LANG([M4 jako preprocesor – bez dočasného souboru], [M4 as preprocessor – without intermediate file]), [
CMD() BO([m4 root.m4 stem.m4 branch.m4 leaf.m4 file.c | gcc -x c -o progr -])
])dnl COMMAND
PARA([[dnl czech
M4 v[]NB()režimu preprocesoru může být součástí kolony.
Konfliktní znak CODE([LQ()]) ze vstupního zdrojového kódu je skryt do makra, například CODE_M4([`'LQ()]).
Prázdný pár řídících znaků CODE_M4([`']) před makrem slouží jako LINK([oddělovač symbolů], [symbols_in_brackets]).
],
[dnl english: _next_language_
M4 in the preprocessor mode can be a part of a[]NB()pipeline.
The conflicting character CODE([LQ()]) from the input source code is hidden into a[]NB()macro, for example CODE_M4([`'LQ()]).
An empty pair of control characters CODE_M4([`']) before the macro serves as a[]NB()LINK([symbol separator], [symbols_in_brackets]).
]])
# sorry i couldn't resist …
define([dirty_hack], LANG([M4 jako preprocesor s řídícími znaky], [M4 as preprocessor with control characters]))
COMMAND(, defn([dirty_hack])[: `'], [
CMD() BO([sed 's/LQ()/`'\''CODE_M4([LQ()])/g' any_src.code | m4 rootq.m4 leaf.m4 - | gcc …])
])dnl COMMAND
PARA([[dnl czech
Při průchodu zdrojového kódu makro procesorem se makro CODE_M4([`'LQ()]) přepíše zpátky na původní znak CODE([LQ()]) a[]NB()prázdný pár CODE_M4([`']) je odstraněn.
Použijeme-li pro řízení expanze neterminálů hranaté závorky, skryjeme stejným způsobem levou CODE([LB()]) hranatou závorku.
],
[dnl english: _next_language_
When the source code is passed through the macro processor, the CODE_M4([`'LQ()]) macro is rewritten back to the original CODE([LQ()]) character and the empty pair CODE_M4([`']) is removed.
If square brackets are used to control the expansion of nonterminals, the left CODE([LB()]) square bracket must be hidden in the same way.
]])
COMMAND(, defn([dirty_hack])[: []], [
CMD() BO([sed 's/\LB()/CODE_M4([[]LB()])/g' any_src.code | m4 rootb.m4 leaf.m4 - | gcc …])
])dnl COMMAND
PARA([[dnl czech
Pro řízeni expanze neterminálů lze použít netisknutelné znaky BO([CODE([␂])]) (SAMP([0x02])) a[]NB()BO([CODE([␆])]) (SAMP([0x06])).
Tyto znaky nemohou kolidovat s[]NB()tisknutelnými znaky zdrojového kódu.
],
[dnl english: _next_language_
Non printable characters BO([CODE([␂])]) (SAMP([0x02])) and BO([CODE([␆])]) (SAMP([0x06])) can be used to control the expansion of nonterminals.
These characters cannot interfere with printable source code characters.
]])
COMMAND(, defn([dirty_hack])[: ␂␆], [
CMD() BO([m4 rootn.m4 leaf.m4 any_src.code | gcc …])
])dnl COMMAND
undefine([dirty_hack])
PARA_MONO([[dnl
try_it_yourself() LINK([preproc_examples], [preproc_examples])
]])
BRIDGEHEAD([dnl czech
[Smíšený režim],
dnl english: _next_language_
[Mixed mode],
])
PARA([[dnl czech
Smíšený režim je kombinací předchozích režimů a[]NB()je používán hlavně na pokusy.
Data nejsou oddělena od transformačních pravidel.
Listový soubor CODE([leaf.m4]) obsahuje definice těchto pravidel spolu se vstupními daty.
],
[dnl english: _next_language_
The mixed mode is a[]NB()combination of the previous modes and is mainly used for experiments.
The data is not separated from the rules for its transformation.
The leaf file CODE([leaf.m4]) contains transformation rule definitions along with input data.
]])
COMMAND(, LANG([jak se naučit M4], [how to learn M4]), [
CMD() BO([m4 root.m4 leaf.m4])
])dnl COMMAND
PARA_MONO([[dnl
try_it_yourself() LINK([m4_on_examples], [m4_on_examples])
]])
CHAPTER([prerequisites_for_mastering], [dnl czech
[Předpoklady pro zvládnutí M4],
dnl english: _next_language_
[Prerequisites for mastering M4],
])
PARA([[dnl czech
Pro úspěšné zvládnutí tohoto makro jazyka je důležité splnit několik předpokladů.
M4 není jednoduchý jazyk, protože není možné v[]NB()něm myslet a[]NB()programovat jako v[]NB()běžném programovacím jazyce.
Nejdůležitější je uvědomit si, že se v[]NB()něm programují přepisovací pravidla gramatiky.
Každý řetězec je buď terminální nebo neterminální symbol včetně všech klíčových slov jazyka (symboly CODE_M4([#]) a[]NB()CODE_M4([,]) jsou speciální případy neterminálů).
],
[dnl english: _next_language_
To successfully master this macro language it is important to fulfill several prerequisites.
M4 is not a[]NB()simple language because it is not possible to think and program in it like an ordinary programming language.
The most important thing to realize is that it is used to program the grammar rules for rewriting.
Each string is either a[]NB()terminal or a[]NB()nonterminal symbol, including all language keywords (the symbols CODE_M4([#]) and CODE_M4([,]) are special cases of nonterminals).
]])
NOTE_WRAP([
PLAIN_TEXT([[dnl czech
M4 záměrně nemá klíčová slova pro BO([cykly]) (CODE([for])/CODE([while])), protože jeho základ je zcela jiný, než jaký mají procedurální nebo funkcionální jazyky.
],
[dnl english: _next_language_
M4 intentionally does not have keywords for BO([cycles]) (CODE([for])/CODE([while])) because its basis is quite different from procedural or functional languages.
]])
HORIZONTAL_RULE()
ITEMIZEDLIST_WRAP([
LISTITEM([[dnl czech
BO([cykly]) jsou pouze levorekurzivní nebo pravorekurzivní
],
[dnl english: _next_language_
BO([loops]) are only left-recursive or right-recursive
]])
LISTITEM([[dnl czech
BO([větví]) se LINK([řetězením symbolů], [branching_in_m4]) nebo klíčovými slovy CODE_M4([ifelse()]), CODE_M4([ifdef()])
],
[dnl english: _next_language_
BO([branching]) is made by LINK([symbol concatenation], [branching_in_m4]) or CODE_M4([ifelse()]), CODE_M4([ifdef()]) keywords
]])
])dnl ITEMIZEDLIST_WRAP
])dnl NOTE_WRAP
SECT1([dnl czech
[Základy gramatik],
dnl english: _next_language_
[Fundamentals of grammars],
])
PARA([[dnl czech
Základem všech gramatik jsou přepisovací pravidla, jejichž podobu obecně popisuje:
],
[dnl english: _next_language_
All grammars are based on the rules for rewriting and their forms are generally described:
]])
All grammars are based on rewriting rules, which form generally describes:
BRIDGEHEAD([formal_grammar_chomsky], [dnl czech
[Formální gramatika (Chomského typu)],
dnl english: _next_language_
[Formal grammar (Chomsky type)],
])
PROGRAMLISTING([
G = (N, Σ, P, S)
N: LANG([neprázdná konečná množina neterminálních symbolů], [nonempty finite set of nonterminal symbols])
Σ: LANG([konečná množina terminálních symbolů], [finite set of terminal symbols])
N ∩ Σ = ø
P: LANG([konečná množina přepisovacích pravidel], [finite set of production (rewrite) rules])
(N ∪ Σ)* N (N ∪ Σ)* → (N ∪ Σ)*
S: LANG([je počáteční (startovací) symbol], [is the start symbol])
S ∈ N
])dnl PROGRAMLISTING
PARA([[dnl czech
AH([Formální gramatika], [Wikipedie], [https://cs.wikipedia.org/wiki/Formální_gramatika]) popisuje AH([podmnožiny], [Wikipedie – Chomského hierarchie], [https://cs.wikipedia.org/wiki/Chomsk%C3%A9ho_hierarchie]) přepisovacích pravidel AH([formálního jazyka], [Wikipedie], [https://cs.wikipedia.org/wiki/Form%C3%A1ln%C3%AD_jazyk]).
Jedna z[]NB()podmnožin se jmenuje AH([bezkontextová gramatika], [Wikipedie], [https://cs.wikipedia.org/wiki/Bezkontextov%C3%A1_gramatika]), krátce ABBR([CFG], [Context-Free Grammar – bezkontextová gramatika]).
Jak již bylo dříve zmíněno, přepisovací pravidla CFG pracují stejně jako přepisovací pravidla jazyka M4.
Některý z[]NB()následujících dílů seriálu se podrobněji zaměří na formální gramatiky.
],
[dnl english: _next_language_
The AH([Formal grammar], [Wikipedia], [https://en.wikipedia.org/wiki/Formal_grammar]) describes the AH([subsets], [Wikipedia – Chomsky hierarchy], [https://en.wikipedia.org/wiki/Chomsky_hierarchy]) of the AH([formal language], [Wikipedia], [https://en.wikipedia.org/wiki/Formal_language]) rewriting rules and one of the subsets is called AH([context-free grammar], [Wikipedia], [https://en.wikipedia.org/wiki/Context-free_grammar]), shortly ABBR([CFG], [Context-Free Grammar]).
As mentioned earlier, the CFG rewriting rules work the same as the M4 rewriting rules.
Some of the following episodes of this series will focus on formal grammar in detail.
]])
SECT1([dnl czech
[Základy automatů],
dnl english: _next_language_
[Fundamentals of automata],
])
PARA([[dnl czech
Schopnost používat převážně dvoustavové automaty je zásadní věc pro psaní jednoduchých M4 skriptů, protože převážná většina skriptů používá LINK([malé automaty], [small_automaton]).
],
[dnl english: _next_language_
The ability to use predominantly two-state automata is an essential thing for writing simple M4 scripts because the vast majority of scripts use LINK([small automata], [small_automaton]).
]])
BRIDGEHEAD([testing_automaton], [dnl czech
[Testovací automat],
dnl english: _next_language_
[Testing automaton],
])
PARA([[dnl czech
Pořadí vstupních symbolů nebo jejich kontext lze otestovat automatem.
Splňují-li vstupní symboly požadované vlastnosti, automat skončí v[]NB()uzlu s[]NB()dvojitým kroužkem, kterým se označuje akceptující stav.
],
[dnl english: _next_language_
The order of input symbols or their context can be tested by an automaton.
If the input symbols meet the required properties, the automaton ends up in[]NB()a[]NB()double-ring node which indicates the accepting state.
]])
IMAGEDATA([dfa_img],dnl id
LANG([deterministický konečný automat], [deterministic finite automaton])[ (DFA)],dnl title
[],dnl class
[],dnl style
[],dnl anything
[img/dfa.png, https://i.iinfo.cz/images/149/dfa-1.png],dnl src
[[dnl czech
Příklad automatu[]REF([Teorie automatů], [From Wikipedia, the free encyclopedia], [https://cs.wikipedia.org/wiki/Teorie_automat%C5%AF], [Wikipedie]) akceptující sudý počet (žádný je také sudý) symbolů CODE([0]), ignorující symboly CODE([1]).
Automat je shodný s[]NB()regulárním výrazem CODE([(1*01*01*)*]).
],
[dnl english: _next_language_
Example of an automaton[]REF([Automata theory], [From Wikipedia, the free encyclopedia], [https://en.wikipedia.org/wiki/Automata_theory], [Wikipedia]) accepting an even number (none is even) of symbols CODE([0]), ignoring symbols CODE([1]).
The automaton is the same as the regular expression CODE([(1*01*01*)*]).
]])
PARA([[dnl czech
Předchozí automat lze zapsat jako ASCII art doprovázející M4 skript:
],
[dnl english: _next_language_
The previous automaton can be written as an ASCII art accompanying the M4 script:
]])
PROGRAMLISTING(, [ASCII-art ]LANG([jako dokumentace M4 kódu], [for M4 code documentation]), [
# ____1
# | /
# ___V__/ 0 ____
# --->// S1 \\------>/ S2 \---.1
# \\____//<------\____/<--'
# 0
])dnl PROGRAMLISTING
BRIDGEHEAD([generating_automaton], [dnl czech
[Generující automat],
dnl english: _next_language_
[Generating automaton],
])
PARA([[dnl czech
Vstupní symboly mění uzly automatu, čímž zároveň mění přepisovací pravidla pro generování kódu.
LINK([Tento příklad], [json_generating_automaton]) naleznete v[]NB()příloze:
],
[dnl english: _next_language_
Input symbols change the nodes of the automaton, thereby changing the rewriting rules for code generation.
See the appendix for LINK([this example], [json_generating_automaton]):
]])
PROGRAMLISTING(, [ASCII-art ]LANG([generujícího automatu], [of generating automaton]), [
# _______ ___________
# --->/ ERROR \--->/ NEXT_ITEM \---.
# \_______/ \___________/<--'
])dnl PROGRAMLISTING
PARA([[dnl czech
První symbol ve stavu CODE_M4([ERROR]) vygeneruje záhlaví se závorkami a[]NB()první položku.
Poté automat přejde do stavu CODE_M4([NEXT_ITEM]), ve kterém se pouze přidávají další položky.
Automat zůstává v[]NB()tomto stavu, dokud nejsou zpracována všechna data.
],
[dnl english: _next_language_
The first symbol in the CODE_M4([ERROR]) state generates a[]NB()header with brackets and inserts the first item.
Then automaton make transition to CODE_M4([NEXT_ITEM]) state in which only next items are added.
The automaton remains in this state until all data has been processed.
]])
SECT1([dnl czech
[(GNU) make],
dnl english: _next_language_
[(GNU) make],
])
PARA([[dnl czech
Dobře navržený generátor kódu se obvykle skládá z[]NB()několika menších souborů, jejichž pořadí, závislosti a[]NB()parametry se zapisují do souboru CODE([Makefile]).
Dobrá znalost tvorby CODE([Makefile]) je proto základním předpokladem pro zvládnutí M4.
Čtení a údržba zdrojového kódu celkově zabere vždy více času než jeho tvorba.
Dobře strukturovaný CODE([Makefile]) proto zásadním způsobem přispívá k[]NB()celkové přehlednosti výsledného generátoru kódu.
],
[dnl english: _next_language_
A[]NB()well-designed code generator usually consists of several smaller files whose order, dependencies and parameters are written to the CODE([Makefile]) file.
Good knowledge of CODE([Makefile]) writing is therefore a[]NB()prerequisite for mastering M4.
Reading and maintaining source code generally takes more time than creating it.
A[]NB()well-structured CODE([Makefile]) therefore significantly contributes to the overall clarity of the resulting code generator.
]])
NOTE(, LANG([tímto tématem se budeme zabývat jindy], [we will deal with this topic at another part]), [[dnl czech
Spouštění CODE([make])[]REF([GNU Make Manual], [Free Software Foundation], [https://www.gnu.org/software/make/manual/make.html]) z[]NB()editoru kódu pomocí vhodné klávesové zkratky zásadně urychluje vývoj M4 kódu.
Soubor CODE([~/.vimrc]) obsahuje CODE([nnoremap []LT()c-j[]GT() :make[]LT()cr[]GT()]).
],