File: flex.1

package info (click to toggle)
manpages-ja 0.5.0.0.20120606-1
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 25,964 kB
  • sloc: perl: 161; makefile: 116
file content (4079 lines) | stat: -rw-r--r-- 125,986 bytes parent folder | download | duplicates (5)
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
.\" %FreeBSD: src/usr.bin/lex/lex.1,v 1.10.2.3 2001/09/30 12:40:04 dd Exp %
.\"
.\" $FreeBSD$
.TH FLEX 1 "April 1995" "Version 2.5"
.SH 名称
flex \- 高速な字句解析処理系の生成ツール
.SH 書式
.B flex
.B [\-bcdfhilnpstvwBFILTV78+? \-C[aefFmr] \-ooutput \-Pprefix \-Sskeleton]
.B [\-\-help \-\-version]
.I [filename ...]
.SH 概説
本マニュアルは、
テキストのパターンマッチングを行うプログラムを生成するツール
.I flex
を扱います。
本マニュアルはチュートリアルとリファレンス節とを含みます:
.nf

    解説
        ツールの短い概説

    簡単な例

    入力ファイルのフォーマット

    パターン
        flex が使用する拡張した正規表現

    入力のマッチ方法
        何がマッチするかを決定する規則

    アクション
        パターンがマッチした時に何を行うかを指定する方法

    生成されたスキャナ
        flex が生成するスキャナに関する詳細;
        入力元の制御方法

    開始条件
        スキャナへの文脈の導入と、
        "ミニスキャナ" の制御方法

    複数の入力バッファ
        複数の入力元を扱う方法;
        ファイルではなく文字列からスキャンする方法

    ファイルの終りのルール
        ファイルの終りにマッチする特別なルール

    雑多なマクロ
        アクションで使用可能なマクロのまとめ

    ユーザが使用可能な値
        アクションで使用可能な値のまとめ

    Yacc とのインタフェース
        lex スキャナと yacc パーサとの結合

    オプション
        flex のコマンドラインオプションと、
        "%option" ディレクティブ

    性能関連
        スキャナを可能な限り高速にする方法

    C++ スキャナの生成
        C++ スキャナクラス生成のための
        (実験的な) 機能

    Lex および POSIX との非互換性
        AT&T lex および POSIX lex 標準と
        flex との違い

    診断
        flex (もしくは生成したスキャナ) が出力する
        エラーメッセージで意味が明確でないもの

    関連ファイル
        flex が使用するファイル

    欠陥 / バグ
        flex の既知の問題

    関連項目
        ツールに関係する他のドキュメント

    作者
        連絡方法を含みます

.fi
.SH 解説
.I flex
.I スキャナ
を生成するためのツールです。
ここで、スキャナとは、
テキスト内の字句パターンを解析するプログラムです。
.I flex
は指定したファイル、もしくはファイル名が与えられなかった場合は
標準入力から、生成するスキャナの記述を読み込みます。
この記述は、
正規表現と C コードのペアの形をとっています。
これは
.I ルール
と呼ばれます。
.I flex
は、出力として C ソースファイルの
.B lex.yy.c
を生成しますが、その中に
.B yylex()
ルーチンが定義されます。
このファイルはコンパイルされ、
.B \-ll
ライブラリとともにリンクされて、
実行形式となります。
実行形式が走り始めると、
正規表現をマッチさせるために
入力が解析されます。
マッチするものを見つけると、対応する C コードが実行されます。
.SH 簡単な例
まず簡単な例から、
.I flex
の使い方を見て行きましょう。
次の
.I flex
の入力は、"username" という文字列に出会うとユーザのログイン名に置き換える
スキャナを指定しています:
.nf

    %%
    username    printf( "%s", getlogin() );

.fi
デフォルトでは、
.I flex
スキャナにマッチしなかったテキストは出力にコピーされますので、
"username" を展開しながら入力を出力にコピーすることが
このスキャナの最終的な結果となります。
この入力にはただ一つのルールだけがあります。
"username" は
.I パターン
であり、"printf" は
.I アクション
です。
"%%" はルールの始まりの印です。
.PP
別の例を見て見ましょう:
.nf

    %{
            int num_lines = 0, num_chars = 0;
    %}

    %%
    \\n      ++num_lines; ++num_chars;
    .       ++num_chars;

    %%
    main()
            {
            yylex();
            printf( "# of lines = %d, # of chars = %d\\n",
                    num_lines, num_chars );
            }

.fi
このスキャナは入力の文字数および行数を数えます
(数えた最終結果を報告するだけです)。
最初の行は 2 つの大域変数 "num_lines" と "num_chars" を宣言します。
これらの変数は、2 番目の "%%" の後に宣言されている
.B yylex()
.B main()
のルーチンからアクセス可能です。
ここには 2 つのルールがあります。
1 つ目は改行文字 ("\\n") にマッチし、行数と文字数のカウントを増加させます。
もう 1 つは、改行文字以外の全ての文字
("." という正規表現で表されています)にマッチします。
.PP
次はもうちょっと複雑な例です:
.nf

    /* scanner for a toy Pascal-like language */

    %{
    /* need this for the call to atof() below */
    #include <math.h>
    %}

    DIGIT    [0-9]
    ID       [a-z][a-z0-9]*

    %%

    {DIGIT}+    {
                printf( "An integer: %s (%d)\\n", yytext,
                        atoi( yytext ) );
                }

    {DIGIT}+"."{DIGIT}*        {
                printf( "A float: %s (%g)\\n", yytext,
                        atof( yytext ) );
                }

    if|then|begin|end|procedure|function        {
                printf( "A keyword: %s\\n", yytext );
                }

    {ID}        printf( "An identifier: %s\\n", yytext );

    "+"|"-"|"*"|"/"   printf( "An operator: %s\\n", yytext );

    "{"[^}\\n]*"}"     /* eat up one-line comments */

    [ \\t\\n]+          /* eat up whitespace */

    .           printf( "Unrecognized character: %s\\n", yytext );

    %%

    main( argc, argv )
    int argc;
    char **argv;
        {
        ++argv, --argc;  /* skip over program name */
        if ( argc > 0 )
                yyin = fopen( argv[0], "r" );
        else
                yyin = stdin;

        yylex();
        }

.fi
これは Pascal のような言語の単純なスキャナの原型です。
異なったタイプの
.I トークン
を定義し、これを見付けると報告します。
.PP
この例の詳細は、以降の節で説明します。
.SH 入力ファイルのフォーマット
.I flex
の入力ファイルは 3 つの部分からなり、
.B %%
だけからなる行により分けられます:
.nf

    定義
    %%
    ルール
    %%
    ユーザコード

.fi
.I 定義
部分は、スキャナの宣言を単純化する単純な
.I 名前
の定義の宣言と、後で説明する
.I 開始条件
の宣言とからなります。
.PP
名前の定義は次の形式です:
.nf

    名前\ 定義

.fi
"名前" は語であり、
レターかアンダースコア ('_') から始まって 0 個以上のレター・数字・'_'・'-'
(ダッシュ)が続きます。
定義は、名前に続く最初の非空白文字から始まり、行末まで続くものとされます。
定義は後で "{名前}" で参照でき、"(定義)" を展開します。
例えば、
.nf

    DIGIT    [0-9]
    ID       [a-z][a-z0-9]*

.fi
は、
"DIGIT" が単一の数字にマッチする正規表現であると定義し、
"ID" がレターに 0 個以上のレターか数字が続く正規表現であると定義します。
後で出て来る参照
.nf

    {DIGIT}+"."{DIGIT}*

.fi
.nf

    ([0-9])+"."([0-9])*

.fi
と同じであり、1 個以上の数字に '.' が続き、
0 個以上の数字が続くものにマッチします。
.PP
.I flex
の入力の
.I ルール
は次の形式の一連のルールからなります:
.nf

    パターン\ \ \ アクション

.fi
ここで、パターンはインデントされていてはならず、
アクションは同じ行から始まる必要があります。
.PP
パターンとアクションの詳細は後の解説を見て下さい。
.PP
最後に、ユーザコードの部分は単純にそのままの形で
.B lex.yy.c
にコピーされます。
スキャナを呼び出すまたは呼び出される付随ルーチンのために使用されます。
この部分はあっても無くても構いません;
無い場合には、入力ファイル中の 2 番目の
.B %%
も省略できます。
.PP
定義とルールの部分では、
.I インデントされた
テキストと
.B %{
.B %}
との間のテキストはそのままの形で出力にコピーされます
(この際 %{} は削除されます)。
%{} はインデントされていない行に現れる必要があります。
.PP
ルールの部分では、
最初のルールの前に現れるインデントされたもしくは %{} 部分のテキストは、
スキャンルーチンにローカルな変数と、
(宣言の後では)スキャンルーチンに入るたびに実行されるコードとを宣言します。
ルール部分の他のインデントされたもしくは %{} 部分のテキストは
出力にコピーされますが、
意味はちゃんと定義されておらずコンパイル時にエラーとなるかも知れません
(この仕様は
.I POSIX
互換のためにあります; 他のこのような仕様は以降を見て下さい)。
.PP
定義の部分(ルールの部分ではないです)では、
インデントされていないコメント("/*" から始まる行) は次の "*/" まで
そのままの形でコピーされます。
.SH パターン
入力ファイルのパターンは拡張した正規表現を使って記述します。
以下に示します:
.nf

    x          文字 'x' にマッチ。
    .          改行を除く全ての文字(バイト)。
    [xyz]      "文字クラス"; この場合、'x', 'y', 'z' のいずれにも
                 マッチします。
    [abj-oZ]   範囲指定を含む "文字クラス"; この場合、'a', 'b' と
                 'j' から 'o' までの任意のレターと 'Z' にマッチします。
    [^A-Z]     "否定文字クラス"; クラスに含まれない任意の文字に
                 マッチします。 この場合、'A' から 'Z' までの大文字
                 「以外の」文字にマッチします。
    [^A-Z\\n]   大文字と改行を「除く」全ての文字。
    r*         0 もしくはそれ以上の r。r は任意の正規表現。
    r+         1 もしくはそれ以上の r。
    r?         0 もしくは 1つの r (「おまけ」の r)
    r{2,5}     2 つから 5つまでの r。
    r{2,}      2 つ以上の r。
    r{4}       ちょうど 4つ の r。
    {名前}     "名前" の定義の展開。
               (上を参照)
    "[xyz]\\"foo"
               文字列 [xyz]"foo
    \\X         X が 'a', 'b', 'f', 'n', 'r', 't', 'v' のいずれかの
                 とき、ANSI-C での \\X の解釈となります。
                 それ以外の場合、文字 'X' ('*' のようなオペレータの
                 意味を打ち消し、その文字自体を指定する際に使います)。
    \\123       8進数で 123 と表される文字。
    \\x2a       16進数で 2a と表される文字。
    (r)        r にマッチ; ()は 優先順位を変えるために使用。
                 (以下を参照)


    rs         正規表現 r に正規表現 s が続く; 「連結(concatenation)」
                 と呼びます。


    r|s        r もしくは s。


    r/s        後ろに s が続く時の r。
                 s にマッチするテキストはこのルールの "最長適合" を判定する
                 時には含まれますが、アクションが実行される前に
                 入力に戻されます。
                 アクションは r にマッチするテキストだけを見ます。
                 このパターンは "右文脈(trailing context)" と呼ばれます。
                 (flex が正確にマッチ不能な r/s の組合せは複数あります;
                 "危険な右文脈" については、
                 以降の、欠陥 / バグ の節の記述を見て下さい。)
    ^r         行頭にある r。(スキャンの始まりもしくは
                 スキャンされた改行の右です)。
    r$         行末にある r。"r/\\n" と等価(改行の前です)。
                 "r/\\n" と同じです。

               flex の "改行" の表現は flex をコンパイルした
               C コンパイラが解釈する '\\n' と完全に一致することに
               注意して下さい;
               特定のシステム DOS では \\r を入力から取り除くか
               "r$" を表すために明示的に r/\\r\\n を使用する必要があります。


    <s>r       開始条件 s における r。(開始条件については以下を
               参照)。
    <s1,s2,s3>r
               上に同じ。ただし開始条件は s1, s2, s3 のいずれでもよい。
    <*>r       任意の開始条件の r。開始条件は排他的なものでもよい。


    <<EOF>>    ファイルの終了。
    <s1,s2><<EOF>>
               開始条件が s1 もしくは s2 であるときのファイルの終了。

.fi
文字クラス中では、全ての正規表現のオペレータは、
エスケープ ('\\') および
文字クラスオペレータである '-' と ']' とクラスの先頭の '^' を除き
特別な意味を失うことに注意して下さい。
.PP
上に挙げた正規表現は優先順位によってグループに分けられています。
一番上のグループが最も高い優先度で、
一番下のグループの優先順位が最も低くなっています。
グループ内では同じ優先順位です。例えば、
.nf

    foo|bar*

.fi
.nf

    (foo)|(ba(r*))

.fi
と同じです。なぜなら '*' オペレータは連結より優先度が高く、
連結は選言 ('|') より優先度が高いからです。このパターンは
文字列 "foo"
.I もしくは
文字列 "ba" に 0 個以上の r がつづくものの
.I どちらにも
マッチします。
"foo" もしくは 0 個以上の "bar" にマッチさせるためには次の表現を使用して下さい:
.nf

    foo|(bar)*

.fi
0 個以上の "foo" または "bar" にマッチするためには次の表現を使用して下さい:
.nf

    (foo|bar)*

.fi
.PP
文字もしくは文字範囲に加え、文字クラスも文字クラスの
.I 表現
を含みます。
これらの表現は
.B [:
および
.B :]
のデリミタに囲まれます (文字クラスの '[' と ']' との間に現れる必要があります;
他の要素が文字クラス中に現れても構いません)。
有効な表現は以下の通りです:
.nf

    [:alnum:] [:alpha:] [:blank:]
    [:cntrl:] [:digit:] [:graph:]
    [:lower:] [:print:] [:punct:]
    [:space:] [:upper:] [:xdigit:]

.fi
これらの表現は対応する標準 C の
.B isXXX
関数に適合する全ての文字集合を指示します。例えば、
.B [:alnum:]
.B isalnum()
が真を返す文字を指示します - すなわちすべてのアルファベットと数字です。
.B isblank(),
が無いシステムでは、flex は
.B [:blank:]
を空白とタブと定義します。
.PP
例えば以下の表現は全て同じです:
.nf

    [[:alnum:]]
    [[:alpha:][:digit:]]
    [[:alpha:]0-9]
    [a-zA-Z0-9]

.fi
スキャナが大文字小文字を意識しない場合(
.B \-i
フラグ指定時)
.B [:upper:]
.B [:lower:]
.B [:alpha:]
と同じです。
.PP
パターンに関する注意点です:
.IP -
否定文字クラス、例えば上の "[^A-Z]" は
"\\n" (もしくはこれを表すエスケープシーケンス) が明示的に
否定文字クラスに現れている場合 (例えば "[^A-Z\\n]") を除き
.I 改行にマッチします。
これは他の正規表現ツールが否定文字クラスを扱う方法とは異なりますが、
不幸なことにこの矛盾は歴史的に確立しています。
改行にマッチするとは、
入力に別のクオートが存在しない場合に [^"]* のようなパターンが
入力全体にマッチすることを意味します。
.IP -
ルールは右文脈('/' オペレータもしくは '$' オペレータ)
を高々一つしか持てません。
開始条件 '^' と "<<EOF>>" パターンは
パターンの最初になければならず、 '/', '$'
同様に () 内にいれることは出来ません。
ルールの先頭ではない '^' もしくはルールの終りではない '$' は
特別な意味を失い、通常の文字として扱われます。
.IP
以下は無効です:
.nf

    foo/bar$
    <sc1>foo<sc2>bar

.fi
前者は "foo/bar\\n" と書けます。
.IP
以下では '$' と '^' とは通常の文字として扱われます:
.nf

    foo|(bar$)
    foo|^bar

.fi
"foo" もしくは "改行が続く bar" を指定したい場合は、
次の表現を使用して下さい (特別な '|' の動作は後で説明します):
.nf

    foo      |
    bar$     /* action goes here */

.fi
同じ方法で、foo もしくは 行頭の bar を指定可能です。
.SH 入力のマッチ方法
生成したスキャナを実行すると、
スキャナは入力を見てパターンにマッチする文字列を探します。
1 より多くのマッチを見付けると、最長テキストのマッチを採用します
(右文脈(trailing context rule)の後ろの部分も長さに含みますが、
後ろの部分は入力に戻されます)。
同じ長さのマッチを 2 つ以上見付けた場合、
.I flex
入力ファイルで最初に記述されたルールを採用します。
.PP
マッチが決定すると、マッチに対応するテキスト(
.I トークン
と呼ばれます)がグローバル文字ポインタ
.B yytext
により使用可能となり、長さがグローバル整数
.B yyleng
により使用可能となります。
その後、マッチしたパターンに対応する
.I アクション
が実行され(アクションの詳細な記述は後で行います)、
残りの入力が残りのマッチのためにスキャンされます。
.PP
マッチが見付からないと、
.I デフォルトルール
が実行されます: 入力の次の文字がマッチしたと見倣され、
標準出力にコピーされます。最も簡単で正当な
.I flex
の入力は以下の通りです:
.nf

    %%

.fi
これは、入力を単純に出力にコピー(1 度に 1 文字ずつ)するスキャナを生成します。
.PP
.B yytext
は 2 つの異なった方法により定義されうることに注意して下さい: 文字
.I ポインタ
もしくは文字
.I 配列
です。
.I flex
がどちらの定義を使用するかは特別なディレクティブ
.B %pointer
もしくは
.B %array
を flex の入力の最初の(定義)部分に含めることにより制御できます。
デフォルトは
.B %pointer
であり、
.B -l
lex 互換オプションを使用した場合には例外的に
.B yytext
は配列になります。
.B %pointer
を使用する利点はスキャンが高速であること、
非常に大きなトークンにマッチする時にも
(動的メモリを使用し尽くさない限り)バッファオーバフローとならないことです。
欠点は、アクションが
.B yytext
を修正することが制限されること(次節参照)、
.B unput()
呼び出しが
.B yytext
の現在の内容を破壊することです。
これは異なる
.I lex
バージョン間での移植性に関する頭痛の種です。
.PP
.B %array
の利点は
.B yytext
の内容を思った通りに変更できること、
.B unput()
を呼び出しても
.B yytext
の内容が破壊されないことです(下記参照)。
その上、既存の
.I lex
プログラムは
.B yytext
を外部から次の形式の宣言を使用してアクセスしていることがあります:
.nf
    extern char yytext[];
.fi
この定義は
.B %pointer
使用時には誤りですが、
.B %array
使用時には正しいです。
.PP
.B %array
.B yytext
を文字数
.B YYLMAX
(デフォルトは十分大きな値)の配列であると定義します。
この大きさは、
.I flex
の入力の最初の部分で単純に
.B YYLMAX
を異なった値に #define することにより変更できます。
上記の通り、
.B %pointer
使用時には yytext は大きなトークンを格納するために動的に大きくなります。
このことは
.B %pointer
を使用したスキャナは非常に大きなトークン
(例えばコメントブロック全体)を格納可能であることを意味しますが、
スキャナが
.B yytext
の大きさを変えるたびにトークン全体を先頭から再スキャンすることが必要となるため
このようなトークンに対するマッチングは遅くなりうることを覚えておいて下さい。
現在、
.B yytext
.B unput()
が結果として返すテキストが大きい時には動的には大きくなり
.I ません;
実行時エラーとなります。
.PP
また、
.B %array
C++ スキャナクラスでは使用できないことに注意して下さい(
.B c++
オプションに関しては下記参照)。
.SH アクション
ルール中のパターンは対応するアクションを持ちます。
アクションは任意の C の文です。
パターンは最初のエスケープされていない空白文字で終ります;
行の残りがアクションです。
アクションが空である場合、
パターンがマッチした時に入力トークンは単純に捨てられます。
例えば入力から全ての "zap me" を削除するプログラムの仕様を示します:
.nf

    %%
    "zap me"

.fi
(入力の他の全ての文字を出力にコピーします。
なぜならデフォルトルールにマッチするからです。)
.PP
次は、複数の空白や文字を単一の空白に圧縮し行末の空白を捨てるプログラムです:
.nf

    %%
    [ \\t]+        putchar( ' ' );
    [ \\t]+$       /* ignore this token */

.fi
.PP
アクションが '{' を含む場合、アクションは対応する '}' まで続き、
複数行に渡る場合もあります。
.I flex
は C の文字列およびコメントに関して知っており、
それらの中のブレースを誤解することはありませんが、
アクションが
.B %{
で始まることを許し、次の
.B %}
までのテキストがアクションであるとします
(アクション内部の任意個のブレースには関係ありません)。
.PP
垂直バー ('|') のみからなるアクションは
"次のルールと同じ" を意味します。説明は以下を見て下さい。
.PP
アクションは任意の C コードを含むことが出来ます。
これには、
.B yylex()
を呼び出したルーチンに対して値を返す
.B return
文も含まれます。
.B yylex()
が呼ばれるたび、最後に残ったトークンから処理を再開し、
ファイルの終了もしくは return を実行するまで処理を行います。
.PP
アクションは自由に
.B yytext
を変更できますが、例外は長さを増やすことです
(文字を末尾に加えることになり、
これは入力ストリームの後続する文字を上書きします)。
これは
.B %array
使用時には当てはまりません(上述); この場合
.B yytext
を自由に変更できます。
.PP
アクションは自由に
.B yyleng
を変更できますが、アクションが
.B yymore()
を使用する時には例外的に変更してはいけません(後述)。
.PP
多くの特別なディレクティブがあり、アクション中に含めることが出来ます:
.IP -
.B ECHO
yytext をスキャナの出力にコピーします。
.IP -
.B BEGIN
後ろに開始条件の名前を書くと、スキャナを対応する開始条件に設定します(後述)。
.IP -
.B REJECT
入力(もしくは入力の頭)に "2 番目によく(second best)" マッチするルール
に進むようにスキャナに指示します。
"入力のマッチ方法" で示したようにルールは選択され、
.B yytext
.B yyleng
は適切に設定されます。
選択されるルールは、最初に選択されたルールと同じ長さであるが
.I flex
の入力ファイルにて後で出て来るもの、もしくは少ない文字数にマッチするものです。
例えば次の例では入力中の語を数え、
"frob" が見付かるたびにルーチン special() を呼びます:
.nf

            int word_count = 0;
    %%

    frob        special(); REJECT;
    [^ \\t\\n]+   ++word_count;

.fi
.B REJECT
が無い場合、
入力中の "frob" は語として数えられず、
スキャナは通常通りトークン毎に 1 つのアクションだけを行います。
複数の
.B REJECT
を使用可能であり、それぞれ現在有効なルールの次に良い選択を見付けます。
例えば次のスキャナは、"abcd" というトークンをスキャンし、
出力に "abcdabcaba" を書きます:
.nf

    %%
    a        |
    ab       |
    abc      |
    abcd     ECHO; REJECT;
    .|\\n     /* eat up any unmatched character */

.fi
(前の 3 つのルールは 4 番目のルールのアクションを共有します。
なぜなら特別な '|' アクションが使用されているからです。)
.B REJECT
はスキャナの性能という点で特にコストのかかる機能です;
もしスキャナのアクションの
.I いずれか
にでも REJECT が使われたなら、スキャナの
.I 全ての
マッチング速度を低下させるということです。
さらに
.B REJECT
をオプション
.I -Cf
.I -CF
と共に用いることは出来ません。
.IP
また、他の特別アクションと違い
.B REJECT
.I 分岐(branch)
であることに注意してください; すなわち REJECT 直後のアクションは
実行
.I されません。
.IP -
.B yymore()
次にルールとマッチしたときには、対応するトークンは、
現在の
.B yytext
の内容と入れ換えるのではなく
.B yytext
.I 追加
するようスキャナに指示します。
例えば、入力 "mega-kludge" が与えられると、以下は
"mega-mega-kludge" を出力に書きます:
.nf

    %%
    mega-    ECHO; yymore();
    kludge   ECHO;

.fi
最初の "mega-" はマッチし出力にエコーされます。
次に "kludge" がマッチしますが、直前の "mega-" がまだ
.B yytext
の先頭に残っており、"kludge" の
.B ECHO
ルールは実際には "mage-kludge" を書きます。
.PP
.B yymore()
の使用に関し 2 つの注意点があります。
まず、
.B yymore()
は現在のトークンの大きさを反映する
.I yyleng
の値の正確さに依存することであり、
.B yymore()
使用時には
.I yyleng
を変更してはなりません。
次に、
スキャナのアクションに
.B yymore()
があると、スキャナのマッチ速度に若干悪影響があります。
.IP -
.B yyless(n)
現在のトークンから最初の
.I n
文字を除いたものを入力ストリームに戻します。
戻した文字列はスキャナが次のマッチングをとるときに再度スキャンされます。
.B yytext
.B yyleng
は適切に調整されます(例えば
.B yyleng
.I n
となります)。
例えば、入力 "foobar" が与えられると、以下は
"foobarbar" を書きます:
.nf

    %%
    foobar    ECHO; yyless(3);
    [a-z]+    ECHO;

.fi
引数 0 を
.B yyless
に与えると、現在の入力文字列全体が再度スキャンされます。
(例えば
.B BEGIN
を使用して)次にスキャナが入力する方法を変更していないと、無限ループとなります。
.PP
.B yyless
はマクロであり、flex 入力ファイルでのみ使用可能であり、
別のソースファイルからは使用不能であることに注意して下さい。
.IP -
.B unput(c)
文字
.I c
を入力ストリームへ戻します。戻した文字は次にスキャンされる文字になります。
次のアクションは現在のトークンを取り上げ、
括弧内に入れて再スキャンします。
.nf

    {
    int i;
    /* Copy yytext because unput() trashes yytext */
    char *yycopy = strdup( yytext );
    unput( ')' );
    for ( i = yyleng - 1; i >= 0; --i )
        unput( yycopy[i] );
    unput( '(' );
    free( yycopy );
    }

.fi
.B unput()
は文字を入力ストリームの
.I 先頭
に戻すので、文字列を戻す場合には後ろから前に向かって戻す必要があります。
.PP
.B unput()
使用時の重要な潜在的な問題は、
.B %pointer
使用時(デフォルト)に
.B unput()
を呼び出すと、
右端の文字から開始し 1 文字ずつ左に向かって消費され、
.I yytext
の内容が
.I 破壊
されることです。
(上記例のように)
.B unput()
呼び出し後も
.I yytext
の内容を保存するためには、始めに別の場所にコピーするか、
スキャナを
.B %array
を使うように構築することです(入力のマッチ方法参照)。
.PP
最後に、
.B EOF
を戻して入力ストリームにファイルの終りをマークするとは
出来ないことに注意して下さい。
.IP -
.B input()
次の文字を入力ストリームから読みます。
次の例は C コメントを食べます:
.nf

    %%
    "/*"        {
                register int c;

                for ( ; ; )
                    {
                    while ( (c = input()) != '*' &&
                            c != EOF )
                        ;    /* eat up text of comment */

                    if ( c == '*' )
                        {
                        while ( (c = input()) == '*' )
                            ;
                        if ( c == '/' )
                            break;    /* found the end */
                        }

                    if ( c == EOF )
                        {
                        error( "EOF in comment" );
                        break;
                        }
                    }
                }

.fi
(スキャナが
.B C++
でコンパイルされたときは、このルーチンは
.B yyinput()
という名称になり、
.B C++
ストリームの
.I input
と名前が衝突することを避けます。)
.IP -
.B YY_FLUSH_BUFFER
スキャナの内部バッファをフラッシュし、
次にスキャナがトークンをマッチしようとした時
バッファを
.B YY_INPUT
にてリフィルします(生成されたスキャナで後述)。
このアクションは、
複数の入力バッファにおいて後述する
より一般的な
.B yy_flush_buffer()
関数の特別なケースです。
.IP -
.B yyterminate()
アクションの return 文の代わりに使うことが出来ます。
.B yyterminate()
はスキャナを終了し、"全て終了" を意味する 0 を呼び出し元関数に返します。
デフォルトでは
.B yyterminate()
はファイルの終わりに達したときにも呼ばれます。
.B yyterminate()
はマクロであり、定義しなおすことができます。
.SH 生成されたスキャナ
.I flex
の出力は
.B lex.yy.c
というファイルであり、スキャンルーチン
.B yylex()
と、トークンのマッチングに使用する複数のテーブルと、
複数の付属ルーチンとマクロからなります。デフォルトでは、
.B yylex()
は次のように宣言されます:
.nf

    int yylex()
        {
        ... various definitions and the actions in here ...
        }

.fi
(環境が関数プロトタイプをサポートしている場合、
"int yylex( void )" となります。)
この定義は "YY_DECL" マクロを定義することにより変更できます。
例えば次のように使用することが出来ます:
.nf

    #define YY_DECL float lexscan( a, b ) float a, b;

.fi
これはスキャンルーチンの名前を
.I lexscan
とし、浮動小数点数を返すようにし、2 つの浮動小数点数を引数とします。
K&R の非プロトタイプの関数宣言を使用してスキャンルーチンに対して引数を
与える場合、定義をセミコロン(;)で終了する必要があります。
.PP
.B yylex()
は呼ばれるたび、グローバル入力ファイル
.I yyin
(デフォルトでは標準入力)からトークンをスキャンします。
ファイルの終りになる(この場合 0 を返します)か、
アクションが
.I return
文を実行するまで、実行を続けます。
.PP
スキャナがファイルの終りに到達すると、
.I yyin
が新たなファイルを指さないか
(新たなファイルを指す場合はこのファイルのスキャンを続けます)、
.B yyrestart()
が呼ばれない限り、
後続する呼び出しは未定義です。
.B yyrestart()
.B FILE *
ポインタ(
.B YY_INPUT
を設定して
.I yyin
以外のソースをスキャンするようにした場合には nil も可です)
である引数を 1 つとり、そのファイルからのスキャンのために
.I yyin
を初期化します。
本質的に、
.I yyin
を新しい入力ファイルに割り当てることと
.B yyrestar()
を使用することとは同じです;
後者は前のバージョンの
.I flex
との互換性のために使用可能であり、
またスキャンの途中で入力ファイルを変えることが可能です。
引数を
.I yyin
として呼び出すことにより、現在の入力バッファを捨てることも出来ます;
ただし、
.B YY_FLUSH_BUFFER
(上述)を使用する方が良いです。
.B yyrestart()
.B INITIAL
の開始条件を変更し
.I ない
ことに注意して下さい
(後述の開始条件参照)。
.PP
あるアクション中で
.I return
文を実行することにより
.B yylex()
がスキャンを止めた場合、スキャナは再度呼び出し可能であり、
この場合スキャンの残りの部分から再開します。
.PP
デフォルトで(効率のため)、スキャナは単純な
.I getc()
コールではなくブロックリードを行い、
.I yyin
から文字を読みます。
入力取得方法は
.B YY_INPUT
マクロを定義することにより制御できます。
YY_INPUT 呼び出し手順は "YY_INPUT(buf,result,max_size)" です。
このアクションは、
.I buf
文字配列中に最大
.I max_size
文字を用意し、整数変数
.I result
中に読めた文字数もしくは定数 YY_NULL (Unix システムでは 0)を入れて返します。
デフォルトの YY_INPUT はグローバルファイルポインタ "yyin" から読みます。
.PP
YY_INPUT のサンプル定義です(入力ファイルの定義部に格納):
.nf

    %{
    #define YY_INPUT(buf,result,max_size) \\
        { \\
        int c = getchar(); \\
        result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \\
        }
    %}

.fi
この定義により、入力処理は 1 度に 1 文字ずつ行うように変更されます。
.PP
スキャナが YY_INPUT からファイルの終りを通知された場合、
スキャナは
.B yywrap()
関数をチェックします。
.B yywrap()
関数が偽(ゼロ)を返す場合、関数は続行中であるとされ、
.I yyin
を別の入力ファイルを指すように設定し、スキャンを続行します。
関数が真(非ゼロ)を返す場合、スキャナは終了し、呼び出し元に 0 を返します。
どちらの場合も開始条件は変化しないことに注意して下さい;
つまり
.B INITIAL
には戻り
.I ません。
.PP
独自の
.B yywrap()
を設定しない場合、
.B %option noyywrap
(この場合スキャナは
.B yywrap()
が 1 を返したかのように動作します)を使用するか、フラグ
.B \-ll
を指定してデフォルトのルーチン(常に 1 を返します)を使用しなければなりません。
.PP
ファイルではなくメモリ中のバッファからスキャンするための 3 つのルーチンを
使用可能です:
.B yy_scan_string(), yy_scan_bytes(), yy_scan_buffer()
これらに関する議論は複数の入力バッファの節を参照して下さい。
.PP
スキャナは、自己の
.B ECHO
出力を
.I yyout
グローバル(デフォルトでは標準出力であり、
別の
.B FILE
ポインタに割り当てることで再定義できます)に書きます。
.SH 開始条件
.I flex
は、条件的に有効となるルールのための機構を提供します。
パターンのプレフィックスが "<sc>" となっているルールは、
スキャナが "sc" という名前の開始条件にいる場合のみ有効です。
例えば、
.nf

    <STRING>[^"]*        { /* eat up the string body ... */
                ...
                }

.fi
はスキャナが "STRING" 開始条件にいる時のみ有効であり、
.nf

    <INITIAL,STRING,QUOTE>\\.        { /* handle an escape ... */
                ...
                }

.fi
は現在の開始条件が、
"INITIAL", "STRING", "QUOTE" のいずれかの場合のみ有効です。
.PP
開始条件は、入力の定義(先頭)部において、インデントされない行で
.B %s
もしくは
.B %x
から始まり名前が続く行において宣言されます。
前者は
.I 内包的
開始条件を、
後者は
.I 排他的
開始条件を、それぞれ宣言します。
開始条件を有効にするのは
.B BEGIN
アクションです。
次の
.B BEGIN
アクションが実行されるまで、与えられた開始条件のルールは有効であり、
他の開始条件のルールは無効です。
開始条件が
.I 内包的
な場合、開始条件を持たないルールもまた有効です。
開始条件が
.I 排他的
な場合、
開始条件を満たすルール
.I だけ
が有効です。
同じ排他開始条件に依存するルールの組は、
.I flex
入力中の別のルールとは独立なスキャナを記述します。
そのため、排他開始条件を使用すれば、"ミニスキャナ"
(別部分とは文法的に異なる部分(例えばコメント)に対するスキャナ)
を簡単に指定できます。
.PP
内包的開始条件と排他的開始条件とがまだ少し曖昧であるなら、
両者の関係を表す例を示して説明します。以下のルールの組:
.nf

    %s example
    %%

    <example>foo   do_something();

    bar            something_else();

.fi
.nf

    %x example
    %%

    <example>foo   do_something();

    <INITIAL,example>bar    something_else();

.fi
と等価です。
.B <INITIAL,example>
が無いと、2 番目の例における
.I bar
パターンは、開始条件が
.B example
の場合、有効となりません(すなわちマッチしません)。
.B <example>
だけを
.I bar
につけると、
.B example
だけにおいて有効となり、
.B INITIAL
では有効となりません。一方、最初の例ではどちらの場合でも有効です。
なぜなら最初の例では
.B example
開始条件は
.I 内包的
.B (%s)
開始条件だからです。
.PP
特殊な開始条件指定子
.B <*>
は全ての開始条件にマッチすることに注意して下さい。
このため、上の例は次のようにも書けます;
.nf

    %x example
    %%

    <example>foo   do_something();

    <*>bar    something_else();

.fi
.PP
デフォルトルール(マッチしなかった文字に対しては
.B ECHO
です)は開始条件中でも有効です。
これは次のものと等価です:
.nf

    <*>.|\\n     ECHO;

.fi
.PP
.B BEGIN(0)
は、開始条件の無いルールだけが有効である、最初の状態に戻ります。
この状態は開始条件 "INITIAL" として参照できるため、
.B BEGIN(INITIAL)
.B BEGIN(0)
と等価です。
(開始条件名を括る括弧は不要ですが、良いスタイルであるとされています。)
.PP
.B BEGIN
アクションは、ルール部の先頭のインデントされたコード中に現れても良いです。
例えば以下の例では、
.B yylex()
が呼ばれグローバル変数
.I enter_special
が真の場合には、スキャナは "SPECIAL" 開始条件に入ります:
.nf

            int enter_special;

    %x SPECIAL
    %%
            if ( enter_special )
                BEGIN(SPECIAL);

    <SPECIAL>blahblahblah
    ...more rules follow...

.fi
.PP
開始条件を説明するために、
"123.456" のような文字列を 2 通りの異なった解釈をするスキャナを示します。
デフォルトではこれは、
整数 "123" とドット ('.') と整数 "456" の 3 トークンに数えられます。
しかし、この文字列の前に "expect-floats" の文字列がある場合、
これは単一のトークンであるとされ、浮動小数点数 123.456 とされます:
.nf

    %{
    #include <math.h>
    %}
    %s expect

    %%
    expect-floats        BEGIN(expect);

    <expect>[0-9]+"."[0-9]+      {
                printf( "found a float, = %f\\n",
                        atof( yytext ) );
                }
    <expect>\\n           {
                /* that's the end of the line, so
                 * we need another "expect-number"
                 * before we'll recognize any more
                 * numbers
                 */
                BEGIN(INITIAL);
                }

    [0-9]+      {
                printf( "found an integer, = %d\\n",
                        atoi( yytext ) );
                }

    "."         printf( "found a dot\\n" );

.fi
次は、C のコメントを理解(して捨てる)一方で、
現在の入力行を数えるスキャナです。
.nf

    %x comment
    %%
            int line_num = 1;

    "/*"         BEGIN(comment);

    <comment>[^*\\n]*        /* eat anything that's not a '*' */
    <comment>"*"+[^*/\\n]*   /* eat up '*'s not followed by '/'s */
    <comment>\\n             ++line_num;
    <comment>"*"+"/"        BEGIN(INITIAL);

.fi
このスキャナは各ルールで可能な最大のテキストにマッチしようとする場合、
ちょっとした問題が起こります。
一般的には、高速なスキャナを記述する場合、
各ルールで最大のマッチを得ようとすることが最も成功します。
.PP
開始条件名は実際には整数値であり、格納することが出来ることに注意して下さい。
そのため、上記例は以下のように拡張できます:
.nf

    %x comment foo
    %%
            int line_num = 1;
            int comment_caller;

    "/*"         {
                 comment_caller = INITIAL;
                 BEGIN(comment);
                 }

    ...

    <foo>"/*"    {
                 comment_caller = foo;
                 BEGIN(comment);
                 }

    <comment>[^*\\n]*        /* eat anything that's not a '*' */
    <comment>"*"+[^*/\\n]*   /* eat up '*'s not followed by '/'s */
    <comment>\\n             ++line_num;
    <comment>"*"+"/"        BEGIN(comment_caller);

.fi
さらに、現在の開始条件を整数値であるマクロ
.B YY_START
にてアクセスできます。
例えば、上記の
.I comment_caller
への代入は次のように記述できます。
.nf

    comment_caller = YY_START;

.fi
flex は
.B YYSTATE
.B YY_START
のエイリアスとして提供します
(AT&T の
.I lex
が使用しています)。
.PP
開始条件は独自の名前空間を持たないことに注意して下さい;
%s や %x の宣言における名前宣言の扱いは #define と同じです。
.PP
最後に、排他的開始条件を使用する、
展開されたエスケープシーケンスを含む(長すぎる文字列のチェックは含みません)
C スタイルのクオート文字列へのマッチ方法を示します:
.nf

    %x str

    %%
            char string_buf[MAX_STR_CONST];
            char *string_buf_ptr;


    \\"      string_buf_ptr = string_buf; BEGIN(str);

    <str>\\"        { /* saw closing quote - all done */
            BEGIN(INITIAL);
            *string_buf_ptr = '\\0';
            /* return string constant token type and
             * value to parser
             */
            }

    <str>\\n        {
            /* error - unterminated string constant */
            /* generate error message */
            }

    <str>\\\\[0-7]{1,3} {
            /* octal escape sequence */
            int result;

            (void) sscanf( yytext + 1, "%o", &result );

            if ( result > 0xff )
                    /* error, constant is out-of-bounds */

            *string_buf_ptr++ = result;
            }

    <str>\\\\[0-9]+ {
            /* generate error - bad escape sequence; something
             * like '\\48' or '\\0777777'
             */
            }

    <str>\\\\n  *string_buf_ptr++ = '\\n';
    <str>\\\\t  *string_buf_ptr++ = '\\t';
    <str>\\\\r  *string_buf_ptr++ = '\\r';
    <str>\\\\b  *string_buf_ptr++ = '\\b';
    <str>\\\\f  *string_buf_ptr++ = '\\f';

    <str>\\\\(.|\\n)  *string_buf_ptr++ = yytext[1];

    <str>[^\\\\\\n\\"]+        {
            char *yptr = yytext;

            while ( *yptr )
                    *string_buf_ptr++ = *yptr++;
            }

.fi
.PP
上記例のように同一の開始条件を持つ全てのルールの前に
開始条件を書かねばならないことが多いです。
flex はこれを簡単かつ綺麗にするため開始条件
.I スコープ
を導入しました。
開始条件スコープは次のように始まります:
.nf

    <SCs>{

.fi
ここで
.I SCs
は 1 つ以上の開始条件のリストです。
開始条件スコープ内では、
最初の
.I '{'
にマッチするまでの
.I '}'
において、全てのルールは自動的に
.I <SCs>
のプレフィックスが付きます。
そのため、例えば
.nf

    <ESC>{
        "\\\\n"   return '\\n';
        "\\\\r"   return '\\r';
        "\\\\f"   return '\\f';
        "\\\\0"   return '\\0';
    }

.fi
は次のものと等価です:
.nf

    <ESC>"\\\\n"  return '\\n';
    <ESC>"\\\\r"  return '\\r';
    <ESC>"\\\\f"  return '\\f';
    <ESC>"\\\\0"  return '\\0';

.fi
開始条件スコープはネストすることが出来ます。
.PP
開始条件のスタックを制御するために 3 つのルーチンを使用可能です:
.TP
.B void yy_push_state(int new_state)
現在の開始条件を開始条件スタックの先頭にプッシュし、
.B BEGIN new_state
を使用したかのように
.I new_state
に切り替えます
(開始条件名は整数値でもあることを思い出して下さい)。
.TP
.B void yy_pop_state()
スタックの先頭をポップし、
.B BEGIN
を使用してその開始条件に切り替えます。
.TP
.B int yy_top_state()
スタックの内容を変更せずに、スタックの先頭を返します。
.PP
開始条件スタックは動的に大きくなり、
また組み込み時のサイズ制限はありません。
メモリを使い切ると、プログラム実行は中止されます。
.PP
開始条件スタックを使用するためには、スキャナは
.B %option stack
ディレクティブをインクルードする必要があります
(下記オプションを参照して下さい)。
.SH 複数の入力バッファ
スキャナによっては(ファイルの "include" をサポートする等)
複数の入力ストリームを扱う必要があります。
.I flex
スキャナでは大きなバッファリングを行うため、
スキャンコンテキストに影響される
.B YY_INPUT
を単純に書き換えるだけでは次の入力がどこから読まれるのかを制御できません。
.B YY_INPUT
が呼ばれるのはスキャナがバッファの終りに到達する時だけですので、
例えば "include" のように入力元を切り替える必要のある文をスキャンした後でも
長時間を費す場合があります。
.PP
この様な問題を解決するため、
.I flex
は複数の入力バッファを生成して切り替える機構を提供します。
入力バッファは次のように生成されます:
.nf

    YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )

.fi
これは
.I FILE
ポインタと size を取り、与えられる file に関連し
.I size
文字を保持するに十分なバッファを生成します
(疑わしい場合には size には
.B YY_BUF_SIZE
を使用して下さい)。
これは、別のルーチン(下記参照)に渡すための
.B YY_BUFFER_STATE
ハンドルを返します。
.B YY_BUFFER_STATE
のタイプは
.B struct yy_buffer_state
構造体へのポインタであるため、
安全のため YY_BUFFER_STATE 変数を
.B ((YY_BUFFER_STATE) 0)
と初期化することが出来、
スキャナではなくソースファイルにおいて
入力バッファを正しく宣言するためにこの構造体を参照することが出来ます。
.B yy_create_buffer
呼び出しにおける
.I FILE
ポインタは
.B YY_INPUT
から見える
.I yyin
の値と同じようにだけ使用されることに注意して下さい;
.B YY_INPUT
を再定義して
.I yyin
を使わないようにすることにより、
.B yy_create_buffer
に対して安全にニル
.I FILE
ポインタを渡せます。
スキャンするバッファを選択するためには次のようにします:
.nf

    void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )

.fi
これはスキャナの入力バッファを切り替え、
トークンが
.I new_buffer
から来るようになります。
新たなファイルをオープンして
.I yyin
を指すのではなく、スキャンを継続するために yywrap() から
.B yy_switch_to_buffer()
を使用することがあることに注意して下さい。
また、
.B yy_switch_to_buffer()
または
.B yywrap()
による入力元の切り替えは開始条件を変更し
.I ない
ことにも注意して下さい。
.nf

    void yy_delete_buffer( YY_BUFFER_STATE buffer )

.fi
はバッファに関連づけられたストレージの返還要求に使用します。(
.B buffer
はニルでも構いませんがこの場合このルーチンは何もしません。)
現在のバッファの内容をクリアするには次のようにします:
.nf

    void yy_flush_buffer( YY_BUFFER_STATE buffer )

.fi
この関数はバッファの内容を捨てるため、
次にスキャナがこのバッファとトークンのマッチを行う場合、
スキャナはまず
.B YY_INPUT
を使用してこのバッファをフィルします。
.PP
.B yy_new_buffer()
.B yy_create_buffer()
のエイリアスであり、動的オブジェクトの生成と破壊のために使用する C++ の
.I new
.I delete
との互換性のために提供しています。
.PP
最後に
.B YY_CURRENT_BUFFER
マクロは、現在のバッファに対する
.B YY_BUFFER_STATE
ハンドルを返します。
.PP
この機能を使用してインクルードファイルを展開するスキャナの記述例です(
.B <<EOF>>
機能は後述します):
.nf

    /* the "incl" state is used for picking up the name
     * of an include file
     */
    %x incl

    %{
    #define MAX_INCLUDE_DEPTH 10
    YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
    int include_stack_ptr = 0;
    %}

    %%
    include             BEGIN(incl);

    [a-z]+              ECHO;
    [^a-z\\n]*\\n?        ECHO;

    <incl>[ \\t]*      /* eat the whitespace */
    <incl>[^ \\t\\n]+   { /* got the include file name */
            if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
                {
                fprintf( stderr, "Includes nested too deeply" );
                exit( 1 );
                }

            include_stack[include_stack_ptr++] =
                YY_CURRENT_BUFFER;

            yyin = fopen( yytext, "r" );

            if ( ! yyin )
                error( ... );

            yy_switch_to_buffer(
                yy_create_buffer( yyin, YY_BUF_SIZE ) );

            BEGIN(INITIAL);
            }

    <<EOF>> {
            if ( --include_stack_ptr < 0 )
                {
                yyterminate();
                }

            else
                {
                yy_delete_buffer( YY_CURRENT_BUFFER );
                yy_switch_to_buffer(
                     include_stack[include_stack_ptr] );
                }
            }

.fi
ファイルではなくメモリ上の文字列をスキャンするための
入力バッファを設定するための 3 つのルーチンを使用可能です。
いずれも文字列をスキャンする新しい入力バッファを生成し、対応する
.B YY_BUFFER_STATE
ハンドル(終了時には
.B yy_delete_buffer()
にて消去します)を返します。新しいバッファに切り替える時には
.B yy_switch_to_buffer()
を使用し、次の
.B yylex()
の呼び出し時にはこの文字列をスキャン開始します。
.TP
.B yy_scan_string(const char *str)
NUL ターミネートされた文字列をスキャンします。
.TP
.B yy_scan_bytes(const char *bytes, int len)
.I len
バイト (NUL が含まれるかも知れません)を位置
.I bytes
からスキャンします。
.PP
どちらの関数も文字列もしくはバイト列の
.I コピー
を生成してからスキャンします。(
.B yylex()
はスキャンするバッファの内容を変更するため、これが望ましいのです。)
コピーを避けるためには次のようにします:
.TP
.B yy_scan_buffer(char *base, yy_size_t size)
バッファ内で
.I base
から
.I size
バイトの長さをスキャンします。最後の 2 バイトは
.B YY_END_OF_BUFFER_CHAR
(ASCII NUL)
である
.I 必要があります。
これらの最後の 2 バイトはスキャンされません;
そのためスキャンの内容は
.B base[0]
から
.B base[size-2]
までで両端を含みます。
.IP
この様になるように
.I base
を設定しなかった場合(つまり最後の 2 つの
.B YY_END_OF_BUFFER_CHAR
バイトを忘れた場合)、
.B yy_scan_buffer()
は新しいバッファを生成するのではなくニルポインタを返します。
.IP
.B yy_size_t
は整数型であり、
バッファの大きさを反映する整数式をこの型にキャストすることが出来ます。
.SH ファイルの終りのルール
特別ルール "<<EOF>>" は、
ファイルの終了時もしくは
yywrap() が非ゼロ(すなわち処理するファイルが無いことを表す)の時に
行われるべきアクションを表します。
アクションは以下の 4 つのうちのいずれかで終る必要があります。
.IP -
.I yyin
に新しいファイルを割り当てる(前のバージョンの flex では、
割り当て後に特別なアクション
.B YY_NEW_FILE
を呼び出す必要がありました;
今では不要です。);
.IP -
.I return
文を実行する;
.IP -
特別な
.B yyterminate()
アクションを実行する;
.IP -
.B yy_switch_to_buffer()
を使用して新たなバッファに切り替える
(上記例で示した通り)。
.PP
<<EOF>> ルールを他のパターンと共に使用してはなりません;
他のパターンは開始条件のリストともにだけ満たされるからです。
満たされない <<EOF>> ルールが与えられた場合、
<<EOF>> アクションをまだ持っていない
.I 全ての
開始条件に適用されます。
<<EOF>> ルールを最初の開始条件だけに指定するためには次のようにして下さい。
.nf

    <INITIAL><<EOF>>

.fi
.PP
これらのルールは閉じていないコメントを捕まえる場合等に便利です。
例えば:
.nf

    %x quote
    %%

    ...other rules for dealing with quotes...

    <quote><<EOF>>   {
             error( "unterminated quote" );
             yyterminate();
             }
    <<EOF>>  {
             if ( *++filelist )
                 yyin = fopen( *filelist, "r" );
             else
                yyterminate();
             }

.fi
.SH 雑多なマクロ
マクロ
.B YY_USER_ACTION
にはマッチルールアクションに先だって常に行うアクションを定義できます。
例えば、yytext を小文字に変換するルーチンを呼ぶように #define 出来ます。
.B YY_USER_ACTION
起動時には、変数
.I yy_act
はマッチしたルールの番号を与えます(ルールは 1 番から数えます)。
各ルールがマッチする頻度を知りたい場合を想像して下さい。
以下に仕掛けを示します:
.nf

    #define YY_USER_ACTION ++ctr[yy_act]

.fi
ここで
.I ctr
は配列であり、それぞれのルールがマッチした回数を計数します。
マクロ
.B YY_NUM_RULES
はルールの総数を表すため(
.B \-s
を使った時でさえデフォルトルールを含みます)、
正しい
.I ctr
の宣言は次のようになります:
.nf

    int ctr[YY_NUM_RULES];

.fi
.PP
マクロ
.B YY_USER_INIT
には最初のスキャンの前に常に行うアクションを再定義できます
(スキャナの内部初期化の前に行われます)。
例えばデータ表を読み込んだり、ログファイルをオープンするために使用できます。
.PP
マクロ
.B yy_set_interactive(is_interactive)
は現在のバッファが
.I 対話的
と見倣されているか否かを制御するために使用します。
対話的なバッファの処理は遅くなりますが、
スキャナの入力元が対話的でありバッファをフィルするのを待つことに起因する
問題を避けるためには指定しなければなりません(以下の
.B \-I
.B %option interactive
フラグに関する議論を参照して下さい)。
マクロ起動時に非ゼロを指定するとバッファは対話的になり、
ゼロを指定すると非対話的になります。
このマクロの使用は
.B %option interactive ,
.B %option always-interactive ,
.B %option never-interactive
に優先します(下記オプションを参照して下さい)。
バッファをスキャンして対話的である(もしくはでない)と判断される前に、
.B yy_set_interactive()
を起動して下さい。
.PP
マクロ
.B yy_set_bol(at_bol)
は現在のバッファにおける次のトークンに対するマッチのためのスキャンが
行頭から始まるか否かを制御します。
非ゼロのマクロ引数は、'^' が付いたルールを有効にしますが、
ゼロのマクロ引数は '^' が付いたルールを無効にします。
.PP
現在のバッファからスキャンされた次のトークンが有効な '^' ルールを持つ時、
マクロ
.B YY_AT_BOL()
は真を返します。
そうでない場合は偽を返します。
.PP
生成されたスキャナでは、全てのアクションは大きな一つの switch 文に
集められ、
.B YY_BREAK
で分けられています。
.B YY_BREAK
は再定義可能です。デフォルトではそれぞれのルールのアクションを
分けるための単なる "break" です。
.B YY_BREAK
を再定義することにより、例えば C++ ユーザが
#define YY_BREAK を何もしないように定義し
(ただし全てのルールが "break" か "return" で終るように
注意しなければなりません!)、
ルールのアクションが "return" で終ることにより
.B YY_BREAK
がアクセスできないことに起因する、
到達できない文があるという警告を避けることが出来ます。
.SH ユーザが使用可能な値
この節ではユーザがルールのアクション部分で使用可能な値をまとめます。
.IP -
.B char *yytext
現トークンのテキストを保持しています。内容を変更しても構いませんが、
その長さを伸ばしてはいけません(終りに文字を追加してはいけない)。
.IP
スキャナの記述の最初の部分に特別な指示である
.B %array
が書かれているとき、
.B yytext
.B char yytext[YYLMAX]
と定義されます。
.B YYLMAX
はマクロで、デフォルトの値 (多くの場合8KB) を変更したい場合には
最初の部分で再定義可能です。
.B %array
を使うといくらか遅いスキャナになりますが、
.B yytext
の値は
.I input()
.I unput()
の呼び出しでも破壊されなくなります。
.B yytext
が文字ポインタである場合、
これらの関数呼び出しは
.B yytext
を破壊する可能性があります。
.B %array
と対称な指定
.B %pointer
がデフォルトです。
.IP
C++ のスキャナクラスを生成する (オプション
.B \-+
) ときには
.B %array
は使えません。
.IP -
.B int yyleng
現トークンの長さを保持しています。
.IP -
.B FILE *yyin
はデフォルトで
.I flex
が読むファイルです。再定義することは可能ですが、スキャンを
始める前か EOF に到達した後でのみ再定義は意味を持ちます。
スキャンの途中で変更すると予想外の結果をもたらします。
というのも
.I flex
は入力をバッファリングしているからです;
そのような場合には、直接再定義せず
.B yyrestart()
を使って下さい。
ファイルの終わりでスキャンが終了した場合には
.I yyin
を新しい入力ファイルに割り当て、
再びスキャナを呼び出してスキャンを続けることが出来ます。
.IP -
.B void yyrestart( FILE *new_file )
を呼ぶことで
.I yyin
が新しい入力ファイルを指すように出来ます。新しいファイルへの変更は
すぐに行われます (それまでにバッファに読み込まれていた入力は失われます)。
.I yyin
を引数として
.B yyrestart()
を呼ぶと、現在の入力バッファを捨てて同じ入力ファイルを
スキャンし続けることに注意して下さい。
.IP -
.B FILE *yyout
.B ECHO
アクションが行われる対象のファイルです。
ユーザが再割当することが出来ます。
.IP -
.B YY_CURRENT_BUFFER
カレントバッファの
.B YY_BUFFER_STATE
ハンドルを返します。
.IP -
.B YY_START
現在の開始条件に対応する整数値を返します。
続いてこの値を
.B BEGIN
と共に使うことで、スキャナをその開始条件へ戻すことが出来ます。
.SH YACC とのインタフェース
.I flex
の主な使用方法の一つは、
.I yacc
パーサジェネレータと共に使用することです。
.I yacc
パーサは
.B yylex()
と言う名前のルーチンを呼び、次の入力トークンを見付けるものとしています。
このルーチンは、次のトークンの型を返し、
関連する値をグローバルの
.B yylval
に格納するものとされています。
.I flex
.I yacc
と共に使うには、
.I yacc
.B \-d
オプションを指定して、
.I yacc
の入力に現れる全ての
.B %tokens
の定義を含む
.B y.tab.h
ファイルを生成させます。
このファイルは
.I flex
スキャナにインクルードされます。
例えばトークンの一つが "TOK_NUMBER" である場合、
スキャナの一部分は次のようになっています:
.nf

    %{
    #include "y.tab.h"
    %}

    %%

    [0-9]+        yylval = atoi( yytext ); return TOK_NUMBER;

.fi
.SH オプション
.I flex
には以下のようなオプションがあります:
.TP
.B \-b
バックアップ情報を
.I lex.backup
に出力します。
このファイルには、スキャナのバックアップ(backing-up)を必要とする状態と
それに対応する入力文字の一覧がリストされます。
ルールを追加することでバックアップ状態を取り除くこと
ができます。バックアップ状態が
.I 全て
取り除かれ、
.B \-Cf
または
.B \-CF
を指定すると、生成されたスキャナの実行速度が向上します(
.B \-p
フラグを見て下さい)。
スキャナをぎりぎりまで最適化しようとしてるユーザのみが
このオプションに関係あります。
(後述の性能関連の節を見て下さい。)
.TP
.B \-c
何もしません。POSIX 互換のために用意されています。
.TP
.B \-d
生成されたスキャナが
.I デバッグ
モードで実行されます。
.B yy_flex_debug
が非ゼロの場合(デフォルト)、
パターンが認識されるたびに、スキャナは次のようなメッセージを
.I 標準エラー出力
へ出力します。
.nf

    --accepting rule at line 53 ("the matched text")

.fi
行番号はスキャナを定義しているファイル (flexに与えられたファイル)
でのルールの位置です。
スキャナがバックアップしたとき、デフォルトルールを受け入れたとき、
入力バッファの最後に到達したとき (あるいは、NULに到達したとき;
スキャナには、この二つの区別はつきません) 、ファイルの最後に到達した
ときにもメッセージが出力されます。
.TP
.B \-f
.I 高速なスキャナ
を指定します。
テーブル圧縮は行われず、標準入出力をバイパスします。
その結果生成されるスキャナは大きくなりますが、高速なものになります。
このオプションは
.B \-Cfr
と同等です (以下を参照)。
.TP
.B \-h
.I flex
のオプションの要約からなる "ヘルプ" を
.I 標準出力
に書き出し終了します。
.B \-?
.B \-\-help
とは
.B \-h
と同じです。
.TP
.B \-i
.I 大文字小文字を区別しない
スキャナを生成します。
.I flex
の入力パターンに与えられる文字が大文字であるか小文字であるかは区別されず、
スキャナに入力される文字列は大文字小文字に関係なくマッチします。
マッチしたテキスト
.I yytext
では入力時の大文字小文字が保存されます (大文字を小文字に変換したりしません)。
.TP
.B \-l
AT&T の
.I lex
の実装に対して最大限の互換性を持たせます。これは
.I 完全な
互換性を意味しません。
このオプションを使用すると性能に大きな影響があります。
このオプションは、
.B \-+, \-f, \-F, \-Cf, \-CF
と同時に使用できません。詳しくは、
後述の "Lex および POSIX との非互換性" の節を御覧下さい。
またこのオプションを使用すると、
.B YY_FLEX_LEX_COMPAT
が生成されたスキャナの名前に #define されます。
.TP
.B \-n
何もしません。POSIX 互換のためにだけ用意されたオプションです。
.TP
.B \-p
性能情報を標準エラー出力に出力します。
.I flex
入力ファイルの記述のうち、
生成されるスキャナの性能低下の深刻な原因となる部分について、
コメントされます。
オプションを2回指定すると、より細かな性能低下についても
コメントが出力されます。
.IP
.B REJECT
.B %option yylineno
・可変長右文脈(欠陥/バグの節で後述)は多大なる性能への悪影響があります;
.I yymore()
の使用・
.B ^
オペレータ・
.B \-I
フラグは小さな性能の悪影響があります。
.TP
.B \-s
.I デフォルトルール
(マッチしないスキャナの入力を
.I 標準出力
に出力する)
が抑制されます。ルールにマッチしない入力が表れたとき、スキャナは
エラーで異常終了します。
スキャナのルールの組に抜けが無いかを確認する場合に有効です。
.TP
.B \-t
.B lex.yy.c
ではなく、標準出力にスキャナを書き出します。
.TP
.B \-v
生成するスキャナの特徴の要約を
.I 標準エラー出力
に出力するように
.I flex
に指示します。
ほとんどの特徴は通常の
.I flex
ユーザには意味がありませんが、最初の行は
.I flex
のバージョンを表示し(
.B \-V
で表示されるもと同じです)、次の行はデフォルトを含むスキャナ生成時のフラグです。
.TP
.B \-w
警告メッセージを抑制します。
.TP
.B \-B
.I 対話的
なスキャナ (以下の
.B \-I
の項を参照) ではなく
.I バッチ的
なスキャナを生成するよう
.I flex
に指示します。
通常
.B \-B
を使用するのは、スキャナを対話的に使用しないことが
.I 分かっている
時であり、
.I 少しでも
性能を追求したい時です。
より大きい性能を追求する場合には、
.B \-Cf
もしくは
.B \-CF
オプションを使用すべきです(後述)。
.B \-B
を自動的に設定します。
.TP
.B \-F
.ul
高速な
スキャナテーブルの表現を使う(標準入出力はバイパスする)ことを指定します。
この表現は、完全テーブル表現
.B (-f)
とほぼ同じぐらい高速で、
ある種のパターンに対してはかなり小さく (ある種に対しては大きく)
なります。
通常、次のように、パターンの組が "keywords" とその対応
および "identifier" ルールからなる場合:
.nf

    "case"    return TOK_CASE;
    "switch"  return TOK_SWITCH;
    ...
    "default" return TOK_DEFAULT;
    [a-z]+    return TOK_ID;

.fi
この場合、完全テーブル表現を使用する方が良いです。
もし "identifier" ルールからのみ表現され、
キーワードを検知するためにハッシュ表等を使用する場合は、
.B -F
を使用する方が良いです。
.IP
このオプションは
.B \-CFr
と等価です (以下を参照)。
これは
.B \-+
オプションとは同時に指定できません。
.TP
.B \-I
.I flex
.I 対話的
なスキャナを生成するように指示します。
対話的なスキャナは、
先読みすることによりマッチするトークンが完全に決まる場合のみ先読みします。
現在のトークンが既に明らかな場合でも常に先読みする方法は、
必要時のみ先読みする方法より少し速いです。
しかし、常に先読みする方法では対話性能に著しく悪影響があります;
例えばユーザが改行を入力した場合、
.I 別の
トークンを入力するまでそれは改行として認識されません。
大概の場合、次の行全体を入力することになります。
.IP
.I flex
のスキャナのデフォルトは
.I 対話的
であり、例外は
.B \-Cf
.B \-CF
といったテーブル圧縮オプション(後述)使用時です。
高性能追求時にはこれらのオプションを使用しているべきですので、
これらのオプションを使用していない場合には、
.I flex
は実行時性能を少し犠牲にして直観的な対話的な振舞いを取っているものとします。
.B \-I
オプションを
.B \-Cf
.B \-CF
と共に
.I 使用できない
ことにも注意して下さい。
実際はこのオプションは不要です;
許される場合、デフォルトで有効になっています。
.IP
.B isatty()
がスキャナの入力に対して偽を返す場合、
.B \-I
が指定されていた場合でも、flex はバッチモードへ戻ります。
なにがあっても対話モードを強制するには、
.B %option always-interactive
(後述のオプションを参照) を使用します。
.IP
スキャナを対話的で
.I 無い
ように強制するには
.B \-B
(先述)を使用します。
.TP
.B \-L
.I flex
.B #line
ディレクティブを
.B lex.yy.c
中に生成しないように指示します。
デフォルトではこの #line ディレクティブを生成するので、
アクションにおけるエラーメッセージは、オリジナルの
.I flex
入力ファイル(
エラーが入力ファイルのコードに起因する場合)もしくは
ファイル
.B lex.yy.c
(
.I flex
の誤り -- 以下の電子メールアドレスに報告して下さい)
における正しい位置を与えます。
.TP
.B \-T
.I flex
.I トレース
モードで実行します。
入力の形式とその結果として出力される非決定性/決定性有限
オートマトンに関して
.I 標準エラー出力
に多量のメッセージを出力します。
このオプションは主に
.I flex
をメンテナンスするために使われます。
.TP
.B \-V
バージョン番号を
.I 標準出力
に出力して終了します。
.B \-\-version
.B \-V
と同じです。
.TP
.B \-7
7 ビットのスキャナを生成します。
すなわち、入力に 7 ビットの文字のみを使用することを意味します。
.B \-7
を指定する利点は、
.B \-8
オプション(後述)を指定して生成するテーブルの半分まで小さくなりうることです。
欠点は、入力に 8 ビット文字が含まれている時に、
スキャナがハングもしくはクラッシュすることです。
.IP
しかしながら、
.B \-Cf
.B \-CF
といったテーブル圧縮オプション使用時にはテーブル圧縮の効果は少なく、
移植性が著しく低下することに注意して下さい。
.I flex
のデフォルトの動作では、
.B \-Cf
.B \-CF,
を指定しない限り 8 ビットスキャナを生成します。
指定時には、
あなたのサイトが常に 8 ビットスキャナを生成するように
(USA 以外のサイトでは良くあります)していない場合には、
7 ビットスキャナを生成します。
flex が 7 ビットもしくは 8 ビットのいずれのスキャナを生成するのかを
知りたい場合には、上述の
.B \-v
の出力のフラグの要約を調べて下さい。
.IP
.B \-Cfe
もしくは
.B \-CFe
(これらのテーブル圧縮オプションおよび等価クラスは後述)
を使用しても、flex はデフォルトで 8 ビットスキャナを生成することに
注意して下さい。
なぜなら、完全な 8 ビットテーブルは 7 ビットテーブルと比べても
たいして高価にはならないからです。
.TP
.B \-8
8 ビットのスキャナを生成するように
.I flex
に指示します。すなわち 8 ビット文字を解釈します。
圧縮オプション
.B \-Cf
.B \-CF
使用時にのみ必要です。
なぜなら flex はデフォルトでは 8 ビットスキャナを生成するからです。
.IP
flex のデフォルト動作と 7 ビットおよび 8 ビットスキャナの
トレードオフに関しては、上記
.B \-7
の議論を見て下さい。
.TP
.B \-+
C++ のスキャナクラスを生成します。
詳しくは C++ スキャナの生成で後述します。
.TP
.B \-C[aefFmr]
テーブル圧縮の程度と、
より一般的には小さいスキャナと高速なスキャナとのトレードオフを指定します。
.IP
.B \-Ca
("アライン")
生成されるスキャナのテーブルは、
メモリアクセスおよび計算のためにアラインされるため、より大きなものになります。
RISC アーキテクチャではロングワードのフェッチおよび操作は
ショートワードといったより小さな大きさのものに対するものより効率的です。
場合によってはスキャナのテーブルサイズが通常の 2倍になることもあります。
.IP
.B \-Ce
.I 等価クラス
(同一の字句属性を持つ文字セット)を構築します
(例えば、
.I flex
入力中に数字が現れるのが文字クラス "[0-9]" のみの場合、
数字 '0', '1', ..., '9' は全て同じ等価クラスになります)。
多くの場合、等価クラスを用いることで最終的なテーブル/
オブジェクトファイルのサイズを劇的(平均して 1/2-1/5)に減らすことが出来ます。
また、その際の性能コストは非常に低く抑えられます
( 1文字スキャンするごとに 1回の配列検索を行うだけです)。
.IP
.B \-Cf
.I 完全(full)
スキャナテーブルを生成することを指示します -
.I flex
は、別の状態に関する類似した遷移関数をうまく利用するという、
テーブル圧縮手法を用いません。
.IP
.B \-CF
別の高速スキャナ表現(
.B \-F
フラグにて記述)を用いることを指定します。
このオプションは
.B \-+
と同時に使用できません。
.IP
.B \-Cm
.I flex
.I メタ等価クラス
を構築するよう指示します。
メタ等価クラスは一緒に使われることの多い等価クラス
(等価クラスが使われていないときには文字群) の集合です。
圧縮テーブルを使っているとき、
メタ等価クラスは多くの場合にかなりの効果的をもたらしますが、
やや性能に影響します
(1-2 回の条件テストと 1 回の配列検索がスキャンした文字ごとに行われます)。
.IP
.B \-Cr
生成されたスキャナは入力に対しては標準入出力ライブラリ(標準入出力)を
.I バイパス
します。
スキャナは、
.B fread()
.B getc()
ではなく、
.B read()
システムコールを使用します。
性能改善結果はシステムに依存します。
オプション
.B \-Cf
もしくは
.B \-CF
を使用していない場合には、
一般にこのオプションは性能をあまり改善しません。
.B \-Cr
を指定すると、例えばスキャナを設定する前に標準入出力を使用して
.I yyin
を読み取る等した場合奇妙な動作となり得ます
(標準入出力の入力バッファに以前読み込んだものを、スキャナは読めません)。
.IP
.B \-Cr
.B YY_INPUT
を定義した場合意味がありません
(前述の生成されたスキャナを参照)。
スキャナの呼出に先だって標準入力を使って
.I yyin
から読みだしているときには、予想外の振る舞いをすることがあります。
.IP
.B \-C
のみを指定したときには、スキャナはテーブル圧縮は行いますが、
等価クラスもメタ等価クラスも使いません。
.IP
オプション
.B \-Cf
.B \-CF
はオプション
.B \-Cm
を同時に指定しても意味をなしません -
なぜなら、テーブル圧縮が行われないときメタ等価クラス
は現れないからです。
それ以外のオプションは自由に組み合わせることが出来ます。
.IP
デフォルトの設定は
.B \-Cem
です。このとき
.I flex
は等価クラスとメタ等価クラスを生成します。
この設定は最も高いテーブル圧縮を行います。
テーブルサイズの大きさと実行の高速性はトレードオフの関係にあり、
一般に
.nf

    遅いが 小さい
          -Cem
          -Cm
          -Ce
          -C
          -C{f,F}e
          -C{f,F}
          -C{f,F}a
    速いが 大きい

.fi
となります。
小さいテーブルのスキャナは通常生成もコンパイルも高速であるため、
通常の開発時は最大の圧縮を行うでしょう。
.IP
製品のスキャナでは、
.B \-Cfe
が速度と大きさの良いバランスです。
.TP
.B \-ooutput
.B lex.yy.c
ではなくファイル
.B output
にスキャナを書くように flex に指示します。
.B \-o
.B \-t
オプションを組み合わせると、
スキャナは
.I 標準出力
に書かれますが、
.B #line
ディレクティブ(
.B \\-L
にて上述)はファイル
.B output
を参照します。
.TP
.B \-Pprefix
.I flex
の使うデフォルトのプレフィックス
.I "yy"
の代わりに
.I prefix
を使います。これはグローバル変数とファイル名に影響します。
例えば
.B \-Pfoo
とすると、
.B yytext
の名前は
.B footext
となります。
またデフォルトの出力ファイル名を
.B lex.yy.c
から
.B lex.foo.c
に変えます。
影響を受ける名前の一覧です:
.nf

    yy_create_buffer
    yy_delete_buffer
    yy_flex_debug
    yy_init_buffer
    yy_flush_buffer
    yy_load_buffer_state
    yy_switch_to_buffer
    yyin
    yyleng
    yylex
    yylineno
    yyout
    yyrestart
    yytext
    yywrap

.fi
(C++ スキャナ使用時には
.B yywrap
.B yyFlexLexer
だけが影響を受けます。)
スキャナの中では、グローバル変数および関数を
どちらの名前ででも参照できます;
外部的には修正した名前のみ持ちます。
.IP
このオプションを使用することにより、複数の
.I flex
プログラムを同一の実行形式に容易にリンクすることが出来ます。
しかし、このオプションは
.B yywrap()
の名前をも変えますので、
独自の(適切に名前を付けた)ルーチンをスキャナのために用意するか、
.B %option noyywrap
を使用して
.B \-ll
とリンクする
.I 必要があります。
どれもデフォルトでは提供されません。
.TP
.B \-Sskeleton_file
.I flex
がスキャナを構築するのに使うデフォルトの
スケルトンファイルに優先します。
.I flex
のメンテナンスや開発をする場合以外、このオプションは必要ありません。
.PP
.I flex
は、flex のコマンドラインではなく、
スキャナ仕様記述中からオプションを制御する機構を提供します。
これはスキャナの最初の部分に
.B %option
ディレクティブを含めることで実現できます。
単一の
.B %option
ディレクティブにおいて複数のオプションを指定でき、
また複数のディレクティブを flex 入力ファイルの最初の部分に置くことが出来ます。
.PP
ほとんどのオプションが単純な名前であり、
オプションとして前に "no" という語(空白をはさみません)を付けて
意味を反転できます。
数値は flex のフラグやその反転と等価です。
.nf

    7bit            -7 オプション
    8bit            -8 オプション
    align           -Ca オプション
    backup          -b オプション
    batch           -B オプション
    c++             -+ オプション

    caseful または
    case-sensitive  -i オプションの逆(デフォルト)

    case-insensitive または
    caseless        -i オプション

    debug           -d オプション
    default         -s オプションの逆
    ecs             -Ce オプション
    fast            -F オプション
    full            -f オプション
    interactive     -I オプション
    lex-compat      -l オプション
    meta-ecs        -Cm オプション
    perf-report     -p オプション
    read            -Cr オプション
    stdout          -t オプション
    verbose         -v オプション
    warn            -w オプションの逆
                    (-w オプションには "%option nowarn" を使用して下さい)

    array           "%array" と等価
    pointer         "%pointer" と等価(デフォルト)

.fi
.B %option
には、他では利用できない機能を提供するものもあります:
.TP
.B always-interactive
入力を常に "対話的" に扱うスキャナを生成するように flex に指示します。
通常、新たな入力ファイル毎にスキャナは
.B isatty()
を呼び出し、スキャナの入力元が対話的であり 1 度に 1 文字ずつ読むべきか
どうか判定しようとします。
一方このオプションを使用するとこの様な呼び出しは行いません。
.TP
.B main
スキャナに対し、
.B yylex()
を呼び出すだけのデフォルトの
.B main()
プログラムを提供するように指示します。
このオプションは
.B noyywrap
(後述)も暗黙的に指示します。
.TP
.B never-interactive
入力を "対話的" とはしないスキャナを生成するように flex に指示します
(これもまた
.B isatty()
を呼び出しません)。
これは
.B always-interactive
の逆です。
.TP
.B stack
開始条件スタックの使用を有効にします(前述の開始条件を参照)。
.TP
.B stdinit
設定されている場合 (すなわち
.B %option stdinit)
.I yyin
および
.I yyout
を、
デフォルトの
.I nil
ではなく、
.I 標準入力
.I 標準出力
に設定します。
既存の
.I lex
プログラムには、
ANSI C 互換ではないものの、この動作に依存しているものがあります。
ANSI C では
.I 標準入力
.I 標準出力
がコンパイル時の定数である必要はありません。
.TP
.B yylineno
入力から読み取った現在の行番号をグローバル変数
.B yylineno
に保持するスキャナを生成するように、
.I flex
に指示します。
このオプションは
.B %option lex-compat
から暗黙的に指定されます。
.TP
.B yywrap
セットされていない場合 (すなわち
.B %option noyywrap)
、スキャナはファイルの終りに際し
.B yywrap()
を呼ばず単にスキャンすべきファイルがもう無いものとするようになります(
ユーザが
.I yyin
を新しいファイルを指すようにし、再度
.B yylex()
を呼び出すまでです)。
.PP
.I flex
はルールアクションをスキャンし、
.B REJECT
.B yymore()
の機能が使われているかどうかを調べます。
.B reject
.B yymore
のオプションを使用すると、
オプションで指定した通りにこの判定に優先します。
オプションの指定は、セットして機能を使用していることを示す(例えば
.B %option reject)
、もしくはアンセットして機能を使用していないことを示す(例えば
.B %option noyymore)
ものとします。
.PP
次のオプションは文字列の値を取り、'=' で区切ります:
.nf

    %option outfile="ABC"

.fi
これは
.B -oABC
と同じであり、
.nf

    %option prefix="XYZ"

.fi
.B -PXYZ
と同じです。
最後に、
.nf

    %option yyclass="foo"

.fi
は C++ スキャナ生成時のみ有効(
.B \-+
オプション)です。これは
.I flex
に対して、
.B foo
.B yyFlexLexer
のサブクラスであることを知らせますので、
.I flex
はアクションを
.B yyFlexLexer::yylex()
ではなく
.B foo::yylex()
のメンバ関数とします。
また、(
.B yyFlexLexer::LexerError()
を起動することにより)呼び出すと実行時エラーを除去する
.B yyFlexLexer::yylex()
メンバ関数を生成します。
詳細は後述の C++ スキャナの生成を見て下さい。
.PP
生成されたスキャナから不要なルーチンを除きたい lint 純正主義者のために
多くのオプションが用意されています。
以下をアンセットすると(例えば
.B %option nounput
)、対応するルーチンは生成されるスキャナから除かれます:
.nf

    input, unput
    yy_push_state, yy_pop_state, yy_top_state
    yy_scan_buffer, yy_scan_bytes, yy_scan_string

.fi
(
.B yy_push_state()
等は
.B %option stack
を使用しない場合には現れません)。
.SH 性能関連
.I flex
の主なデザインゴールは高性能なスキャナを生成することです。
多くのルールセットを良く扱うことで最適化されます。
既に概説した
.B \-C
オプション使用によるテーブル圧縮に起因する速度への影響の他に、
性能を悪化させる多くのオプション/アクションがあります。
それらを高価なものから安価なものへと並べます:
.nf

    REJECT
    %option yylineno
    自由長の右文脈(trailing context)

    バックアップが必要なパターンの組
    %array
    %option interactive
    %option always-interactive

    '^' 行頭オペレータ
    yymore()

.fi
最初の 3 つは非常に高価であり、最後の 2 つは非常に安価です。
.B unput()
は潜在的に非常に大きな仕事をするルーチン呼び出しとして実装されているのに対し、
.B yyless()
は非常に安価なマクロです;
ですからスキャンした余分なテキストを戻すだけの場合には
.B yyless()
を使って下さい。
.PP
性能が重要な場合には、出来うる限りの努力でもって
.B REJECT
を避けて下さい。
これは特に高価なオプションです。
.PP
バックアップを取り除くと、乱雑になり、
ひどく苦労して複雑なスキャナを作ることになります。
実際的には
.B \-b
フラグを指定して
.I lex.backup
ファイルを生成することから始めます。例えば、入力
.nf

    %%
    foo        return TOK_KEYWORD;
    foobar     return TOK_KEYWORD;

.fi
に対しては、ファイルは次のようになります:
.nf

    State #6 is non-accepting -
     associated rule line numbers:
           2       3
     out-transitions: [ o ]
     jam-transitions: EOF [ \\001-n  p-\\177 ]

    State #8 is non-accepting -
     associated rule line numbers:
           3
     out-transitions: [ a ]
     jam-transitions: EOF [ \\001-`  b-\\177 ]

    State #9 is non-accepting -
     associated rule line numbers:
           3
     out-transitions: [ r ]
     jam-transitions: EOF [ \\001-q  s-\\177 ]

    Compressed tables always back up.

.fi
最初の数行は、
\&'o' に遷移できるが他の文字には遷移できない状態があり、
その状態では現在スキャンされたテキストは他のルールにはマッチしないことを
表します。
この状態が発生したのは、
入力ファイルの行 2, 3 のルールにマッチしようとした時です。
スキャナがこの様な状態にあり 'o' 以外の文字を読んだ場合には、
マッチするルールを探すためのバックアップが必要となります。
少し考えれば、これは "fo" を見た時にある状態に違いないことが分かるでしょう。
この様な時、'o' 以外のものが現れると、
スキャナは、単に 'f' にマッチする(デフォルトルール)ところまで
戻り(バックアップし)ます。
.PP
状態 #8 に関係するコメントは、
"foob" がスキャンされた時に問題があることを表しています。
実際、'a' 以外の文字に出会うと、スキャナは "foo" を受理するところまで戻ります。
同様に状態 #9 に関係するコメントは、
"fooba" がスキャンされ 'r' が続かない場合に関係します。
.PP
最後のコメントが通知するのは、
.B \-Cf
.B \-CF
を使っているのでなければ
バックアップを取り除こうと努力することは無意味であることです。
なぜなら、圧縮されたスキャナに対してそのようなことをしても、
性能上の利益は無いからです。
.PP
バックアップを取り除くためには "エラー" ルールを追加します:
.nf

    %%
    foo         return TOK_KEYWORD;
    foobar      return TOK_KEYWORD;

    fooba       |
    foob        |
    fo          {
                /* false alarm, not really a keyword */
                return TOK_ID;
                }

.fi
.PP
キーワードのリストからバックアップを取り除くには、"全てを捕まえる"
ルールを使用することが出来ます:
.nf

    %%
    foo         return TOK_KEYWORD;
    foobar      return TOK_KEYWORD;

    [a-z]+      return TOK_ID;

.fi
通常、適切な時にはこれは一番良い解決策です。
.PP
バックアップメッセージはカスケードすることが多いです。
複雑なルールの組では、数百ものメッセージを得るのは普通のことです。
しかし、これを解析すれば、バックアップを除去するためには
大抵の場合数ダースのルールにだけ関係あることが分かるでしょう
(しかし、間違えることが多く、誤ったルールが偶然有効なトークンにマッチし得ます。
将来の
.I flex
の機能では、
自動的にバックアップを除去するルールを追加するようになるかも知れません)。
.PP
バックアップを除去することにより利益があるのは、
.I 全ての
バックアップを除去した時だけということを覚えておくことは重要です。
たった一つを残しても何も得ることが出来ません。
.PP
.I 可変長の
右文脈 (左部分と右部分のいずれかもしくは両方が可変長)は
.B REJECT
とほぼ同じだけの(すなわち相当の)性能劣化となります。
そのため次のようなルール:
.nf

    %%
    mouse|rat/(cat|dog)   run();

.fi
は次のように書くか:
.nf

    %%
    mouse/cat|dog         run();
    rat/cat|dog           run();

.fi
次のように書いた方が良いです:
.nf

    %%
    mouse|rat/cat         run();
    mouse|rat/dog         run();

.fi
特別な '|' アクションは助けにはなり
.I ません
し、かえって状況を悪くします
(後述の欠陥/バグを参照)。
.LP
スキャナの性能を向上させるための余地(実現は最も容易)は、
マッチするトークンが長ければスキャナが高速になることにあります。
長いトークンではほとんどの入力処理は(短い)内部ループで処理され、
アクションのためにスキャナ環境を設定する追加の仕事(例えば
.B yytext)
をほとんどしないからです。
C コメントのスキャナを思い出しましょう:
.nf

    %x comment
    %%
            int line_num = 1;

    "/*"         BEGIN(comment);

    <comment>[^*\\n]*
    <comment>"*"+[^*/\\n]*
    <comment>\\n             ++line_num;
    <comment>"*"+"/"        BEGIN(INITIAL);

.fi
次のように書くと高速になります:
.nf

    %x comment
    %%
            int line_num = 1;

    "/*"         BEGIN(comment);

    <comment>[^*\\n]*
    <comment>[^*\\n]*\\n      ++line_num;
    <comment>"*"+[^*/\\n]*
    <comment>"*"+[^*/\\n]*\\n ++line_num;
    <comment>"*"+"/"        BEGIN(INITIAL);

.fi
今度は、改行毎に別のアクションの処理を行うのではなく、
改行認識はルール間で "分散" され、
可能な限り長いテキストにマッチするようになっています。
ルールの
.I 追加
はスキャナを遅く
.I しません!
スキャナの速度は、ルール数とも、
オペレータ '*' や '|' といったものに基づくルールの複雑さ
(この節の始めで扱いました)とも独立です。
.\" 括弧内自信無しです
.\" Apr 29 1997, horikawa@jp.freebsd.org
.PP
最後の高速化の例です:
1 行に 1 つずつであり別の文字は付かないような、
識別子とキーワードを全てファイルからスキャンすることを考えます。
最初は次のようになるでしょう:
.nf

    %%
    asm      |
    auto     |
    break    |
    ... etc ...
    volatile |
    while    /* it's a keyword */

    .|\\n     /* it's not a keyword */

.fi
後戻りを避けるために全てを捕まえるルールを導入します:
.nf

    %%
    asm      |
    auto     |
    break    |
    ... etc ...
    volatile |
    while    /* it's a keyword */

    [a-z]+   |
    .|\\n     /* it's not a keyword */

.fi
1 行に正確に 1 語だけあることが保証されている場合、
改行の認識を別のトークンと併せることで、
マッチの総数を半分に減らすことが出来ます:
.nf

    %%
    asm\\n    |
    auto\\n   |
    break\\n  |
    ... etc ...
    volatile\\n |
    while\\n  /* it's a keyword */

    [a-z]+\\n |
    .|\\n     /* it's not a keyword */

.fi
ここで、再度バックアップをスキャナに組み込んだことに
気を付けなければなりません。
実際
.I 我々は
入力ストリームはレターと改行だけであることを知っていますが、
.I flex
はこれが分からないため、
トークン "auto" などをスキャンした次の文字が改行でもレターでもない場合には
バックアップが必要であると考えます。
以前は "auto" ルールに適合しそれで終りでしたが、
今は "auto" ルールは無く、"auto\\n" ルールだけがあります。
バックアップの可能性を除去するためには、
最後の改行以外のルールを二重化するか、
そのような入力に出くわさないので分類は不要と分かっているため、
改行を導入しないもう一つの全てを捕まえるルールを導入することが出来ます:
.nf

    %%
    asm\\n    |
    auto\\n   |
    break\\n  |
    ... etc ...
    volatile\\n |
    while\\n  /* it's a keyword */

    [a-z]+\\n |
    [a-z]+   |
    .|\\n     /* it's not a keyword */

.fi
.B \-Cf
を付けてコンパイルすると、実際問題上
.I flex
で得られるほぼ最速になります。
.PP
最後の注意事項:
.I flex
は NUL にマッチする時には遅く、トークンが複数の NUL を含む時には特に遅いです。
テキストがしばしば NUL を含むものと予想される場合には、テキストの
.I 短い
部分とマッチするようにルールを書くべきです。
.PP
もう一つの性能に関する最終注意事項:
入力のマッチ方法の節で既に示したように、
大きなトークンを納めるために
.B yytext
のサイズを動的に変更すると処理が遅くなります。
なぜなら、(巨大な)トークンを再度先頭からスキャンしなおさねばならないからです。
性能が重要な場合、
テキストの "大きな" 部分にマッチさせるべきですが "巨大な" 部分にマッチさせる
べきではありません。
両者の堺目は 8K 文字/トークンです。
.SH C++ スキャナの生成
.I flex
は 2 通りの C++ スキャナ生成方法を提供します。
最初の方法は
.I flex
が生成したスキャナを単に C コンパイラではなく C++ コンパイラで
コンパイルするというものです。
この場合コンパイルエラーには出会わないはずです
(見付けた場合には作者の節で後述する電子メールアドレスに報告して下さい)。
この場合ルールにおいて C コードではなく C++ コードを書くことが出来ます。
スキャナのデフォルトの入力元は
.I yyin
のままであり、
デフォルトのエコー先は
.I yyout
のままであることに注意して下さい。
どちらも
.I FILE *
変数のままであり、C++
.I streams
ではないです。
.PP
.I flex
に C++ スキャナクラスを生成させることも出来ます。
.B \-+
オプションを指定する(もしくは等価的に
.B %option c++
を使う)とこのように実行され、
flex の実行形式名が '+' で終っている場合には自動的に指定されます。
このオプションを指定すると flex が生成するスキャナのデフォルトはファイル
.B lex.yy.cc
となり
.B lex.yy.c
ではありません。
生成されたスキャナは
2 つの C++ クラスとのインタフェースを定義するヘッダファイル
.I FlexLexer.h
をインクルードします。
.PP
最初のクラス
.B FlexLexer
は一般的なスキャナクラスを定義する抽象基盤クラスを提供します。
以下のメンバ関数を提供します:
.TP
.B const char* YYText()
最後にマッチしたテキストを返します。
.B yytext
と等価です。
.TP
.B int YYLeng()
最後にマッチしたトークンの長さを返します。
.B yyleng
と等価です。
.TP
.B int lineno() const
現在の入力の行番号(
.B %option yylineno
参照)もしくは
.B %option yylineno
を使用していない場合には
.B 1
を返します。
.TP
.B void set_debug( int flag )
スキャナのデバッグフラグをセットします。
.B yy_flex_debug
に代入するのと同じです(オプションの節で前述)。
スキャナ構築時に
.B %option debug
を使用してデバッグ情報を組み込む必要があることに注意して下さい。
.TP
.B int debug() const
現在のデバッグフラグの設定を返します。
.PP
また次のものと等価なメンバ関数も提供されます
.B yy_switch_to_buffer(),
.B yy_create_buffer()
(最初の引数は
.B istream*
オブジェクトポインタであり
.B FILE*
ではありません),
.B yy_flush_buffer(),
.B yy_delete_buffer(),
.B yyrestart()
(これもまた最初の引数は
.B istream*
オブジェクトポインタです)。
.PP
2 番目のクラスは
.I FlexLexer.h
で定義される
.B yyFlexLexer
であり、
.B FlexLexer
から導出したものです。
以下の追加のメンバ関数を定義します:
.TP
.B
yyFlexLexer( istream* arg_yyin = 0, ostream* arg_yyout = 0 )
与えられた入出力ストリームを使う
.B yyFlexLexer
オブジェクトを構築します。
指定しない場合にはそれぞれストリームのデフォルト
.B cin
.B cout
になります。
.TP
.B virtual int yylex()
これは
.B yylex()
が通常の flex スキャナに対して行ったのと同様の役割を担います:
ルールのアクションが値を返すまで、
入力ストリームをスキャンし、トークンを消費します。
.B yyFlexLexer
からサブクラス
.B S
を導出し
.B yylex()
から
.B S
のメンバ関数および変数をアクセスしたい場合、
.B %option yyclass="S"
を指定して
.B yyFlexLexer
ではなくサブクラスを使用することを
.I flex
に知らせる必要があります。
この場合
.B yyFlexLexer::yylex()
を生成するのではなく、
.I flex
.B S::yylex()
(および呼び出されたなら
.B yyFlexLexer::LexerError()
を呼び出すダミーの
.B yyFlexLexer::yylex()
も)を生成します。
.TP
.B
virtual void switch_streams(istream* new_in = 0,
.B
ostream* new_out = 0)
.B yyin
.B new_in
(非ニルの場合)
に再割当し、
.B yyout
.B new_out
(同様)に再割当します。
.B yyin
が再割当された場合には以前の入力バッファは消去されます。
.TP
.B
int yylex( istream* new_in, ostream* new_out = 0 )
まず入力ストリームを
.B switch_streams( new_in, new_out )
を使用して切り替え、
.B yylex()
の値を返します。
.PP
さらに、
.B yyFlexLexer
は次のプロテクトされた仮想関数を定義します。
スキャナにあわせてこれらを導出クラスにおいて再定義出来ます:
.TP
.B
virtual int LexerInput( char* buf, int max_size )
最大
.B max_size
文字を
.B buf
に読み込み、読めた文字数を返します。
入力の終りを示すには 0 文字を返します。"対話的" スキャナ(
.B \-B
.B \-I
フラグを参照)はマクロ
.B YY_INTERACTIVE
を定義することに注意して下さい。
.B LexerInput()
を再定義し、
対話的な入力元をスキャンする可能性があるかどうかに依存して
異なるアクションが必要となる場合、
この名前が存在するかどうかのテストは
.B #ifdef
にて可能です。
.TP
.B
virtual void LexerOutput( const char* buf, int size )
.B size
文字をバッファ
.B buf
から書き出します。
スキャナのルールが NUL を含むテキストにマッチ可能な場合、
NUL 終端されているこのバッファは "内部に" NUL を含んでいても構いません。
.TP
.B
virtual void LexerError( const char* msg )
致命的なエラーメッセージを報告します。
デフォルトのこの関数はメッセージをストリーム
.B cerr
に書き、終了します。
.PP
.B yyFlexLexer
オブジェクトは
.I 全ての
スキャン時の状態を含むことに注意して下さい。
それゆえこの様なオブジェクトをリエントラントなスキャナとして使用できます。
同一の
.B yyFlexLexer
クラスの複数のインスタンスを具体化可能であり、
複数の C++ スキャナクラスを組み合わせ上記
.B \-P
オプションを使用することで同一のプログラムで使用可能です。
.PP
最後に
.B %array
機能は C++ スキャナクラスでは使用できないことに注意して下さい;
.B %pointer
を使用しなければなりません(デフォルト)。
.PP
単純な C++ スキャナの例を以下に示します:
.nf

        // An example of using the flex C++ scanner class.

    %{
    int mylineno = 0;
    %}

    string  \\"[^\\n"]+\\"

    ws      [ \\t]+

    alpha   [A-Za-z]
    dig     [0-9]
    name    ({alpha}|{dig}|\\$)({alpha}|{dig}|[_.\\-/$])*
    num1    [-+]?{dig}+\\.?([eE][-+]?{dig}+)?
    num2    [-+]?{dig}*\\.{dig}+([eE][-+]?{dig}+)?
    number  {num1}|{num2}

    %%

    {ws}    /* skip blanks and tabs */

    "/*"    {
            int c;

            while((c = yyinput()) != 0)
                {
                if(c == '\\n')
                    ++mylineno;

                else if(c == '*')
                    {
                    if((c = yyinput()) == '/')
                        break;
                    else
                        unput(c);
                    }
                }
            }

    {number}  cout << "number " << YYText() << '\\n';

    \\n        mylineno++;

    {name}    cout << "name " << YYText() << '\\n';

    {string}  cout << "string " << YYText() << '\\n';

    %%

    int main( int /* argc */, char** /* argv */ )
        {
        FlexLexer* lexer = new yyFlexLexer;
        while(lexer->yylex() != 0)
            ;
        return 0;
        }
.fi
複数の(異なった)字句解析クラスを生成したい場合、
.B \-P
フラグ (もしくは
.B prefix=
オプション) を使用して各
.B yyFlexLexer
.B xxFlexLexer
等の別の名前にします。
次に字句解析クラスのソースごとに
.B <FlexLexer.h>
をインクルードします。
以下のように
.B yyFlexLexer
をリネームします:
.nf

    #undef yyFlexLexer
    #define yyFlexLexer xxFlexLexer
    #include <FlexLexer.h>

    #undef yyFlexLexer
    #define yyFlexLexer zzFlexLexer
    #include <FlexLexer.h>

.fi
これはあるスキャナに対し
.B %option prefix="xx"
を使用しもう一方に対し
.B %option prefix="zz"
を使用した場合です。
.PP
重要: 現在のスキャンクラスの形式は
.I 実験的
であり、メジャーリリースが変わると大きく変更される可能性があります。
.SH LEX および POSIX との非互換性
.I flex
は AT&T Unix の
.I lex
ツールのリライトですが(2 つの実装はいかなるコードも共有しません)、
いくばくかの拡張と非互換性を持っており、
どちらの実装でも受理可能なスキャナを書きたい方は
これを意識しなければなりません。
flex は POSIX
.I lex
仕様に完全合致しますが、例外は
.B %pointer
(デフォルト)使用と
.B unput()
呼び出しにより
.B yytext
の内容を破壊することであり、これは POSIX 仕様に反します。
.PP
この節では、
flex と AT&T lex と POSIX 仕様との間の全ての既知の非互換性を扱います。
.PP
.I flex
.B \-l
オプションはオリジナルの AT&T
.I lex
実装との最大の互換性を有効にしますが、
生成されたスキャナの性能は大きく低下します。
.B \-l
オプションを使用しても発生しうる非互換性は後で述べます。
.PP
.I flex
は以下の例外を除き
.I lex
と完全互換です:
.IP -
ドキュメントに記載されていない
.I lex
スキャナ内部の変数
.B yylineno
.B \-l
もしくは
.B %option yylineno
を使用しないとサポートされません。
.IP
.B yylineno
はスキャナ毎(単一のグローバル変数)ではなく、バッファ毎に管理されるべきです。
.IP
.B yylineno
は POSIX 仕様ではありません。
.IP -
.B input()
ルーチンは再定義できませんが、
ルールにマッチしたものに後続する文字を読むために呼ばれえます。
.B input()
がファイルの終りに到達すると、通常の
.B yywrap()
処理は終了します。``実際の'' ファイルの終りは
.I EOF
として返されます。
.IP
実際には入力は
.B YY_INPUT
マクロを定義することにより制御されます。
.IP
.B input()
を再定義できないという
.I flex
の制限は、最初に
.I yyin
を設定する以外のスキャナ入力制御方法を単に規定していないという、
POSIX 仕様と合致します。
.IP -
.B unput()
ルーチンは再定義できません。この制限は POSIX に合致しています。
.IP -
.I flex
スキャナは
.I lex
スキャナとは異なりリエントラントではありません。
実際、対話的なスキャナにおいて、
割り込みハンドラにてロングジャンプを用いてスキャナから脱出し、
その後スキャナを再度呼び出す場合、以下のメッセージを得るでしょう:
.nf

    fatal flex scanner internal error--end of buffer missed

.fi
スキャナに再度入るためには、まず以下のようにして下さい
.nf

    yyrestart( yyin );

.fi
この呼び出しにより入力バッファは捨てられることに注意して下さい;
通常これは対話的スキャナでは問題ではありません。
.IP
また、C++ スキャナクラスはリエントラント
.I です
ので、C++ を使用できるのなら、C++ を使用すべきです。
前述の "C++ スキャナの生成" を参照して下さい。
.IP -
.B output()
はサポートされていません。
.B ECHO
マクロからの出力はファイルポインタ
.I yyout
(デフォルトでは
.I 標準出力
)に対して行われます。
.IP
.B output()
は POSIX 仕様にはありません。
.IP -
.I lex
は排他的開始条件 (%x) をサポートしませんが、これは POSIX 仕様にあります。
.IP -
定義を展開する時、
.I flex
では括弧で括ります。
lex では以下は:
.nf

    NAME    [A-Z][A-Z0-9]*
    %%
    foo{NAME}?      printf( "Found it\\n" );
    %%

.fi
文字列 "foo" にはマッチしません。
なぜなら展開されたマクロはルール "foo[A-Z][A-Z0-9]*?" と等価になり、
優先度にて `?' は "[A-Z0-9]*" と結び付きます。
.I flex
ではルールが展開されると "foo([A-Z][A-Z0-9]*)?" となり、
文字列 "foo" がマッチします。
.IP
.B ^
で始まるか
.B $
で終る定義は、展開時に括弧で括らず、
これらのオペレータが定義において特別な意味を失わないようにすることに
注意して下さい。
しかし
.B <s>, /,
.B <<EOF>>
オペレータは
.I flex
の定義では使用できません。
.IP
.B \-l
を使用すると、
.I lex
の振舞いと同じく定義を括弧で括りません。
.IP
POSIX 仕様では、定義を括弧で括ります。
.IP -
.I lex
の実装によっては、
ルールのパターンの右側に空白がある場合、
ルールのアクションを別の行から始めることを許します:
.nf

    %%
    foo|bar<space here>
      { foobar_action(); }

.fi
.I flex
はこの機能をサポートしません。
.IP -
.I lex
.B %r
(Ratfor スキャナの生成)オプションはサポートされていません。
これは POSIX 仕様には含まれません。
.IP -
スキャナを
.B %array
を使用して構築したのではない限り、
.B unput()
呼び出し後には、次のトークンにマッチするまで
.I yytext
は未定義です。
これは
.I lex
にも POSIX 仕様にも当てはまりません。
.B \-l
オプションを指定するとこの非互換性を取り除きます。
.IP -
.B {}
(数値範囲)オペレータの優先度が異なります。
.I lex
は "abc{1,3}" を "1 度か 2 度か 3 度の 'abc' にマッチ" と解釈しますが、
.I flex
は "'ab' に 1 度か 2 度か 3 度の 'c' が続くものにマッチ" と解釈します。
後者が POSIX 仕様に合致します。
.IP -
.B ^
オペレータの優先度が異なります。
.I lex
は "^foo|bar" を "行頭の 'foo' か任意位置の 'bar' にマッチ" と解釈しますが、
.I flex
は "行頭の 'foo' か 'bar' にマッチ" と解釈します。
後者が POSIX 仕様に合致します。
.IP -
.I lex
でサポートされている
.B %a
等の特別なテーブルサイズの宣言は
.I flex
スキャナでは不要です;
.I flex
はこれらを無視します。
.IP -
.I flex
.I lex
のどちらでもスキャナを使用可能に書けるように、
.bd
FLEX_SCANNER
という名前を定義します。
スキャナを生成した
.I flex
のバージョンを表す
.B YY_FLEX_MAJOR_VERSION
.B YY_FLEX_MINOR_VERSION
を、スキャナは含みます
(例えば 2.5 リリースではこれらはそれぞれ 2 と 5 になります)。
.PP
以下の
.I flex
の機能は
.I lex
および POSIX 仕様には含まれません:
.nf

    C++ スキャナ
    %option
    開始条件スコープ
    開始条件スタック
    対話的/非対話的スキャナ
    yy_scan_string() 等
    yyterminate()
    yy_set_interactive()
    yy_set_bol()
    YY_AT_BOL()
    <<EOF>>
    <*>
    YY_DECL
    YY_START
    YY_USER_ACTION
    YY_USER_INIT
    #line ディレクティブ
    アクションの周りの %{}
    単一行における複数のアクション

.fi
さらにほぼ全ての flex フラグです。
リストの最後の機能の意味は、
.I flex
では複数のアクションをセミコロンで区切って同一行に記述可能ですが、
.I lex
では次の
.nf

    foo    handle_foo(); ++num_foos_seen;

.fi
は (驚くべきことに) 次のように切り詰められるということです。
.nf

    foo    handle_foo();

.fi
.I flex
はアクションを切り詰めません。
ブレースで括られないアクションは単純に行末で終了します。
.SH 診断
.I warning, rule cannot be matched
常に同じテキストにマッチするルールが前にあるので、
与えられたルールがマッチしません。
例えば以下の "foo" は "全てを捕まえる" ルールの後ろにありますので
決してマッチしません:
.nf

    [a-z]+    got_identifier();
    foo       got_foo();

.fi
スキャナ中で
.B REJECT
を使用するとこの警告を抑制します。
.PP
.I warning,
.B \-s
.I
option given but default rule can be matched
(おそらくある特定の開始条件のもとでは)
デフォルトルール (任意の一文字にマッチする) しか特定の入力に
対してはマッチしないことがあります。
.B \-s
を指定しているので、おそらくそうなりません。
.PP
.I reject_used_but_not_detected undefined
あるいは
.I yymore_used_but_not_detected undefined -
これらのエラーは コンパイル時に起きます。スキャナが
.B REJECT
もしくは
.B yymore()
を使っていますが
.I flex
がそのことに気づかなかったということです。
つまり、
.I flex
は最初の 2 つの部分を探しても
これらのアクションの出現を見つけられなかったのですが、
実際には何らかの方法
(例えば #include ファイルを介して)でこれらが記述されていた、ということです。
.B %option reject
.B %option yymore
を使用して、flex にこれらの機能を実際に使用していることを教えて下さい。
.PP
.I flex scanner jammed -
.B \-s
でコンパイルされたスキャナが、どのルールにもマッチしない
入力文字列に遭遇しました。
内部的な問題に起因してこのエラーが起こることもあります。
.PP
.I token too large, exceeds YYLMAX -
スキャナが
.B %array
を使っている場合に、あるルールが定数
.B YYLMAX
(デフォルトで 8K バイト) より大きな文字列とマッチしました。
.I flex
の入力ファイルの定義部で
.B YYLMAX
を #define することで値を大きくできます。
.PP
.I scanner requires \-8 flag to
.I use the character 'x' -
スキャナの記述に 8 ビットの文字
.I 'x'
を識別する部分があり、
.B \-Cf
もしくは
.B \-CF
のテーブル圧縮オプションのためにデフォルトの 7 ビットになっている
にもかかわらず、
\-8 オプションをつけていないということです。
詳細は
.B \-7
フラグのオプションの議論を参照して下さい。
.PP
.I flex scanner push-back overflow -
.B unput()
でテキストを戻しすぎたため、スキャナのバッファは
戻したテキストと現トークンを
.B yytext
に保てません。
この場合、理想的にはスキャナが動的にバッファの大きさを変えるべきですが、
現在のところそうなってはいません。
.PP
.I
input buffer overflow, can't enlarge buffer because scanner uses REJECT -
スキャナは非常に大きなトークンのマッチを調べていて、入力バッファを
拡張する必要が起きました。しかしながら、バッファの拡張は
.B
REJECT
を使うスキャナでは働きません。
.PP
.I
fatal flex scanner internal error--end of buffer missed -
スキャナが使用しているフレームから(を越えて)ロングジャンプした後、
再度スキャナに入った場合に起こります。
再度スキャナに入る前に:
.nf

    yyrestart( yyin );

.fi
を使うか、前述のように C++ スキャナクラスを使用するようにして下さい。
.PP
.I too many start conditions in <> construct! -
存在するより多くの開始条件を <> 中に記載しました
(少なくとも一つを二度記載しました)。
.SH 関連ファイル
.TP
.B \-ll
スキャナがリンクしなければならないライブラリ。
.TP
.I lex.yy.c
生成されたスキャナ(システムによっては
.I lexyy.c
という名前になります)。
.TP
.I lex.yy.cc
.B -+
を使った時に作成された C++ スキャナクラス。
.TP
.I <FlexLexer.h>
C++ スキャナベースクラス
.B FlexLexer
とその導出クラス
.B yyFlexLexer
を定義するヘッダファイル。
.TP
.I flex.skl
スケルトンスキャナ。
このファイルは flex の実行時ではなく、flex を構築する時のみ利用されます。
.TP
.I lex.backup
.B \-b
フラグ用のバックアップ情報(システムによっては
.I lex.bck
という名前になります)。
.SH 欠陥 / バグ
右文脈(trailing context)パターンの中には、正しくマッチせず
警告メッセージ ("dangerous trailing context") を出すものがあります。
これらのパターンは、
ルールの最初の部分が 2番目の頭の部分とマッチするようなものです。
例えば "zx*/xy*" の場合、'x*' は右文脈の頭の 'x' とマッチします。
(POSIX ドラフトではそのようなパターンにマッチするテキストは
未定義であると述べていることに注意して下さい。)
.PP
右文脈の中には、実際には固定長であるのにそうとは解釈されないものがあり、
上に述べた性能の低下が起こります。
特に、 '|' や {n} (例えば "foo{3}") は常に可変長であると解釈されます。
.PP
右文脈と特別なアクション '|' を組み合わせると
.I 固定の
右文脈がよりコストのかかる
.I 可変の
右文脈となります。例えば、次のようなものです:
.nf

    %%
    abc      |
    xyz/def

.fi
.PP
.B %array
もしくは
.B \-l
オプションを指定しない場合、
.B unput()
を使うと yytext と yyleng を破壊します。
.PP
NUL のパターンマッチングは他の文字の比較よりかなり遅くなっています。
.PP
入力バッファの動的な大きさの再調整は時間がかかります。これは現トークン
(一般に巨大)までのマッチした全テキストの再スキャンを伴うためです。
.PP
入力のバッファリングと先読みのため、 <stdio.h> ルーチンと
混合して使うことが出来ません。例えば、
.B getchar()
.I flex
のルールはうまく行きません。代わりに
.B input()
を使って下さい。
.PP
.B \-v
オプションで表示される全テーブルエントリには、
どのルールがマッチしたのかを決定するのに必要なテーブルエントリ数が
含まれていません。エントリの数はスキャナが
.B REJECT
を使っていないときには DFA 状態数に等しく、
使っているときには DFA 状態数よりいくらか大きくなります。
.PP
.B REJECT
がオプション
.B \-f
もしくは
.B \-F
とともに使えません。
.PP
.I flex
の内部アルゴリズムについてのドキュメントが必要です。
.SH 関連項目
lex(1), yacc(1), sed(1), awk(1)
.PP
John Levine, Tony Mason, and Doug Brown,
.I Lex & Yacc,
O'Reilly and Associates.
第 2 版を入手すること。
.PP
M. E. Lesk and E. Schmidt,
.I LEX \- Lexical Analyzer Generator
.PP
Alfred Aho, Ravi Sethi and Jeffrey Ullman,
.I Compilers: Principles, Techniques and Tools,
Addison-Wesley (1986).
.I flex
で使用しているパターンマッチング技法を解説している(決定性オートマトン)。
.SH 作者
Vern Paxson が多くのアイディアとインスピレーションを得る助けを
Van Jacobson から受けました。
オリジナルバージョンは Jef Poskanzer が作成しました。
高速テーブル表現は Van Jacobson のデザインの部分実装です。
この実装は Kevin Gong と Vern Paxson が行いました。
.PP
多くの
.I flex
ベータテスタ、フィードバッカ、コントリビュータ、特に Francois Pinard,
Casey Leedom,
Robert Abramovitz,
Stan Adermann, Terry Allen, David Barker-Plummer, John Basrai,
Neal Becker, Nelson H.F. Beebe, benson@odi.com,
Karl Berry, Peter A. Bigot, Simon Blanchard,
Keith Bostic, Frederic Brehm, Ian Brockbank, Kin Cho, Nick Christopher,
Brian Clapper, J.T. Conklin,
Jason Coughlin, Bill Cox, Nick Cropper, Dave Curtis, Scott David
Daniels, Chris G. Demetriou, Theo Deraadt,
Mike Donahue, Chuck Doucette, Tom Epperly, Leo Eskin,
Chris Faylor, Chris Flatters, Jon Forrest, Jeffrey Friedl,
Joe Gayda, Kaveh R. Ghazi, Wolfgang Glunz,
Eric Goldman, Christopher M. Gould, Ulrich Grepel, Peer Griebel,
Jan Hajic, Charles Hemphill, NORO Hideo,
Jarkko Hietaniemi, Scott Hofmann,
Jeff Honig, Dana Hudes, Eric Hughes, John Interrante,
Ceriel Jacobs, Michal Jaegermann, Sakari Jalovaara, Jeffrey R. Jones,
Henry Juengst, Klaus Kaempf, Jonathan I. Kamens, Terrence O Kane,
Amir Katz, ken@ken.hilco.com, Kevin B. Kenny,
Steve Kirsch, Winfried Koenig, Marq Kole, Ronald Lamprecht,
Greg Lee, Rohan Lenard, Craig Leres, John Levine, Steve Liddle,
David Loffredo, Mike Long,
Mohamed el Lozy, Brian Madsen, Malte, Joe Marshall,
Bengt Martensson, Chris Metcalf,
Luke Mewburn, Jim Meyering, R. Alexander Milowski, Erik Naggum,
G.T. Nicol, Landon Noll, James Nordby, Marc Nozell,
Richard Ohnemus, Karsten Pahnke,
Sven Panne, Roland Pesch, Walter Pelissero, Gaumond
Pierre, Esmond Pitt, Jef Poskanzer, Joe Rahmeh, Jarmo Raiha,
Frederic Raimbault, Pat Rankin, Rick Richardson,
Kevin Rodgers, Kai Uwe Rommel, Jim Roskind, Alberto Santini,
Andreas Scherer, Darrell Schiebel, Raf Schietekat,
Doug Schmidt, Philippe Schnoebelen, Andreas Schwab,
Larry Schwimmer, Alex Siegel, Eckehard Stolz, Jan-Erik Strvmquist,
Mike Stump, Paul Stuart, Dave Tallman, Ian Lance Taylor,
Chris Thewalt, Richard M. Timoney, Jodi Tsai,
Paul Tuinenga, Gary Weik, Frank Whaley, Gerhard Wilhelms, Kent Williams, Ken
Yap, Ron Zellar, Nathan Zelle, David Zuhn,
および私の最低のメールアーカイブ能力から滑り落ちた方々、
それらの方々の協力にも同様に感謝します。
.PP
Keith Bostic, Jon Forrest, Noah Friedman,
John Gilmore, Craig Leres, John Levine, Bob Mulcahy, G.T.
Nicol, Francois Pinard, Rich Salz, Richard Stallman
には多くの悩みの分散に関して感謝します。
.PP
Esmond Pitt と Earle Horton には 8 ビット文字サポートに関して;
Benson Margulies と Fred Burke には C++ サポートに関して;
Kent Williams と Tom Epperly には C++ クラスサポートに関して;
Ove Ewerlid には NUL のサポートに関して;
Eric Hughes には複数バッファのサポートに関して、それぞれ感謝します。
.PP
この作品は当初、私が CA Berkeley の Lawrence Berkeley Laboratory
における Real Time Systems Group にいた時に作成されました。
私に協力してくれた方々に感謝します。
.PP
コメントは vern@ee.lbl.gov に送って下さい。