ebnf-abn.el 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. ;;; ebnf-abn.el --- parser for ABNF (Augmented BNF)
  2. ;; Copyright (C) 2001-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.2
  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 ABNF (Augmented BNF).
  26. ;;
  27. ;; See ebnf2ps.el for documentation.
  28. ;;
  29. ;;
  30. ;; ABNF Syntax
  31. ;; -----------
  32. ;;
  33. ;; See the URL:
  34. ;; `http://www.ietf.org/rfc/rfc2234.txt'
  35. ;; or
  36. ;; `http://www.faqs.org/rfcs/rfc2234.html'
  37. ;; or
  38. ;; `http://www.rnp.br/ietf/rfc/rfc2234.txt'
  39. ;; ("Augmented BNF for Syntax Specifications: ABNF").
  40. ;;
  41. ;;
  42. ;; rulelist = 1*( rule / (*c-wsp c-nl) )
  43. ;;
  44. ;; rule = rulename defined-as elements c-nl
  45. ;; ; continues if next line starts with white space
  46. ;;
  47. ;; rulename = ALPHA *(ALPHA / DIGIT / "-")
  48. ;;
  49. ;; defined-as = *c-wsp ("=" / "=/") *c-wsp
  50. ;; ; basic rules definition and incremental
  51. ;; ; alternatives
  52. ;;
  53. ;; elements = alternation *c-wsp
  54. ;;
  55. ;; c-wsp = WSP / (c-nl WSP)
  56. ;;
  57. ;; c-nl = comment / CRLF
  58. ;; ; comment or newline
  59. ;;
  60. ;; comment = ";" *(WSP / VCHAR) CRLF
  61. ;;
  62. ;; alternation = concatenation
  63. ;; *(*c-wsp "/" *c-wsp concatenation)
  64. ;;
  65. ;; concatenation = repetition *(1*c-wsp repetition)
  66. ;;
  67. ;; repetition = [repeat] element
  68. ;;
  69. ;; repeat = 1*DIGIT / (*DIGIT "*" *DIGIT)
  70. ;;
  71. ;; element = rulename / group / option /
  72. ;; char-val / num-val / prose-val
  73. ;;
  74. ;; group = "(" *c-wsp alternation *c-wsp ")"
  75. ;;
  76. ;; option = "[" *c-wsp alternation *c-wsp "]"
  77. ;;
  78. ;; char-val = DQUOTE *(%x20-21 / %x23-7E) DQUOTE
  79. ;; ; quoted string of SP and VCHAR without DQUOTE
  80. ;;
  81. ;; num-val = "%" (bin-val / dec-val / hex-val)
  82. ;;
  83. ;; bin-val = "b" 1*BIT
  84. ;; [ 1*("." 1*BIT) / ("-" 1*BIT) ]
  85. ;; ; series of concatenated bit values
  86. ;; ; or single ONEOF range
  87. ;;
  88. ;; dec-val = "d" 1*DIGIT
  89. ;; [ 1*("." 1*DIGIT) / ("-" 1*DIGIT) ]
  90. ;;
  91. ;; hex-val = "x" 1*HEXDIG
  92. ;; [ 1*("." 1*HEXDIG) / ("-" 1*HEXDIG) ]
  93. ;;
  94. ;; prose-val = "<" *(%x20-3D / %x3F-7E) ">"
  95. ;; ; bracketed string of SP and VCHAR without
  96. ;; ; angles
  97. ;; ; prose description, to be used as last resort
  98. ;;
  99. ;; ; Core rules -- the coding depends on the system, here is used 7-bit ASCII
  100. ;;
  101. ;; ALPHA = %x41-5A / %x61-7A
  102. ;; ; A-Z / a-z
  103. ;;
  104. ;; BIT = "0" / "1"
  105. ;;
  106. ;; CHAR = %x01-7F
  107. ;; ; any 7-bit US-ASCII character, excluding NUL
  108. ;;
  109. ;; CR = %x0D
  110. ;; ; carriage return
  111. ;;
  112. ;; CRLF = CR LF
  113. ;; ; Internet standard newline
  114. ;;
  115. ;; CTL = %x00-1F / %x7F
  116. ;; ; controls
  117. ;;
  118. ;; DIGIT = %x30-39
  119. ;; ; 0-9
  120. ;;
  121. ;; DQUOTE = %x22
  122. ;; ; " (Double Quote)
  123. ;;
  124. ;; HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
  125. ;;
  126. ;; HTAB = %x09
  127. ;; ; horizontal tab
  128. ;;
  129. ;; LF = %x0A
  130. ;; ; linefeed
  131. ;;
  132. ;; LWSP = *(WSP / CRLF WSP)
  133. ;; ; linear white space (past newline)
  134. ;;
  135. ;; OCTET = %x00-FF
  136. ;; ; 8 bits of data
  137. ;;
  138. ;; SP = %x20
  139. ;; ; space
  140. ;;
  141. ;; VCHAR = %x21-7E
  142. ;; ; visible (printing) characters
  143. ;;
  144. ;; WSP = SP / HTAB
  145. ;; ; white space
  146. ;;
  147. ;;
  148. ;; NOTES:
  149. ;;
  150. ;; 1. Rules name and terminal strings are case INSENSITIVE.
  151. ;; So, the following rule names are all equals:
  152. ;; Rule-name, rule-Name, rule-name, RULE-NAME
  153. ;; Also, the following strings are equals:
  154. ;; "abc", "ABC", "aBc", "Abc", "aBC", etc.
  155. ;;
  156. ;; 2. To have a case SENSITIVE string, use the character notation.
  157. ;; For example, to specify the lowercase string "abc", use:
  158. ;; %d97.98.99
  159. ;;
  160. ;; 3. There are no implicit spaces between elements, for example, the
  161. ;; following rules:
  162. ;;
  163. ;; foo = %x61 ; a
  164. ;;
  165. ;; bar = %x62 ; b
  166. ;;
  167. ;; mumble = foo bar foo
  168. ;;
  169. ;; Are equivalent to the following rule:
  170. ;;
  171. ;; mumble = %x61.62.61
  172. ;;
  173. ;; If spaces are needed, it should be explicit specified, like:
  174. ;;
  175. ;; spaces = 1*(%x20 / %x09) ; one or more spaces or tabs
  176. ;;
  177. ;; mumble = foo spaces bar spaces foo
  178. ;;
  179. ;; 4. Lines starting with space or tab are considered a continuation line.
  180. ;; For example, the rule:
  181. ;;
  182. ;; rule = foo
  183. ;; bar
  184. ;;
  185. ;; Is equivalent to:
  186. ;;
  187. ;; rule = foo bar
  188. ;;
  189. ;;
  190. ;; Differences Between ABNF And ebnf2ps ABNF
  191. ;; -----------------------------------------
  192. ;;
  193. ;; Besides the characters that ABNF accepts, ebnf2ps ABNF accepts also the
  194. ;; underscore (_) for rule name and european 8-bit accentuated characters (from
  195. ;; \240 to \377) for rule name, string and comment.
  196. ;;
  197. ;;
  198. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  199. ;;; Code:
  200. (require 'ebnf-otz)
  201. (defvar ebnf-abn-lex nil
  202. "Value returned by `ebnf-abn-lex' function.")
  203. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  204. ;; Syntactic analyzer
  205. ;;; rulelist = 1*( rule / (*c-wsp c-nl) )
  206. (defun ebnf-abn-parser (start)
  207. "ABNF parser."
  208. (let ((total (+ (- ebnf-limit start) 1))
  209. (bias (1- start))
  210. (origin (point))
  211. rule-list token rule)
  212. (goto-char start)
  213. (setq token (ebnf-abn-lex))
  214. (and (eq token 'end-of-input)
  215. (error "Invalid ABNF file format"))
  216. (and (eq token 'end-of-rule)
  217. (setq token (ebnf-abn-lex)))
  218. (while (not (eq token 'end-of-input))
  219. (ebnf-message-float
  220. "Parsing...%s%%"
  221. (/ (* (- (point) bias) 100.0) total))
  222. (setq token (ebnf-abn-rule token)
  223. rule (cdr token)
  224. token (car token))
  225. (or (ebnf-add-empty-rule-list rule)
  226. (setq rule-list (cons rule rule-list))))
  227. (goto-char origin)
  228. rule-list))
  229. ;;; rule = rulename defined-as elements c-nl
  230. ;;; ; continues if next line starts with white space
  231. ;;;
  232. ;;; rulename = ALPHA *(ALPHA / DIGIT / "-")
  233. ;;;
  234. ;;; defined-as = *c-wsp ("=" / "=/") *c-wsp
  235. ;;; ; basic rules definition and incremental
  236. ;;; ; alternatives
  237. ;;;
  238. ;;; elements = alternation *c-wsp
  239. ;;;
  240. ;;; c-wsp = WSP / (c-nl WSP)
  241. ;;;
  242. ;;; c-nl = comment / CRLF
  243. ;;; ; comment or newline
  244. ;;;
  245. ;;; comment = ";" *(WSP / VCHAR) CRLF
  246. (defun ebnf-abn-rule (token)
  247. (let ((name ebnf-abn-lex)
  248. (action ebnf-action)
  249. elements)
  250. (setq ebnf-action nil)
  251. (or (eq token 'non-terminal)
  252. (error "Invalid rule name"))
  253. (setq token (ebnf-abn-lex))
  254. (or (memq token '(equal incremental-alternative))
  255. (error "Invalid rule: missing `=' or `=/'"))
  256. (and (eq token 'incremental-alternative)
  257. (setq name (concat name " =/")))
  258. (setq elements (ebnf-abn-alternation))
  259. (or (memq (car elements) '(end-of-rule end-of-input))
  260. (error "Invalid rule: there is no end of rule"))
  261. (setq elements (cdr elements))
  262. (ebnf-eps-add-production name)
  263. (cons (ebnf-abn-lex)
  264. (ebnf-make-production name elements action))))
  265. ;;; alternation = concatenation
  266. ;;; *(*c-wsp "/" *c-wsp concatenation)
  267. (defun ebnf-abn-alternation ()
  268. (let (body concatenation)
  269. (while (eq (car (setq concatenation
  270. (ebnf-abn-concatenation (ebnf-abn-lex))))
  271. 'alternative)
  272. (setq body (cons (cdr concatenation) body)))
  273. (ebnf-token-alternative body concatenation)))
  274. ;;; concatenation = repetition *(1*c-wsp repetition)
  275. (defun ebnf-abn-concatenation (token)
  276. (let ((term (ebnf-abn-repetition token))
  277. seq)
  278. (or (setq token (car term)
  279. term (cdr term))
  280. (error "Empty element"))
  281. (setq seq (cons term seq))
  282. (while (setq term (ebnf-abn-repetition token)
  283. token (car term)
  284. term (cdr term))
  285. (setq seq (cons term seq)))
  286. (cons token
  287. (ebnf-token-sequence seq))))
  288. ;;; repetition = [repeat] element
  289. ;;;
  290. ;;; repeat = 1*DIGIT / (*DIGIT "*" *DIGIT)
  291. (defun ebnf-abn-repetition (token)
  292. (let (lower upper)
  293. ;; INTEGER [ "*" [ INTEGER ] ]
  294. (when (eq token 'integer)
  295. (setq lower ebnf-abn-lex
  296. token (ebnf-abn-lex))
  297. (or (eq token 'repeat)
  298. (setq upper lower)))
  299. ;; "*" [ INTEGER ]
  300. (when (eq token 'repeat)
  301. ;; only * ==> lower & upper are empty string
  302. (or lower
  303. (setq lower ""
  304. upper ""))
  305. (when (eq (setq token (ebnf-abn-lex)) 'integer)
  306. (setq upper ebnf-abn-lex
  307. token (ebnf-abn-lex))))
  308. (let ((element (ebnf-abn-element token)))
  309. (cond
  310. ;; there is a repetition
  311. (lower
  312. (or element
  313. (error "Missing element repetition"))
  314. (setq token (ebnf-abn-lex))
  315. (cond
  316. ;; one or more
  317. ((and (string= lower "1") (null upper))
  318. (cons token (ebnf-make-one-or-more element)))
  319. ;; zero or more
  320. ((or (and (string= lower "0") (null upper))
  321. (and (string= lower "") (string= upper "")))
  322. (cons token (ebnf-make-zero-or-more element)))
  323. ;; real repetition
  324. (t
  325. (ebnf-token-repeat lower (cons token element) upper))))
  326. ;; there is an element
  327. (element
  328. (cons (ebnf-abn-lex) element))
  329. ;; something that caller has to deal
  330. (t
  331. (cons token nil))))))
  332. ;;; element = rulename / group / option /
  333. ;;; char-val / num-val / prose-val
  334. ;;;
  335. ;;; group = "(" *c-wsp alternation *c-wsp ")"
  336. ;;;
  337. ;;; option = "[" *c-wsp alternation *c-wsp "]"
  338. ;;;
  339. ;;; char-val = DQUOTE *(%x20-21 / %x23-7E) DQUOTE
  340. ;;; ; quoted string of SP and VCHAR without DQUOTE
  341. ;;;
  342. ;;; num-val = "%" (bin-val / dec-val / hex-val)
  343. ;;;
  344. ;;; bin-val = "b" 1*BIT
  345. ;;; [ 1*("." 1*BIT) / ("-" 1*BIT) ]
  346. ;;; ; series of concatenated bit values
  347. ;;; ; or single ONEOF range
  348. ;;;
  349. ;;; dec-val = "d" 1*DIGIT
  350. ;;; [ 1*("." 1*DIGIT) / ("-" 1*DIGIT) ]
  351. ;;;
  352. ;;; hex-val = "x" 1*HEXDIG
  353. ;;; [ 1*("." 1*HEXDIG) / ("-" 1*HEXDIG) ]
  354. ;;;
  355. ;;; prose-val = "<" *(%x20-3D / %x3F-7E) ">"
  356. ;;; ; bracketed string of SP and VCHAR without
  357. ;;; ; angles
  358. ;;; ; prose description, to be used as last resort
  359. (defun ebnf-abn-element (token)
  360. (cond
  361. ;; terminal
  362. ((eq token 'terminal)
  363. (ebnf-make-terminal ebnf-abn-lex))
  364. ;; non-terminal
  365. ((eq token 'non-terminal)
  366. (ebnf-make-non-terminal ebnf-abn-lex))
  367. ;; group
  368. ((eq token 'begin-group)
  369. (let ((body (ebnf-abn-alternation)))
  370. (or (eq (car body) 'end-group)
  371. (error "Missing `)'"))
  372. (cdr body)))
  373. ;; optional
  374. ((eq token 'begin-optional)
  375. (let ((body (ebnf-abn-alternation)))
  376. (or (eq (car body) 'end-optional)
  377. (error "Missing `]'"))
  378. (ebnf-token-optional (cdr body))))
  379. ;; no element
  380. (t
  381. nil)
  382. ))
  383. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  384. ;; Lexical analyzer
  385. (defconst ebnf-abn-token-table (make-vector 256 'error)
  386. "Vector used to map characters to a lexical token.")
  387. (defun ebnf-abn-initialize ()
  388. "Initialize EBNF token table."
  389. ;; control character & control 8-bit character are set to `error'
  390. (let ((char ?\060))
  391. ;; digits: 0-9
  392. (while (< char ?\072)
  393. (aset ebnf-abn-token-table char 'integer)
  394. (setq char (1+ char)))
  395. ;; printable character: A-Z
  396. (setq char ?\101)
  397. (while (< char ?\133)
  398. (aset ebnf-abn-token-table char 'non-terminal)
  399. (setq char (1+ char)))
  400. ;; printable character: a-z
  401. (setq char ?\141)
  402. (while (< char ?\173)
  403. (aset ebnf-abn-token-table char 'non-terminal)
  404. (setq char (1+ char)))
  405. ;; European 8-bit accentuated characters:
  406. (setq char ?\240)
  407. (while (< char ?\400)
  408. (aset ebnf-abn-token-table char 'non-terminal)
  409. (setq char (1+ char)))
  410. ;; Override end of line characters:
  411. (aset ebnf-abn-token-table ?\n 'end-of-rule) ; [NL] linefeed
  412. (aset ebnf-abn-token-table ?\r 'end-of-rule) ; [CR] carriage return
  413. ;; Override space characters:
  414. (aset ebnf-abn-token-table ?\013 'space) ; [VT] vertical tab
  415. (aset ebnf-abn-token-table ?\t 'space) ; [HT] horizontal tab
  416. (aset ebnf-abn-token-table ?\ 'space) ; [SP] space
  417. ;; Override form feed character:
  418. (aset ebnf-abn-token-table ?\f 'form-feed) ; [FF] form feed
  419. ;; Override other lexical characters:
  420. (aset ebnf-abn-token-table ?< 'non-terminal)
  421. (aset ebnf-abn-token-table ?% 'terminal)
  422. (aset ebnf-abn-token-table ?\" 'terminal)
  423. (aset ebnf-abn-token-table ?\( 'begin-group)
  424. (aset ebnf-abn-token-table ?\) 'end-group)
  425. (aset ebnf-abn-token-table ?* 'repeat)
  426. (aset ebnf-abn-token-table ?= 'equal)
  427. (aset ebnf-abn-token-table ?\[ 'begin-optional)
  428. (aset ebnf-abn-token-table ?\] 'end-optional)
  429. (aset ebnf-abn-token-table ?/ 'alternative)
  430. ;; Override comment character:
  431. (aset ebnf-abn-token-table ?\; 'comment)))
  432. ;; replace the range "\240-\377" (see `ebnf-range-regexp').
  433. (defconst ebnf-abn-non-terminal-chars
  434. (ebnf-range-regexp "-_0-9A-Za-z" ?\240 ?\377))
  435. (defconst ebnf-abn-non-terminal-letter-chars
  436. (ebnf-range-regexp "A-Za-z" ?\240 ?\377))
  437. (defun ebnf-abn-lex ()
  438. "Lexical analyzer for ABNF.
  439. Return a lexical token.
  440. See documentation for variable `ebnf-abn-lex'."
  441. (if (>= (point) ebnf-limit)
  442. 'end-of-input
  443. (let (token)
  444. ;; skip spaces and comments
  445. (while (if (> (following-char) 255)
  446. (progn
  447. (setq token 'error)
  448. nil)
  449. (setq token (aref ebnf-abn-token-table (following-char)))
  450. (cond
  451. ((eq token 'space)
  452. (skip-chars-forward " \013\t" ebnf-limit)
  453. (< (point) ebnf-limit))
  454. ((eq token 'comment)
  455. (ebnf-abn-skip-comment))
  456. ((eq token 'form-feed)
  457. (forward-char)
  458. (setq ebnf-action 'form-feed))
  459. ((eq token 'end-of-rule)
  460. (ebnf-abn-skip-end-of-rule))
  461. (t nil)
  462. )))
  463. (cond
  464. ;; end of input
  465. ((>= (point) ebnf-limit)
  466. 'end-of-input)
  467. ;; error
  468. ((eq token 'error)
  469. (error "Invalid character"))
  470. ;; end of rule
  471. ((eq token 'end-of-rule)
  472. 'end-of-rule)
  473. ;; integer
  474. ((eq token 'integer)
  475. (setq ebnf-abn-lex (ebnf-buffer-substring "0-9"))
  476. 'integer)
  477. ;; terminal: "string" or %[bdx]NNN((.NNN)+|-NNN)?
  478. ((eq token 'terminal)
  479. (setq ebnf-abn-lex
  480. (if (= (following-char) ?\")
  481. (ebnf-abn-string)
  482. (ebnf-abn-character)))
  483. 'terminal)
  484. ;; non-terminal: NAME or <NAME>
  485. ((eq token 'non-terminal)
  486. (let ((prose-p (= (following-char) ?<)))
  487. (when prose-p
  488. (forward-char)
  489. (or (looking-at ebnf-abn-non-terminal-letter-chars)
  490. (error "Invalid prose value")))
  491. (setq ebnf-abn-lex
  492. (ebnf-buffer-substring ebnf-abn-non-terminal-chars))
  493. (when prose-p
  494. (or (= (following-char) ?>)
  495. (error "Invalid prose value"))
  496. (setq ebnf-abn-lex (concat "<" ebnf-abn-lex ">"))))
  497. 'non-terminal)
  498. ;; equal: =, =/
  499. ((eq token 'equal)
  500. (forward-char)
  501. (if (/= (following-char) ?/)
  502. 'equal
  503. (forward-char)
  504. 'incremental-alternative))
  505. ;; miscellaneous: (, ), [, ], /, *
  506. (t
  507. (forward-char)
  508. token)
  509. ))))
  510. (defun ebnf-abn-skip-end-of-rule ()
  511. (let (eor-p)
  512. (while (progn
  513. ;; end of rule ==> 2 or more consecutive end of lines
  514. (setq eor-p (or (> (skip-chars-forward "\r\n" ebnf-limit) 1)
  515. eor-p))
  516. ;; skip spaces
  517. (skip-chars-forward " \013\t" ebnf-limit)
  518. ;; skip comments
  519. (and (= (following-char) ?\;)
  520. (ebnf-abn-skip-comment))))
  521. (not eor-p)))
  522. ;; replace the range "\177-\237" (see `ebnf-range-regexp').
  523. (defconst ebnf-abn-comment-chars
  524. (ebnf-range-regexp "^\n\000-\010\016-\037" ?\177 ?\237))
  525. (defun ebnf-abn-skip-comment ()
  526. (forward-char)
  527. (cond
  528. ;; open EPS file
  529. ((and ebnf-eps-executing (= (following-char) ?\[))
  530. (ebnf-eps-add-context (ebnf-abn-eps-filename)))
  531. ;; close EPS file
  532. ((and ebnf-eps-executing (= (following-char) ?\]))
  533. (ebnf-eps-remove-context (ebnf-abn-eps-filename)))
  534. ;; EPS header
  535. ((and ebnf-eps-executing (= (following-char) ?H))
  536. (ebnf-eps-header-comment (ebnf-abn-eps-filename)))
  537. ;; EPS footer
  538. ((and ebnf-eps-executing (= (following-char) ?F))
  539. (ebnf-eps-footer-comment (ebnf-abn-eps-filename)))
  540. ;; any other action in comment
  541. (t
  542. (setq ebnf-action (aref ebnf-comment-table (following-char)))
  543. (skip-chars-forward ebnf-abn-comment-chars ebnf-limit))
  544. )
  545. ;; check for a valid end of comment
  546. (cond ((>= (point) ebnf-limit)
  547. nil)
  548. ((= (following-char) ?\n)
  549. t)
  550. (t
  551. (error "Invalid character"))
  552. ))
  553. (defun ebnf-abn-eps-filename ()
  554. (forward-char)
  555. (ebnf-buffer-substring ebnf-abn-comment-chars))
  556. ;; replace the range "\240-\377" (see `ebnf-range-regexp').
  557. (defconst ebnf-abn-string-chars
  558. (ebnf-range-regexp " -!#-~" ?\240 ?\377))
  559. (defun ebnf-abn-string ()
  560. (buffer-substring-no-properties
  561. (progn
  562. (forward-char)
  563. (point))
  564. (progn
  565. (skip-chars-forward ebnf-abn-string-chars ebnf-limit)
  566. (or (= (following-char) ?\")
  567. (error "Missing `\"'"))
  568. (prog1
  569. (point)
  570. (forward-char)))))
  571. (defun ebnf-abn-character ()
  572. ;; %[bdx]NNN((-NNN)|(.NNN)+)?
  573. (buffer-substring-no-properties
  574. (point)
  575. (progn
  576. (forward-char)
  577. (let* ((char (following-char))
  578. (chars (cond ((or (= char ?B) (= char ?b)) "01")
  579. ((or (= char ?D) (= char ?d)) "0-9")
  580. ((or (= char ?X) (= char ?x)) "0-9A-Fa-f")
  581. (t (error "Invalid terminal value")))))
  582. (forward-char)
  583. (or (> (skip-chars-forward chars ebnf-limit) 0)
  584. (error "Invalid terminal value"))
  585. (if (= (following-char) ?-)
  586. (progn
  587. (forward-char)
  588. (or (> (skip-chars-forward chars ebnf-limit) 0)
  589. (error "Invalid terminal value range")))
  590. (while (= (following-char) ?.)
  591. (forward-char)
  592. (or (> (skip-chars-forward chars ebnf-limit) 0)
  593. (error "Invalid terminal value")))))
  594. (point))))
  595. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  596. (provide 'ebnf-abn)
  597. ;;; ebnf-abn.el ends here