ebnf-yac.el 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. ;;; ebnf-yac.el --- parser for Yacc/Bison
  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.4
  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 Yacc/Bison.
  26. ;;
  27. ;; See ebnf2ps.el for documentation.
  28. ;;
  29. ;;
  30. ;; Yacc/Bison Syntax
  31. ;; -----------------
  32. ;;
  33. ;; YACC = { YACC-Definitions }* "%%" { YACC-Rule }* [ "%%" [ YACC-Code ] ].
  34. ;;
  35. ;; YACC-Definitions = ( "%token" | "%left" | "%right" | "%nonassoc" )
  36. ;; [ "<" Name ">" ] Name-List
  37. ;; | "%prec" Name
  38. ;; | "any other Yacc definition"
  39. ;; .
  40. ;;
  41. ;; YACC-Code = "any C definition".
  42. ;;
  43. ;; YACC-Rule = Name ":" Alternative ";".
  44. ;;
  45. ;; Alternative = { Sequence || "|" }*.
  46. ;;
  47. ;; Sequence = { Factor }*.
  48. ;;
  49. ;; Factor = Name
  50. ;; | "'" "character" "'"
  51. ;; | "error"
  52. ;; | "{" "C like commands" "}"
  53. ;; .
  54. ;;
  55. ;; Name-List = { Name || "," }*.
  56. ;;
  57. ;; Name = "[A-Za-z][A-Za-z0-9_.]*".
  58. ;;
  59. ;; Comment = "/*" "any character, but the sequence \"*/\"" "*/"
  60. ;; | "//" "any character, but the newline \"\\n\"" "\\n".
  61. ;;
  62. ;;
  63. ;; In other words, a valid Name begins with a letter (upper or lower case)
  64. ;; followed by letters, decimal digits, underscore (_) or point (.). For
  65. ;; example: this_is_a_valid.name, Another_EXAMPLE, mIxEd.CaSe.
  66. ;;
  67. ;;
  68. ;; Acknowledgements
  69. ;; ----------------
  70. ;;
  71. ;; Thanks to Matthew K. Junker <junker@alum.mit.edu> for the suggestion to deal
  72. ;; with %right, %left and %prec pragmas. His suggestion was extended to deal
  73. ;; with %nonassoc pragma too.
  74. ;;
  75. ;;
  76. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  77. ;;; Code:
  78. (require 'ebnf-otz)
  79. (defvar ebnf-yac-lex nil
  80. "Value returned by `ebnf-yac-lex' function.")
  81. (defvar ebnf-yac-token-list nil
  82. "List of `%TOKEN' names.")
  83. (defvar ebnf-yac-skip-char nil
  84. "Non-nil means skip printable characters with no grammatical meaning.")
  85. (defvar ebnf-yac-error nil
  86. "Non-nil means \"error\" occurred.")
  87. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  88. ;; Syntactic analyzer
  89. ;;; YACC = { YACC-Definitions }* "%%" { YACC-Rule }* [ "%%" [ YACC-Code ] ].
  90. ;;;
  91. ;;; YACC-Code = "any C definition".
  92. (defun ebnf-yac-parser (start)
  93. "yacc/Bison parser."
  94. (let ((total (+ (- ebnf-limit start) 1))
  95. (bias (1- start))
  96. (origin (point))
  97. syntax-list token rule)
  98. (goto-char start)
  99. (setq token (ebnf-yac-lex))
  100. (and (eq token 'end-of-input)
  101. (error "Invalid Yacc/Bison file format"))
  102. (or (eq (ebnf-yac-definitions token) 'yac-separator)
  103. (error "Missing `%%%%'"))
  104. (setq token (ebnf-yac-lex))
  105. (while (not (memq token '(end-of-input yac-separator)))
  106. (ebnf-message-float
  107. "Parsing...%s%%"
  108. (/ (* (- (point) bias) 100.0) total))
  109. (setq token (ebnf-yac-rule token)
  110. rule (cdr token)
  111. token (car token))
  112. (or (ebnf-add-empty-rule-list rule)
  113. (setq syntax-list (cons rule syntax-list))))
  114. (goto-char origin)
  115. syntax-list))
  116. ;;; YACC-Definitions = ( "%token" | "%left" | "%right" | "%nonassoc" )
  117. ;;; [ "<" Name ">" ] Name-List
  118. ;;; | "%prec" Name
  119. ;;; | "any other Yacc definition"
  120. ;;; .
  121. (defun ebnf-yac-definitions (token)
  122. (let ((ebnf-yac-skip-char t))
  123. (while (not (memq token '(yac-separator end-of-input)))
  124. (setq token
  125. (cond
  126. ;; ( "%token" | "%left" | "%right" | "%nonassoc" )
  127. ;; [ "<" Name ">" ] Name-List
  128. ((eq token 'yac-token)
  129. (setq token (ebnf-yac-lex))
  130. (when (eq token 'open-angle)
  131. (or (eq (ebnf-yac-lex) 'non-terminal)
  132. (error "Missing type name"))
  133. (or (eq (ebnf-yac-lex) 'close-angle)
  134. (error "Missing `>'"))
  135. (setq token (ebnf-yac-lex)))
  136. (setq token (ebnf-yac-name-list token)
  137. ebnf-yac-token-list (nconc (cdr token)
  138. ebnf-yac-token-list))
  139. (car token))
  140. ;; "%prec" Name
  141. ((eq token 'yac-prec)
  142. (or (eq (ebnf-yac-lex) 'non-terminal)
  143. (error "Missing prec name"))
  144. (ebnf-yac-lex))
  145. ;; "any other Yacc definition"
  146. (t
  147. (ebnf-yac-lex))
  148. )))
  149. token))
  150. ;;; YACC-Rule = Name ":" Alternative ";".
  151. (defun ebnf-yac-rule (token)
  152. (let ((header ebnf-yac-lex)
  153. (action ebnf-action)
  154. body)
  155. (setq ebnf-action nil)
  156. (or (eq token 'non-terminal)
  157. (error "Invalid rule name"))
  158. (or (eq (ebnf-yac-lex) 'colon)
  159. (error "Invalid rule: missing `:'"))
  160. (setq body (ebnf-yac-alternative))
  161. (or (eq (car body) 'period)
  162. (error "Invalid rule: missing `;'"))
  163. (setq body (cdr body))
  164. (ebnf-eps-add-production header)
  165. (cons (ebnf-yac-lex)
  166. (ebnf-make-production header body action))))
  167. ;;; Alternative = { Sequence || "|" }*.
  168. (defun ebnf-yac-alternative ()
  169. (let (body sequence)
  170. (while (eq (car (setq sequence (ebnf-yac-sequence)))
  171. 'alternative)
  172. (and (setq sequence (cdr sequence))
  173. (setq body (cons sequence body))))
  174. (ebnf-token-alternative body sequence)))
  175. ;;; Sequence = { Factor }*.
  176. (defun ebnf-yac-sequence ()
  177. (let (ebnf-yac-error token seq factor)
  178. (while (setq token (ebnf-yac-lex)
  179. factor (ebnf-yac-factor token))
  180. (setq seq (cons factor seq)))
  181. (cons token
  182. (if (and ebnf-yac-ignore-error-recovery ebnf-yac-error)
  183. ;; ignore error recovery
  184. nil
  185. (ebnf-token-sequence seq)))))
  186. ;;; Factor = Name
  187. ;;; | "'" "character" "'"
  188. ;;; | "error"
  189. ;;; | "{" "C like commands" "}"
  190. ;;; .
  191. (defun ebnf-yac-factor (token)
  192. (cond
  193. ;; 'character'
  194. ((eq token 'terminal)
  195. (ebnf-make-terminal ebnf-yac-lex))
  196. ;; Name
  197. ((eq token 'non-terminal)
  198. (ebnf-make-non-terminal ebnf-yac-lex))
  199. ;; "error"
  200. ((eq token 'yac-error)
  201. (ebnf-make-special ebnf-yac-lex))
  202. ;; not a factor
  203. (t
  204. nil)
  205. ))
  206. ;;; Name-List = { Name || "," }*.
  207. (defun ebnf-yac-name-list (token)
  208. (let (names)
  209. (when (eq token 'non-terminal)
  210. (while (progn
  211. (setq names (cons ebnf-yac-lex names)
  212. token (ebnf-yac-lex))
  213. (eq token 'comma))
  214. (or (eq (ebnf-yac-lex) 'non-terminal)
  215. (error "Missing token name"))))
  216. (cons token names)))
  217. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  218. ;; Lexical analyzer
  219. ;;; Name = "[A-Za-z][A-Za-z0-9_.]*".
  220. ;;;
  221. ;;; Comment = "/*" "any character, but the sequence \"*/\"" "*/"
  222. ;;; | "//" "any character" "\\n".
  223. (defconst ebnf-yac-token-table
  224. ;; control character & 8-bit character are set to `error'
  225. (let ((table (make-vector 256 'error)))
  226. ;; upper & lower case letters:
  227. (mapc
  228. #'(lambda (char)
  229. (aset table char 'non-terminal))
  230. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
  231. ;; printable characters:
  232. (mapc
  233. #'(lambda (char)
  234. (aset table char 'character))
  235. "!#$&()*+-.0123456789=?@[\\]^_`~")
  236. ;; Override space characters:
  237. (aset table ?\n 'space) ; [NL] linefeed
  238. (aset table ?\r 'space) ; [CR] carriage return
  239. (aset table ?\t 'space) ; [HT] horizontal tab
  240. (aset table ?\ 'space) ; [SP] space
  241. ;; Override form feed character:
  242. (aset table ?\f 'form-feed) ; [FF] form feed
  243. ;; Override other lexical characters:
  244. (aset table ?< 'open-angle)
  245. (aset table ?> 'close-angle)
  246. (aset table ?, 'comma)
  247. (aset table ?% 'yac-pragma)
  248. (aset table ?/ 'slash)
  249. (aset table ?\{ 'yac-code)
  250. (aset table ?\" 'string)
  251. (aset table ?\' 'terminal)
  252. (aset table ?: 'colon)
  253. (aset table ?| 'alternative)
  254. (aset table ?\; 'period)
  255. table)
  256. "Vector used to map characters to a lexical token.")
  257. (defun ebnf-yac-initialize ()
  258. "Initializations for Yacc/Bison parser."
  259. (setq ebnf-yac-token-list nil))
  260. (defun ebnf-yac-lex ()
  261. "Lexical analyzer for Yacc/Bison.
  262. Return a lexical token.
  263. See documentation for variable `ebnf-yac-lex'."
  264. (if (>= (point) ebnf-limit)
  265. 'end-of-input
  266. (let (token)
  267. ;; skip spaces, code blocks and comments
  268. (while (if (> (following-char) 255)
  269. (progn
  270. (setq token 'error)
  271. nil)
  272. (setq token (aref ebnf-yac-token-table (following-char)))
  273. (cond
  274. ((or (eq token 'space)
  275. (and ebnf-yac-skip-char
  276. (eq token 'character)))
  277. (ebnf-yac-skip-spaces))
  278. ((eq token 'yac-code)
  279. (ebnf-yac-skip-code))
  280. ((eq token 'slash)
  281. (ebnf-yac-handle-comment))
  282. ((eq token 'form-feed)
  283. (forward-char)
  284. (setq ebnf-action 'form-feed))
  285. (t nil)
  286. )))
  287. (cond
  288. ;; end of input
  289. ((>= (point) ebnf-limit)
  290. 'end-of-input)
  291. ;; error
  292. ((eq token 'error)
  293. (error "Invalid character"))
  294. ;; "string"
  295. ((eq token 'string)
  296. (setq ebnf-yac-lex (ebnf-get-string))
  297. 'string)
  298. ;; terminal: 'char'
  299. ((eq token 'terminal)
  300. (setq ebnf-yac-lex (ebnf-string " -&(-~" ?\' "terminal"))
  301. 'terminal)
  302. ;; non-terminal, terminal or "error"
  303. ((eq token 'non-terminal)
  304. (setq ebnf-yac-lex (ebnf-buffer-substring "0-9A-Za-z_."))
  305. (cond ((member ebnf-yac-lex ebnf-yac-token-list)
  306. 'terminal)
  307. ((string= ebnf-yac-lex "error")
  308. (setq ebnf-yac-error t)
  309. 'yac-error)
  310. (t
  311. 'non-terminal)
  312. ))
  313. ;; %% and Yacc pragmas (%TOKEN, %START, etc).
  314. ((eq token 'yac-pragma)
  315. (forward-char)
  316. (cond
  317. ;; Yacc separator
  318. ((eq (following-char) ?%)
  319. (forward-char)
  320. 'yac-separator)
  321. ;; %TOKEN, %RIGHT, %LEFT, %PREC, %NONASSOC
  322. ((cdr (assoc (upcase (ebnf-buffer-substring "0-9A-Za-z_"))
  323. '(("TOKEN" . yac-token)
  324. ("RIGHT" . yac-token)
  325. ("LEFT" . yac-token)
  326. ("NONASSOC" . yac-token)
  327. ("PREC" . yac-prec)))))
  328. ;; other Yacc pragmas
  329. (t
  330. 'yac-pragma)
  331. ))
  332. ;; miscellaneous
  333. (t
  334. (forward-char)
  335. token)
  336. ))))
  337. (defun ebnf-yac-skip-spaces ()
  338. (skip-chars-forward
  339. (if ebnf-yac-skip-char
  340. "\n\r\t !#$&()*+-.0123456789=?@[\\\\]^_`~"
  341. "\n\r\t ")
  342. ebnf-limit)
  343. (< (point) ebnf-limit))
  344. ;; replace the range "\177-\377" (see `ebnf-range-regexp').
  345. (defconst ebnf-yac-skip-chars
  346. (ebnf-range-regexp "^{}/'\"\000-\010\013\016-\037" ?\177 ?\377))
  347. (defun ebnf-yac-skip-code ()
  348. (forward-char)
  349. (let ((pair 1))
  350. (while (> pair 0)
  351. (skip-chars-forward ebnf-yac-skip-chars ebnf-limit)
  352. (cond
  353. ((= (following-char) ?{)
  354. (forward-char)
  355. (setq pair (1+ pair)))
  356. ((= (following-char) ?})
  357. (forward-char)
  358. (setq pair (1- pair)))
  359. ((= (following-char) ?/)
  360. (ebnf-yac-handle-comment))
  361. ((= (following-char) ?\")
  362. (ebnf-get-string))
  363. ((= (following-char) ?\')
  364. (ebnf-string " -&(-~" ?\' "character"))
  365. (t
  366. (error "Invalid character"))
  367. )))
  368. (ebnf-yac-skip-spaces))
  369. (defun ebnf-yac-handle-comment ()
  370. (forward-char)
  371. (cond
  372. ;; begin comment
  373. ((= (following-char) ?*)
  374. (ebnf-yac-skip-comment)
  375. (ebnf-yac-skip-spaces))
  376. ;; line comment
  377. ((= (following-char) ?/)
  378. (end-of-line)
  379. (ebnf-yac-skip-spaces))
  380. ;; no comment
  381. (t nil)
  382. ))
  383. ;; replace the range "\177-\237" (see `ebnf-range-regexp').
  384. (defconst ebnf-yac-comment-chars
  385. (ebnf-range-regexp "^*\000-\010\013\016-\037" ?\177 ?\237))
  386. (defun ebnf-yac-skip-comment ()
  387. (forward-char)
  388. (cond
  389. ;; open EPS file
  390. ((and ebnf-eps-executing (= (following-char) ?\[))
  391. (ebnf-eps-add-context (ebnf-yac-eps-filename)))
  392. ;; close EPS file
  393. ((and ebnf-eps-executing (= (following-char) ?\]))
  394. (ebnf-eps-remove-context (ebnf-yac-eps-filename)))
  395. ;; EPS header
  396. ((and ebnf-eps-executing (= (following-char) ?H))
  397. (ebnf-eps-header-comment (ebnf-yac-eps-filename)))
  398. ;; EPS footer
  399. ((and ebnf-eps-executing (= (following-char) ?F))
  400. (ebnf-eps-footer-comment (ebnf-yac-eps-filename)))
  401. ;; any other action in comment
  402. (t
  403. (setq ebnf-action (aref ebnf-comment-table (following-char))))
  404. )
  405. (let ((not-end t))
  406. (while not-end
  407. (skip-chars-forward ebnf-yac-comment-chars ebnf-limit)
  408. (cond ((>= (point) ebnf-limit)
  409. (error "Missing end of comment: `*/'"))
  410. ((= (following-char) ?*)
  411. (skip-chars-forward "*" ebnf-limit)
  412. (when (= (following-char) ?/)
  413. ;; end of comment
  414. (forward-char)
  415. (setq not-end nil)))
  416. (t
  417. (error "Invalid character"))
  418. ))))
  419. (defun ebnf-yac-eps-filename ()
  420. (forward-char)
  421. (buffer-substring-no-properties
  422. (point)
  423. (let ((chars (concat ebnf-yac-comment-chars "\n"))
  424. found)
  425. (while (not found)
  426. (skip-chars-forward chars ebnf-limit)
  427. (setq found
  428. (cond ((>= (point) ebnf-limit)
  429. (point))
  430. ((= (following-char) ?*)
  431. (skip-chars-forward "*" ebnf-limit)
  432. (if (/= (following-char) ?\/)
  433. nil
  434. (backward-char)
  435. (point)))
  436. (t
  437. (point))
  438. )))
  439. found)))
  440. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  441. (provide 'ebnf-yac)
  442. ;;; ebnf-yac.el ends here