parser.scm 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. ;;; nyacc/lang/c99/parser.scm - C parser execution
  2. ;; Copyright (C) 2015-2019 Matthew R. Wette
  3. ;;
  4. ;; This library is free software; you can redistribute it and/or
  5. ;; modify it under the terms of the GNU Lesser General Public
  6. ;; License as published by the Free Software Foundation; either
  7. ;; version 3 of the License, or (at your option) any later version.
  8. ;;
  9. ;; This library is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;; Lesser General Public License for more details.
  13. ;;
  14. ;; You should have received a copy of the GNU Lesser General Public License
  15. ;; along with this library; if not, see <http://www.gnu.org/licenses/>.
  16. ;;; Code:
  17. (define-module (nyacc lang c99 parser)
  18. #:export (parse-c99 parse-c99x gen-c99-lexer gen-c99x-lexer gen-c-lexer)
  19. #:use-module (nyacc lex)
  20. #:use-module (nyacc parse)
  21. #:use-module (nyacc lang util)
  22. #:use-module (nyacc lang c99 cpp)
  23. #:use-module (nyacc lang c99 util)
  24. #:re-export (c99-def-help c99-std-help))
  25. (cond-expand
  26. (guile-3)
  27. (guile-2)
  28. (guile
  29. (use-modules (srfi srfi-16))
  30. (use-modules (ice-9 optargs))
  31. (use-modules (ice-9 syncase))
  32. (use-modules (nyacc compat18)))
  33. (else))
  34. (include-from-path "nyacc/lang/c99/body.scm")
  35. ;; Routines to process specifier-lists and declarators, indended
  36. ;; to provide option to convert attribute-specifiers elements into
  37. ;; SXML attributes. See move-attributes in util.scm.
  38. ;;(define process-specs identity)
  39. ;;(define process-declr identity)
  40. (define process-specs move-attributes)
  41. (define process-declr move-attributes)
  42. ;; === file parser ====================
  43. (include-from-path "nyacc/lang/c99/mach.d/c99-act.scm")
  44. (include-from-path "nyacc/lang/c99/mach.d/c99-tab.scm")
  45. (define c99-raw-parser
  46. (make-lalr-parser
  47. (acons 'act-v c99-act-v c99-tables)
  48. #:skip-if-unexp '($lone-comm $code-comm $pragma)))
  49. (define gen-c99-lexer
  50. (make-c99-lexer-generator c99-mtab c99-raw-parser))
  51. ;; @deffn {Procedure} parse-c99 [options]
  52. ;; where options are
  53. ;; @table code
  54. ;; @item #:cpp-defs @i{defs-list}
  55. ;; @i{defs-list} is a list of strings where each string is of the form
  56. ;; @i{NAME} or @i{NAME=VALUE}.
  57. ;; @item #:inc-dirs @i{dir-list}
  58. ;; @{dir-list} is a list of strings of paths to look for directories.
  59. ;; @item #:inc-help @i{helpers}
  60. ;; @i{helpers} is an a-list where keys are include files (e.g.,
  61. ;; @code{"stdint.h"}) and the value is a list of type aliases or CPP define
  62. ;; (e.g., @code{"foo_t" "FOO_MAX=3"}).
  63. ;; @item #:mode @i{mode}
  64. ;; @i{mode} is one literal @code{'code}, @code{'file}, or @code{'decl}.
  65. ;; The default mode is @code{'code}.
  66. ;; @item #:debug @i{bool}
  67. ;; a boolean which if true prints states from the parser
  68. ;; @end table
  69. ;; @example
  70. ;; (with-input-from-file "abc.c"
  71. ;; (parse-c #:cpp-defs '("ABC=123"))
  72. ;; #:inc-dirs '(("." "./incs" "/usr/include"))
  73. ;; #:inc-help (append '("myinc.h" "foo_t" "bar_t") c99-std-help)
  74. ;; #:mode 'file))
  75. ;; @end example
  76. ;; Note: for @code{file} mode user still needs to make sure CPP conditional
  77. ;; expressions can be fully evaluated, which may mean adding compiler generated
  78. ;; defines (e.g., using @code{gen-cpp-defs}).
  79. ;; @end deffn
  80. (define* (parse-c99 #:key
  81. (cpp-defs '()) ; CPP defines
  82. (inc-dirs '()) ; include dirs
  83. (inc-help c99-def-help) ; include helpers
  84. (mode 'code) ; mode: 'file, 'code or 'decl
  85. (xdef? #f) ; pred to determine expand
  86. (show-incs #f) ; show include files
  87. (debug #f)) ; debug
  88. (let ((info (make-cpi debug show-incs cpp-defs (cons "." inc-dirs) inc-help)))
  89. (with-fluids ((*info* info)
  90. (*input-stack* '()))
  91. (catch 'c99-error
  92. (lambda ()
  93. (catch 'nyacc-error
  94. (lambda () (c99-raw-parser
  95. (gen-c99-lexer #:mode mode
  96. #:xdef? xdef?
  97. #:show-incs show-incs)
  98. #:debug debug))
  99. (lambda (key fmt . args) (apply throw 'c99-error fmt args))))
  100. (lambda (key fmt . args)
  101. (report-error fmt args)
  102. #f)))))
  103. ;; === expr parser ====================
  104. (include-from-path "nyacc/lang/c99/mach.d/c99x-act.scm")
  105. (include-from-path "nyacc/lang/c99/mach.d/c99x-tab.scm")
  106. (define c99x-raw-parser
  107. (make-lalr-parser
  108. (acons 'act-v c99x-act-v c99x-tables)
  109. #:skip-if-unexp '($lone-comm $code-comm $pragma)))
  110. (define gen-c99x-lexer
  111. (make-c99-lexer-generator c99x-mtab c99x-raw-parser))
  112. ;; @deffn {Procedure} parse-c99x string [typenames] [options]
  113. ;; where @var{string} is a string C expression, @var{typenames}
  114. ;; is a list of strings to be treated as typenames
  115. ;; and @var{options} may be any of
  116. ;; @table
  117. ;; @item cpp-defs
  118. ;; a list of strings to be treated as preprocessor definitions
  119. ;; @item xdef?
  120. ;; this argument can be a boolean a predicate taking a string argument
  121. ;; @item debug
  122. ;; a boolean which if true prints states from the parser
  123. ;; @end table
  124. ;; This needs to be explained in some detail.
  125. ;; [tyns '("foo_t")]
  126. ;; @end deffn
  127. (define* (parse-c99x expr-string
  128. #:optional
  129. (tyns '()) ; defined typenames
  130. #:key
  131. (cpp-defs '()) ; CPP defines
  132. (xdef? #f) ; pred to determine expand
  133. (debug #f)) ; debug?
  134. (let ((info (make-cpi debug #f cpp-defs '(".") '())))
  135. (set-cpi-ptl! info (cons tyns (cpi-ptl info)))
  136. (with-fluids ((*info* info)
  137. (*input-stack* '()))
  138. (with-input-from-string expr-string
  139. (lambda ()
  140. (catch 'c99-error
  141. (lambda ()
  142. (catch 'nyacc-error
  143. (lambda ()
  144. (c99x-raw-parser (gen-c99x-lexer #:mode 'code #:xdef? xdef?)
  145. #:debug debug))
  146. (lambda (key fmt . args)
  147. (apply throw 'c99-error fmt args))))
  148. (lambda (key fmt . rest)
  149. (report-error fmt rest)
  150. #f)))))))
  151. ;; --- last line ---