Mercurial > emacs
comparison lisp/international/ccl.el @ 30845:dcfcae58d8d6
(declare-ccl-program): Docstring modified.
(ccl-execute-with-args): Likewise.
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Wed, 16 Aug 2000 10:57:57 +0000 |
parents | b37405134317 |
children | 496f65930f98 |
comparison
equal
deleted
inserted
replaced
30844:947edf38ac6f | 30845:dcfcae58d8d6 |
---|---|
35 ;; However, since CCL is designed as a powerful programming language, | 35 ;; However, since CCL is designed as a powerful programming language, |
36 ;; it can be used for more generic calculation. For instance, | 36 ;; it can be used for more generic calculation. For instance, |
37 ;; combination of three or more arithmetic operations can be | 37 ;; combination of three or more arithmetic operations can be |
38 ;; calculated faster than Emacs Lisp. | 38 ;; calculated faster than Emacs Lisp. |
39 ;; | 39 ;; |
40 ;; Here's the syntax of CCL program in BNF notation. | 40 ;; Syntax and semantics of CCL program is described in the |
41 ;; | 41 ;; documentation of `define-ccl-program'. |
42 ;; CCL_PROGRAM := | |
43 ;; (BUFFER_MAGNIFICATION | |
44 ;; CCL_MAIN_BLOCK | |
45 ;; [ CCL_EOF_BLOCK ]) | |
46 ;; | |
47 ;; BUFFER_MAGNIFICATION := integer | |
48 ;; CCL_MAIN_BLOCK := CCL_BLOCK | |
49 ;; CCL_EOF_BLOCK := CCL_BLOCK | |
50 ;; | |
51 ;; CCL_BLOCK := | |
52 ;; STATEMENT | (STATEMENT [STATEMENT ...]) | |
53 ;; STATEMENT := | |
54 ;; SET | IF | BRANCH | LOOP | REPEAT | BREAK | READ | WRITE | CALL | |
55 ;; | |
56 ;; SET := | |
57 ;; (REG = EXPRESSION) | |
58 ;; | (REG ASSIGNMENT_OPERATOR EXPRESSION) | |
59 ;; | integer | |
60 ;; | |
61 ;; EXPRESSION := ARG | (EXPRESSION OPERATOR ARG) | |
62 ;; | |
63 ;; IF := (if EXPRESSION CCL_BLOCK CCL_BLOCK) | |
64 ;; BRANCH := (branch EXPRESSION CCL_BLOCK [CCL_BLOCK ...]) | |
65 ;; LOOP := (loop STATEMENT [STATEMENT ...]) | |
66 ;; BREAK := (break) | |
67 ;; REPEAT := | |
68 ;; (repeat) | |
69 ;; | (write-repeat [REG | integer | string]) | |
70 ;; | (write-read-repeat REG [integer | ARRAY]) | |
71 ;; READ := | |
72 ;; (read REG ...) | |
73 ;; | (read-if (REG OPERATOR ARG) CCL_BLOCK CCL_BLOCK) | |
74 ;; | (read-branch REG CCL_BLOCK [CCL_BLOCK ...]) | |
75 ;; | (read-multibyte-character REG {charset} REG {code-point}) | |
76 ;; WRITE := | |
77 ;; (write REG ...) | |
78 ;; | (write EXPRESSION) | |
79 ;; | (write integer) | (write string) | (write REG ARRAY) | |
80 ;; | string | |
81 ;; | (write-multibyte-character REG(charset) REG(codepoint)) | |
82 ;; TRANSLATE := | |
83 ;; (translate-character REG(table) REG(charset) REG(codepoint)) | |
84 ;; | (translate-character SYMBOL REG(charset) REG(codepoint)) | |
85 ;; MAP := | |
86 ;; (iterate-multiple-map REG REG MAP-IDs) | |
87 ;; | (map-multiple REG REG (MAP-SET)) | |
88 ;; | (map-single REG REG MAP-ID) | |
89 ;; MAP-IDs := MAP-ID ... | |
90 ;; MAP-SET := MAP-IDs | (MAP-IDs) MAP-SET | |
91 ;; MAP-ID := integer | |
92 ;; | |
93 ;; CALL := (call ccl-program-name) | |
94 ;; END := (end) | |
95 ;; | |
96 ;; REG := r0 | r1 | r2 | r3 | r4 | r5 | r6 | r7 | |
97 ;; ARG := REG | integer | |
98 ;; OPERATOR := | |
99 ;; + | - | * | / | % | & | '|' | ^ | << | >> | <8 | >8 | // | |
100 ;; | < | > | == | <= | >= | != | de-sjis | en-sjis | |
101 ;; ASSIGNMENT_OPERATOR := | |
102 ;; += | -= | *= | /= | %= | &= | '|=' | ^= | <<= | >>= | |
103 ;; ARRAY := '[' integer ... ']' | |
104 | 42 |
105 ;;; Code: | 43 ;;; Code: |
106 | 44 |
107 (defgroup ccl nil | 45 (defgroup ccl nil |
108 "CCL (Code Conversion Language) compiler." | 46 "CCL (Code Conversion Language) compiler." |
1303 `(put ',name 'ccl-program-idx (register-ccl-program ',name ,vector))) | 1241 `(put ',name 'ccl-program-idx (register-ccl-program ',name ,vector))) |
1304 | 1242 |
1305 ;;;###autoload | 1243 ;;;###autoload |
1306 (defmacro define-ccl-program (name ccl-program &optional doc) | 1244 (defmacro define-ccl-program (name ccl-program &optional doc) |
1307 "Set NAME the compiled code of CCL-PROGRAM. | 1245 "Set NAME the compiled code of CCL-PROGRAM. |
1308 CCL-PROGRAM is `eval'ed before being handed to the CCL compiler `ccl-compile'. | 1246 |
1309 The compiled code is a vector of integers." | 1247 CCL-PROGRAM is has this form: |
1248 (BUFFER_MAGNIFICATION | |
1249 CCL_MAIN_CODE | |
1250 [ CCL_EOF_CODE ]) | |
1251 | |
1252 BUFFER_MAGNIFICATION is an integer value specifying the approximate | |
1253 output buffer magnification size compared with the bytes of input data | |
1254 text. If the value is zero, the CCL program can't execute `read' and | |
1255 `write' commands. | |
1256 | |
1257 CCL_MAIN_CODE and CCL_EOF_CODE are CCL program codes. CCL_MAIN_CODE | |
1258 executed at first. If there's no more input data when `read' command | |
1259 is executed in CCL_MAIN_CODE, CCL_EOF_CODE is executed. If | |
1260 CCL_MAIN_CODE is terminated, CCL_EOF_CODE is not executed. | |
1261 | |
1262 Here's the syntax of CCL program code in BNF notation. The lines | |
1263 starting by two semicolons (and optional leading spaces) describe the | |
1264 semantics. | |
1265 | |
1266 CCL_MAIN_CODE := CCL_BLOCK | |
1267 | |
1268 CCL_EOF_CODE := CCL_BLOCK | |
1269 | |
1270 CCL_BLOCK := STATEMENT | (STATEMENT [STATEMENT ...]) | |
1271 | |
1272 STATEMENT := | |
1273 SET | IF | BRANCH | LOOP | REPEAT | BREAK | READ | WRITE | CALL | |
1274 | TRANSLATE | END | |
1275 | |
1276 SET := (REG = EXPRESSION) | |
1277 | (REG ASSIGNMENT_OPERATOR EXPRESSION) | |
1278 ;; The following form is the same as (r0 = integer). | |
1279 | integer | |
1280 | |
1281 EXPRESSION := ARG | (EXPRESSION OPERATOR ARG) | |
1282 | |
1283 ;; Evaluate EXPRESSION. If the result is nonzeor, execute | |
1284 ;; CCL_BLOCK_0. Otherwise, execute CCL_BLOCK_1. | |
1285 IF := (if EXPRESSION CCL_BLOCK_0 CCL_BLOCK_1) | |
1286 | |
1287 ;; Evaluate EXPRESSION. Provided that the result is N, execute | |
1288 ;; CCL_BLOCK_N. | |
1289 BRANCH := (branch EXPRESSION CCL_BLOCK_0 [CCL_BLOCK_1 ...]) | |
1290 | |
1291 ;; Execute STATEMENTs until (break) or (end) is executed. | |
1292 LOOP := (loop STATEMENT [STATEMENT ...]) | |
1293 | |
1294 ;; Terminate the most inner loop. | |
1295 BREAK := (break) | |
1296 | |
1297 REPEAT := | |
1298 ;; Jump to the head of the most inner loop. | |
1299 (repeat) | |
1300 ;; Same as: ((write [REG | integer | string]) | |
1301 ;; (repeat)) | |
1302 | (write-repeat [REG | integer | string]) | |
1303 ;; Same as: ((write REG [ARRAY]) | |
1304 ;; (read REG) | |
1305 ;; (repeat)) | |
1306 | (write-read-repeat REG [ARRAY]) | |
1307 ;; Same as: ((write integer) | |
1308 ;; (read REG) | |
1309 ;; (repeat)) | |
1310 | (write-read-repeat REG integer) | |
1311 | |
1312 READ := ;; Set REG_0 to a byte read from the input text, set REG_1 | |
1313 ;; to the next byte read, and so on. | |
1314 (read REG_0 [REG_1 ...]) | |
1315 ;; Same as: ((read REG) | |
1316 ;; (if (REG OPERATOR ARG) CCL_BLOCK_0 CCL_BLOCK_1)) | |
1317 | (read-if (REG OPERATOR ARG) CCL_BLOCK_0 CCL_BLOCK_1) | |
1318 ;; Same as: ((read REG) | |
1319 ;; (branch REG CCL_BLOCK_0 [CCL_BLOCK_1 ...])) | |
1320 | (read-branch REG CCL_BLOCK_0 [CCL_BLOCK_1 ...]) | |
1321 ;; Read a character from the input text while parsing | |
1322 ;; multibyte representation, set REG_0 to the charset ID of | |
1323 ;; the character, set REG_1 to the code point of the | |
1324 ;; character. If the dimension of charset is two, set REG_1 | |
1325 ;; to ((CODE0 << 8) | CODE1), where CODE0 is the first code | |
1326 ;; point and CODE1 is the second code point. | |
1327 | (read-multibyte-character REG_0 REG_1) | |
1328 | |
1329 WRITE := | |
1330 ;; Write REG_0, REG_1, ... to the output buffer. If REG_N is | |
1331 ;; a multibyte character, write the corresponding multibyte | |
1332 ;; representation. | |
1333 (write REG_0 [REG_1 ...]) | |
1334 ;; Same as: ((r7 = EXPRESSION) | |
1335 ;; (write r7)) | |
1336 | (write EXPRESSION) | |
1337 ;; Write the value of `integer' to the output buffer. If it | |
1338 ;; is a multibyte character, write the corresponding multibyte | |
1339 ;; representation. | |
1340 | (write integer) | |
1341 ;; Write the byte sequence of `string' as is to the output | |
1342 ;; buffer. | |
1343 | (write string) | |
1344 ;; Same as: (write string) | |
1345 | string | |
1346 ;; Provided that the value of REG is N, write Nth element of | |
1347 ;; ARRAY to the output buffer. If it is a multibyte | |
1348 ;; character, write the corresponding multibyte | |
1349 ;; representation. | |
1350 | (write REG ARRAY) | |
1351 ;; Write a multibyte representation of a character whose | |
1352 ;; charset ID is REG_0 and code point is REG_1. If the | |
1353 ;; dimension of the charset is two, REG_1 should be ((CODE0 << | |
1354 ;; 8) | CODE1), where CODE0 is the first code point and CODE1 | |
1355 ;; is the second code point of the character. | |
1356 | (write-multibyte-character REG_0 REG_1) | |
1357 | |
1358 ;; Call CCL program whose name is ccl-program-name. | |
1359 CALL := (call ccl-program-name) | |
1360 | |
1361 ;; Terminate the CCL program. | |
1362 END := (end) | |
1363 | |
1364 ;; CCL registers that can contain any integer value. As r7 is also | |
1365 ;; used by CCL interpreter, its value is changed unexpectedly. | |
1366 REG := r0 | r1 | r2 | r3 | r4 | r5 | r6 | r7 | |
1367 | |
1368 ARG := REG | integer | |
1369 | |
1370 OPERATOR := | |
1371 ;; Normal arithmethic operators (same meaning as C code). | |
1372 + | - | * | / | % | |
1373 | |
1374 ;; Bitwize operators (same meaning as C code) | |
1375 | & | `|' | ^ | |
1376 | |
1377 ;; Shifting operators (same meaning as C code) | |
1378 | << | >> | |
1379 | |
1380 ;; (REG = ARG_0 <8 ARG_1) means: | |
1381 ;; (REG = ((ARG_0 << 8) | ARG_1)) | |
1382 | <8 | |
1383 | |
1384 ;; (REG = ARG_0 >8 ARG_1) means: | |
1385 ;; ((REG = (ARG_0 >> 8)) | |
1386 ;; (r7 = (ARG_0 & 255))) | |
1387 | >8 | |
1388 | |
1389 ;; (REG = ARG_0 // ARG_1) means: | |
1390 ;; ((REG = (ARG_0 / ARG_1)) | |
1391 ;; (r7 = (ARG_0 % ARG_1))) | |
1392 | // | |
1393 | |
1394 ;; Normal comparing operators (same meaning as C code) | |
1395 | < | > | == | <= | >= | != | |
1396 | |
1397 ;; If ARG_0 and ARG_1 are higher and lower byte of Shift-JIS | |
1398 ;; code, and CHAR is the corresponding JISX0208 character, | |
1399 ;; (REG = ARG_0 de-sjis ARG_1) means: | |
1400 ;; ((REG = CODE0) | |
1401 ;; (r7 = CODE1)) | |
1402 ;; where CODE0 is the first code point of CHAR, CODE1 is the | |
1403 ;; second code point of CHAR. | |
1404 | de-sjis | |
1405 | |
1406 ;; If ARG_0 and ARG_1 are the first and second code point of | |
1407 ;; JISX0208 character CHAR, and SJIS is the correponding | |
1408 ;; Shift-JIS code, | |
1409 ;; (REG = ARG_0 en-sjis ARG_1) means: | |
1410 ;; ((REG = HIGH) | |
1411 ;; (r7 = LOW)) | |
1412 ;; where HIGH is the higher byte of SJIS, LOW is the lower | |
1413 ;; byte of SJIS. | |
1414 | en-sjis | |
1415 | |
1416 ASSIGNMENT_OPERATOR := | |
1417 ;; Same meaning as C code | |
1418 += | -= | *= | /= | %= | &= | `|=' | ^= | <<= | >>= | |
1419 | |
1420 ;; (REG <8= ARG) is the same as: | |
1421 ;; ((REG <<= 8) | |
1422 ;; (REG |= ARG)) | |
1423 | <8= | |
1424 | |
1425 ;; (REG >8= ARG) is the same as: | |
1426 ;; ((r7 = (REG & 255)) | |
1427 ;; (REG >>= 8)) | |
1428 | |
1429 ;; (REG //= ARG) is the same as: | |
1430 ;; ((r7 = (REG % ARG)) | |
1431 ;; (REG /= ARG)) | |
1432 | //= | |
1433 | |
1434 ARRAY := `[' integer ... `]' | |
1435 | |
1436 | |
1437 TRANSLATE := | |
1438 (translate-character REG(table) REG(charset) REG(codepoint)) | |
1439 | (translate-character SYMBOL REG(charset) REG(codepoint)) | |
1440 MAP := | |
1441 (iterate-multiple-map REG REG MAP-IDs) | |
1442 | (map-multiple REG REG (MAP-SET)) | |
1443 | (map-single REG REG MAP-ID) | |
1444 MAP-IDs := MAP-ID ... | |
1445 MAP-SET := MAP-IDs | (MAP-IDs) MAP-SET | |
1446 MAP-ID := integer | |
1447 " | |
1310 `(let ((prog ,(ccl-compile (eval ccl-program)))) | 1448 `(let ((prog ,(ccl-compile (eval ccl-program)))) |
1311 (defconst ,name prog ,doc) | 1449 (defconst ,name prog ,doc) |
1312 (put ',name 'ccl-program-idx (register-ccl-program ',name prog)) | 1450 (put ',name 'ccl-program-idx (register-ccl-program ',name prog)) |
1313 nil)) | 1451 nil)) |
1314 | 1452 |
1327 ,ccl-program))) | 1465 ,ccl-program))) |
1328 | 1466 |
1329 ;;;###autoload | 1467 ;;;###autoload |
1330 (defun ccl-execute-with-args (ccl-prog &rest args) | 1468 (defun ccl-execute-with-args (ccl-prog &rest args) |
1331 "Execute CCL-PROGRAM with registers initialized by the remaining args. | 1469 "Execute CCL-PROGRAM with registers initialized by the remaining args. |
1332 The return value is a vector of resulting CCL registers." | 1470 The return value is a vector of resulting CCL registers. |
1471 | |
1472 See the documentation of `define-ccl-program' for the detail of CCL program." | |
1333 (let ((reg (make-vector 8 0)) | 1473 (let ((reg (make-vector 8 0)) |
1334 (i 0)) | 1474 (i 0)) |
1335 (while (and args (< i 8)) | 1475 (while (and args (< i 8)) |
1336 (if (not (integerp (car args))) | 1476 (if (not (integerp (car args))) |
1337 (error "Arguments should be integer")) | 1477 (error "Arguments should be integer")) |