ebnf-iso.el 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. ;;; ebnf-iso.el --- parser for ISO EBNF
  2. ;; Copyright (C) 1999-2012 Free Software Foundation, Inc.
  3. ;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
  4. ;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
  5. ;; Keywords: wp, ebnf, PostScript
  6. ;; Version: 1.9
  7. ;; Package: ebnf2ps
  8. ;; This file is part of GNU Emacs.
  9. ;; GNU Emacs is free software: you can redistribute it and/or modify
  10. ;; it under the terms of the GNU General Public License as published by
  11. ;; the Free Software Foundation, either version 3 of the License, or
  12. ;; (at your option) any later version.
  13. ;; GNU Emacs is distributed in the hope that it will be useful,
  14. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ;; GNU General Public License for more details.
  17. ;; You should have received a copy of the GNU General Public License
  18. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  19. ;;; Commentary:
  20. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  21. ;;
  22. ;;
  23. ;; This is part of ebnf2ps package.
  24. ;;
  25. ;; This package defines a parser for ISO EBNF.
  26. ;;
  27. ;; See ebnf2ps.el for documentation.
  28. ;;
  29. ;;
  30. ;; ISO EBNF Syntax
  31. ;; ---------------
  32. ;;
  33. ;; See the URL:
  34. ;; `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
  35. ;; ("International Standard of the ISO EBNF Notation").
  36. ;;
  37. ;;
  38. ;; ISO EBNF = syntax rule, {syntax rule};
  39. ;;
  40. ;; syntax rule = meta identifier, '=', definition list, ';';
  41. ;;
  42. ;; definition list = single definition, {'|', single definition};
  43. ;;
  44. ;; single definition = term, {',', term};
  45. ;;
  46. ;; term = factor, ['-', exception];
  47. ;;
  48. ;; exception = factor (* without <meta identifier> *);
  49. ;;
  50. ;; factor = [integer, '*'], primary;
  51. ;;
  52. ;; primary = optional sequence | repeated sequence | special sequence
  53. ;; | grouped sequence | meta identifier | terminal string
  54. ;; | empty;
  55. ;;
  56. ;; empty = ;
  57. ;;
  58. ;; optional sequence = '[', definition list, ']';
  59. ;;
  60. ;; repeated sequence = '{', definition list, '}';
  61. ;;
  62. ;; grouped sequence = '(', definition list, ')';
  63. ;;
  64. ;; terminal string = "'", character - "'", {character - "'"}, "'"
  65. ;; | '"', character - '"', {character - '"'}, '"';
  66. ;;
  67. ;; special sequence = '?', {character - '?'}, '?';
  68. ;;
  69. ;; meta identifier = letter, { letter | decimal digit | ' ' };
  70. ;;
  71. ;; integer = decimal digit, {decimal digit};
  72. ;;
  73. ;; comment = '(*', {comment symbol}, '*)';
  74. ;;
  75. ;; comment symbol = comment (* <== NESTED COMMENT *)
  76. ;; | terminal string | special sequence | character;
  77. ;;
  78. ;; letter = ? A-Z a-z ?;
  79. ;;
  80. ;; decimal digit = ? 0-9 ?;
  81. ;;
  82. ;; character = letter | decimal digit
  83. ;; | ',' | '=' | '|' | '/' | '!' | '*' | '(' | ')' | '[' | ']' | '{'
  84. ;; | '}' | "'" | '"' | '?' | '-' | ';' | '.' | ' ' | ':' | '+' | '_'
  85. ;; | '%' | '@' | '&' | '#' | '$' | '<' | '>' | '\' | '^' | '`' | '~';
  86. ;;
  87. ;;
  88. ;; There is also the following alternative representation:
  89. ;;
  90. ;; STANDARD ALTERNATIVE
  91. ;; | ==> / or !
  92. ;; [ ==> (/
  93. ;; ] ==> /)
  94. ;; { ==> (:
  95. ;; } ==> :)
  96. ;; ; ==> .
  97. ;;
  98. ;;
  99. ;; Differences Between ISO EBNF And ebnf2ps ISO EBNF
  100. ;; -------------------------------------------------
  101. ;;
  102. ;; ISO EBNF accepts the characters given by <character> production above,
  103. ;; HORIZONTAL TAB (^I), VERTICAL TAB (^K), NEWLINE (^J or ^M) and FORM FEED
  104. ;; (^L), any other characters are invalid. But ebnf2ps accepts also the
  105. ;; european 8-bit accentuated characters (from \240 to \377) and underscore
  106. ;; (_).
  107. ;;
  108. ;;
  109. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  110. ;;; Code:
  111. (require 'ebnf-otz)
  112. (defvar ebnf-iso-lex nil
  113. "Value returned by `ebnf-iso-lex' function.")
  114. (defvar ebnf-no-meta-identifier nil
  115. "Used by `ebnf-iso-term' and `ebnf-iso-lex' functions.")
  116. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  117. ;; Syntactic analyzer
  118. ;;; ISO EBNF = syntax rule, {syntax rule};
  119. (defun ebnf-iso-parser (start)
  120. "ISO EBNF parser."
  121. (let ((total (+ (- ebnf-limit start) 1))
  122. (bias (1- start))
  123. (origin (point))
  124. syntax-list token rule)
  125. (goto-char start)
  126. (setq token (ebnf-iso-lex))
  127. (and (eq token 'end-of-input)
  128. (error "Invalid ISO EBNF file format"))
  129. (while (not (eq token 'end-of-input))
  130. (ebnf-message-float
  131. "Parsing...%s%%"
  132. (/ (* (- (point) bias) 100.0) total))
  133. (setq token (ebnf-iso-syntax-rule token)
  134. rule (cdr token)
  135. token (car token))
  136. (or (ebnf-add-empty-rule-list rule)
  137. (setq syntax-list (cons rule syntax-list))))
  138. (goto-char origin)
  139. syntax-list))
  140. ;;; syntax rule = meta identifier, '=', definition list, ';';
  141. (defun ebnf-iso-syntax-rule (token)
  142. (let ((header ebnf-iso-lex)
  143. (action ebnf-action)
  144. body)
  145. (setq ebnf-action nil)
  146. (or (eq token 'non-terminal)
  147. (error "Invalid meta identifier syntax rule"))
  148. (or (eq (ebnf-iso-lex) 'equal)
  149. (error "Invalid syntax rule: missing `='"))
  150. (setq body (ebnf-iso-definition-list))
  151. (or (eq (car body) 'period)
  152. (error "Invalid syntax rule: missing `;' or `.'"))
  153. (setq body (cdr body))
  154. (ebnf-eps-add-production header)
  155. (cons (ebnf-iso-lex)
  156. (ebnf-make-production header body action))))
  157. ;;; definition list = single definition, {'|', single definition};
  158. (defun ebnf-iso-definition-list ()
  159. (let (body sequence)
  160. (while (eq (car (setq sequence (ebnf-iso-single-definition)))
  161. 'alternative)
  162. (setq sequence (cdr sequence)
  163. body (cons sequence body)))
  164. (ebnf-token-alternative body sequence)))
  165. ;;; single definition = term, {',', term};
  166. (defun ebnf-iso-single-definition ()
  167. (let (token seq term)
  168. (while (and (setq term (ebnf-iso-term (ebnf-iso-lex))
  169. token (car term)
  170. term (cdr term))
  171. (eq token 'catenate))
  172. (setq seq (cons term seq)))
  173. (cons token
  174. (ebnf-token-sequence (if term
  175. (cons term seq)
  176. seq)))))
  177. ;;; term = factor, ['-', exception];
  178. ;;;
  179. ;;; exception = factor (* without <meta identifier> *);
  180. (defun ebnf-iso-term (token)
  181. (let ((factor (ebnf-iso-factor token)))
  182. (if (not (eq (car factor) 'except))
  183. ;; factor
  184. factor
  185. ;; factor - exception
  186. (let ((ebnf-no-meta-identifier t))
  187. (ebnf-token-except (cdr factor) (ebnf-iso-factor (ebnf-iso-lex)))))))
  188. ;;; factor = [integer, '*'], primary;
  189. (defun ebnf-iso-factor (token)
  190. (if (eq token 'integer)
  191. (let ((times ebnf-iso-lex))
  192. (or (eq (ebnf-iso-lex) 'repeat)
  193. (error "Missing `*'"))
  194. (ebnf-token-repeat times (ebnf-iso-primary (ebnf-iso-lex))))
  195. (ebnf-iso-primary token)))
  196. ;;; primary = optional sequence | repeated sequence | special sequence
  197. ;;; | grouped sequence | meta identifier | terminal string
  198. ;;; | empty;
  199. ;;;
  200. ;;; empty = ;
  201. ;;;
  202. ;;; optional sequence = '[', definition list, ']';
  203. ;;;
  204. ;;; repeated sequence = '{', definition list, '}';
  205. ;;;
  206. ;;; grouped sequence = '(', definition list, ')';
  207. ;;;
  208. ;;; terminal string = "'", character - "'", {character - "'"}, "'"
  209. ;;; | '"', character - '"', {character - '"'}, '"';
  210. ;;;
  211. ;;; special sequence = '?', {character - '?'}, '?';
  212. ;;;
  213. ;;; meta identifier = letter, {letter | decimal digit};
  214. (defun ebnf-iso-primary (token)
  215. (let ((primary
  216. (cond
  217. ;; terminal string
  218. ((eq token 'terminal)
  219. (ebnf-make-terminal ebnf-iso-lex))
  220. ;; meta identifier
  221. ((eq token 'non-terminal)
  222. (ebnf-make-non-terminal ebnf-iso-lex))
  223. ;; special sequence
  224. ((eq token 'special)
  225. (ebnf-make-special ebnf-iso-lex))
  226. ;; grouped sequence
  227. ((eq token 'begin-group)
  228. (let ((body (ebnf-iso-definition-list)))
  229. (or (eq (car body) 'end-group)
  230. (error "Missing `)'"))
  231. (cdr body)))
  232. ;; optional sequence
  233. ((eq token 'begin-optional)
  234. (let ((body (ebnf-iso-definition-list)))
  235. (or (eq (car body) 'end-optional)
  236. (error "Missing `]' or `/)'"))
  237. (ebnf-token-optional (cdr body))))
  238. ;; repeated sequence
  239. ((eq token 'begin-zero-or-more)
  240. (let* ((body (ebnf-iso-definition-list))
  241. (repeat (cdr body)))
  242. (or (eq (car body) 'end-zero-or-more)
  243. (error "Missing `}' or `:)'"))
  244. (ebnf-make-zero-or-more repeat)))
  245. ;; empty
  246. (t
  247. nil)
  248. )))
  249. (cons (if primary
  250. (ebnf-iso-lex)
  251. token)
  252. primary)))
  253. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  254. ;; Lexical analyzer
  255. (defconst ebnf-iso-token-table
  256. ;; control character & 8-bit character are set to `error'
  257. (let ((table (make-vector 256 'error))
  258. (char ?\040))
  259. ;; printable character
  260. (while (< char ?\060)
  261. (aset table char 'character)
  262. (setq char (1+ char)))
  263. ;; digits:
  264. (while (< char ?\072)
  265. (aset table char 'integer)
  266. (setq char (1+ char)))
  267. (while (< char ?\101)
  268. (aset table char 'character)
  269. (setq char (1+ char)))
  270. ;; upper case letters:
  271. (while (< char ?\133)
  272. (aset table char 'non-terminal)
  273. (setq char (1+ char)))
  274. (while (< char ?\141)
  275. (aset table char 'character)
  276. (setq char (1+ char)))
  277. ;; lower case letters:
  278. (while (< char ?\173)
  279. (aset table char 'non-terminal)
  280. (setq char (1+ char)))
  281. (while (< char ?\177)
  282. (aset table char 'character)
  283. (setq char (1+ char)))
  284. ;; European 8-bit accentuated characters:
  285. (setq char ?\240)
  286. (while (< char ?\400)
  287. (aset table char 'non-terminal)
  288. (setq char (1+ char)))
  289. ;; Override space characters:
  290. (aset table ?\013 'space) ; [VT] vertical tab
  291. (aset table ?\n 'space) ; [NL] linefeed
  292. (aset table ?\r 'space) ; [CR] carriage return
  293. (aset table ?\t 'space) ; [HT] horizontal tab
  294. (aset table ?\ 'space) ; [SP] space
  295. ;; Override form feed character:
  296. (aset table ?\f 'form-feed) ; [FF] form feed
  297. ;; Override other lexical characters:
  298. (aset table ?_ 'non-terminal)
  299. (aset table ?\" 'double-terminal)
  300. (aset table ?\' 'single-terminal)
  301. (aset table ?\? 'special)
  302. (aset table ?* 'repeat)
  303. (aset table ?, 'catenate)
  304. (aset table ?- 'except)
  305. (aset table ?= 'equal)
  306. (aset table ?\) 'end-group)
  307. table)
  308. "Vector used to map characters to a lexical token.")
  309. (defun ebnf-iso-initialize ()
  310. "Initialize ISO EBNF token table."
  311. (if ebnf-iso-alternative-p
  312. ;; Override alternative lexical characters:
  313. (progn
  314. (aset ebnf-iso-token-table ?\( 'left-parenthesis)
  315. (aset ebnf-iso-token-table ?\[ 'character)
  316. (aset ebnf-iso-token-table ?\] 'character)
  317. (aset ebnf-iso-token-table ?\{ 'character)
  318. (aset ebnf-iso-token-table ?\} 'character)
  319. (aset ebnf-iso-token-table ?| 'character)
  320. (aset ebnf-iso-token-table ?\; 'character)
  321. (aset ebnf-iso-token-table ?/ 'slash)
  322. (aset ebnf-iso-token-table ?! 'alternative)
  323. (aset ebnf-iso-token-table ?: 'colon)
  324. (aset ebnf-iso-token-table ?. 'period))
  325. ;; Override standard lexical characters:
  326. (aset ebnf-iso-token-table ?\( 'begin-parenthesis)
  327. (aset ebnf-iso-token-table ?\[ 'begin-optional)
  328. (aset ebnf-iso-token-table ?\] 'end-optional)
  329. (aset ebnf-iso-token-table ?\{ 'begin-zero-or-more)
  330. (aset ebnf-iso-token-table ?\} 'end-zero-or-more)
  331. (aset ebnf-iso-token-table ?| 'alternative)
  332. (aset ebnf-iso-token-table ?\; 'period)
  333. (aset ebnf-iso-token-table ?/ 'character)
  334. (aset ebnf-iso-token-table ?! 'character)
  335. (aset ebnf-iso-token-table ?: 'character)
  336. (aset ebnf-iso-token-table ?. 'character)))
  337. ;; replace the range "\240-\377" (see `ebnf-range-regexp').
  338. (defconst ebnf-iso-non-terminal-chars
  339. (ebnf-range-regexp " 0-9A-Za-z_" ?\240 ?\377))
  340. (defun ebnf-iso-lex ()
  341. "Lexical analyzer for ISO EBNF.
  342. Return a lexical token.
  343. See documentation for variable `ebnf-iso-lex'."
  344. (if (>= (point) ebnf-limit)
  345. 'end-of-input
  346. (let (token)
  347. ;; skip spaces and comments
  348. (while (if (> (following-char) 255)
  349. (progn
  350. (setq token 'error)
  351. nil)
  352. (setq token (aref ebnf-iso-token-table (following-char)))
  353. (cond
  354. ((eq token 'space)
  355. (skip-chars-forward " \013\n\r\t" ebnf-limit)
  356. (< (point) ebnf-limit))
  357. ((or (eq token 'begin-parenthesis)
  358. (eq token 'left-parenthesis))
  359. (forward-char)
  360. (if (/= (following-char) ?*)
  361. ;; no comment
  362. nil
  363. ;; comment
  364. (ebnf-iso-skip-comment)
  365. t))
  366. ((eq token 'form-feed)
  367. (forward-char)
  368. (setq ebnf-action 'form-feed))
  369. (t nil)
  370. )))
  371. (cond
  372. ;; end of input
  373. ((>= (point) ebnf-limit)
  374. 'end-of-input)
  375. ;; error
  376. ((eq token 'error)
  377. (error "Invalid character"))
  378. ;; integer
  379. ((eq token 'integer)
  380. (setq ebnf-iso-lex (ebnf-buffer-substring "0-9"))
  381. 'integer)
  382. ;; special: ?special?
  383. ((eq token 'special)
  384. (setq ebnf-iso-lex (concat (and ebnf-special-show-delimiter "?")
  385. (ebnf-string " ->@-~" ?\? "special")
  386. (and ebnf-special-show-delimiter "?")))
  387. 'special)
  388. ;; terminal: "string"
  389. ((eq token 'double-terminal)
  390. (setq ebnf-iso-lex (ebnf-string " !#-~" ?\" "terminal"))
  391. 'terminal)
  392. ;; terminal: 'string'
  393. ((eq token 'single-terminal)
  394. (setq ebnf-iso-lex (ebnf-string " -&(-~" ?\' "terminal"))
  395. 'terminal)
  396. ;; non-terminal
  397. ((eq token 'non-terminal)
  398. (setq ebnf-iso-lex
  399. (ebnf-iso-normalize
  400. (ebnf-trim-right
  401. (ebnf-buffer-substring ebnf-iso-non-terminal-chars))))
  402. (and ebnf-no-meta-identifier
  403. (error "Exception sequence should not contain a meta identifier"))
  404. 'non-terminal)
  405. ;; begin optional, begin list or begin group
  406. ((eq token 'left-parenthesis)
  407. (forward-char)
  408. (cond ((= (following-char) ?/)
  409. (forward-char)
  410. 'begin-optional)
  411. ((= (following-char) ?:)
  412. (forward-char)
  413. 'begin-zero-or-more)
  414. (t
  415. 'begin-group)
  416. ))
  417. ;; end optional or alternative
  418. ((eq token 'slash)
  419. (forward-char)
  420. (if (/= (following-char) ?\))
  421. 'alternative
  422. (forward-char)
  423. 'end-optional))
  424. ;; end list
  425. ((eq token 'colon)
  426. (forward-char)
  427. (if (/= (following-char) ?\))
  428. 'character
  429. (forward-char)
  430. 'end-zero-or-more))
  431. ;; begin group
  432. ((eq token 'begin-parenthesis)
  433. 'begin-group)
  434. ;; miscellaneous
  435. (t
  436. (forward-char)
  437. token)
  438. ))))
  439. ;; replace the range "\177-\237" (see `ebnf-range-regexp').
  440. (defconst ebnf-iso-comment-chars
  441. (ebnf-range-regexp "^*(\000-\010\016-\037" ?\177 ?\237))
  442. (defun ebnf-iso-skip-comment ()
  443. (forward-char)
  444. (cond
  445. ;; open EPS file
  446. ((and ebnf-eps-executing (= (following-char) ?\[))
  447. (ebnf-eps-add-context (ebnf-iso-eps-filename)))
  448. ;; close EPS file
  449. ((and ebnf-eps-executing (= (following-char) ?\]))
  450. (ebnf-eps-remove-context (ebnf-iso-eps-filename)))
  451. ;; EPS header
  452. ((and ebnf-eps-executing (= (following-char) ?H))
  453. (ebnf-eps-header-comment (ebnf-iso-eps-filename)))
  454. ;; EPS footer
  455. ((and ebnf-eps-executing (= (following-char) ?F))
  456. (ebnf-eps-footer-comment (ebnf-iso-eps-filename)))
  457. ;; any other action in comment
  458. (t
  459. (setq ebnf-action (aref ebnf-comment-table (following-char))))
  460. )
  461. (let ((pair 1))
  462. (while (> pair 0)
  463. (skip-chars-forward ebnf-iso-comment-chars ebnf-limit)
  464. (cond ((>= (point) ebnf-limit)
  465. (error "Missing end of comment: `*)'"))
  466. ((= (following-char) ?*)
  467. (skip-chars-forward "*" ebnf-limit)
  468. (when (= (following-char) ?\))
  469. ;; end of comment
  470. (forward-char)
  471. (setq pair (1- pair))))
  472. ((= (following-char) ?\()
  473. (skip-chars-forward "(" ebnf-limit)
  474. (when (= (following-char) ?*)
  475. ;; beginning of comment
  476. (forward-char)
  477. (setq pair (1+ pair))))
  478. (t
  479. (error "Invalid character"))
  480. ))))
  481. (defun ebnf-iso-eps-filename ()
  482. (forward-char)
  483. (buffer-substring-no-properties
  484. (point)
  485. (let ((chars (concat ebnf-iso-comment-chars "\n"))
  486. found)
  487. (while (not found)
  488. (skip-chars-forward chars ebnf-limit)
  489. (setq found
  490. (cond ((>= (point) ebnf-limit)
  491. (point))
  492. ((= (following-char) ?*)
  493. (skip-chars-forward "*" ebnf-limit)
  494. (if (/= (following-char) ?\))
  495. nil
  496. (backward-char)
  497. (point)))
  498. ((= (following-char) ?\()
  499. (forward-char)
  500. (if (/= (following-char) ?*)
  501. nil
  502. (backward-char)
  503. (point)))
  504. (t
  505. (point))
  506. )))
  507. found)))
  508. (defun ebnf-iso-normalize (str)
  509. (if (not ebnf-iso-normalize-p)
  510. str
  511. (let ((len (length str))
  512. (stri 0)
  513. (spaces 0))
  514. ;; count exceeding spaces
  515. (while (< stri len)
  516. (if (/= (aref str stri) ?\ )
  517. (setq stri (1+ stri))
  518. (setq stri (1+ stri))
  519. (while (and (< stri len) (= (aref str stri) ?\ ))
  520. (setq stri (1+ stri)
  521. spaces (1+ spaces)))))
  522. (if (zerop spaces)
  523. ;; no exceeding space
  524. str
  525. ;; at least one exceeding space
  526. (let ((new (make-string (- len spaces) ?\ ))
  527. (newi 0))
  528. ;; eliminate exceeding spaces
  529. (setq stri 0)
  530. (while (> spaces 0)
  531. (if (/= (aref str stri) ?\ )
  532. (progn
  533. (aset new newi (aref str stri))
  534. (setq stri (1+ stri)
  535. newi (1+ newi)))
  536. (aset new newi (aref str stri))
  537. (setq stri (1+ stri)
  538. newi (1+ newi))
  539. (while (and (> spaces 0) (= (aref str stri) ?\ ))
  540. (setq stri (1+ stri)
  541. spaces (1- spaces)))))
  542. ;; remaining is normalized
  543. (while (< stri len)
  544. (aset new newi (aref str stri))
  545. (setq stri (1+ stri)
  546. newi (1+ newi)))
  547. new)))))
  548. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  549. (provide 'ebnf-iso)
  550. ;;; ebnf-iso.el ends here