grammar.scm 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. (library (grammar)
  2. ;; export all non-terminal symbols for testing and usage
  3. ;; elsewhere in the code
  4. (export
  5. ;; special characters
  6. SPACE
  7. NEWLINE
  8. ATTRIBUTE-VALUE-SEPARATOR
  9. COMMENT-STARTER
  10. DIGIT
  11. NON-ZERO-DIGIT
  12. ;; character classes
  13. WHITESPACE
  14. WHITESPACE-EXCEPT-NEWLINE
  15. ;; special strings
  16. INTEGER
  17. POSITIVE-INTEGER
  18. SIMPLE-POSITIVE-FLOAT-NUMBER
  19. SIMPLE-FLOAT-NUMBER
  20. ACT-NUMBER
  21. NUMBER
  22. NON-NEWLINE-CONTAINING-STRING
  23. NON-WHITESPACE-CONTAINING-STRING
  24. FILENAME
  25. COMMENT-TEXT
  26. ENTITY-COMMENT-TEXT
  27. IGNORED-WHITESPACE
  28. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  29. ;; tags
  30. STAGE-TAG
  31. STAGE-END-TAG
  32. PHASE-TAG
  33. PHASE-END-TAG
  34. BOSS-TAG
  35. SOLDIER-TAG
  36. END-TAG
  37. ;; attribute names
  38. ID-ATTRIBUTE-NAME
  39. BOUND-ATTRIBUTE-NAME
  40. MUSIC-ATTRIBUTE-NAME
  41. X-COORD-ATTRIBUTE-NAME
  42. Y-COORD-ATTRIBUTE-NAME
  43. HP-ATTRIBUTE-NAME
  44. RATIO-ATTRIBUTE-NAME
  45. TIMES-ATTRIBUTE-NAME
  46. RESERVE-ATTRIBUTE-NAME
  47. JOIN-ATTRIBUTE-NAME
  48. JOIN-RESERVE-ATTRIBUTE-NAME
  49. ACT-ATTRIBUTE-NAME
  50. GOTO-PHASE-ATTRIBUTE-NAME
  51. ;; attributes
  52. ID-ATTRIBUTE
  53. BOUND-ATTRIBUTE
  54. MUSIC-ATTRIBUTE
  55. X-COORD-ATTRIBUTE
  56. Y-COORD-ATTRIBUTE
  57. HP-ATTRIBUTE
  58. RATIO-ATTRIBUTE
  59. TIMES-ATTRIBUTE
  60. RESERVE-ATTRIBUTE
  61. JOIN-ATTRIBUTE
  62. JOIN-RESERVE-ATTRIBUTE
  63. ACT-ATTRIBUTE
  64. GOTO-PHASE-ATTRIBUTE
  65. STAGE-ID-ATTRIBUTE
  66. ;; compound parts
  67. COMMENT
  68. ENTITY-COMMENT
  69. MUSIC-SWITCH
  70. ENTITY-ATTRIBUTE
  71. ENTITY
  72. PHASE-ENTITIES
  73. PHASE
  74. SURVIVAL-STAGE-PHASES
  75. SURVIVAL-STAGE
  76. NORMAL-STAGE
  77. NORMAL-STAGES
  78. STAGE-DAT)
  79. (import
  80. (except (rnrs base) let-values map error)
  81. (only (guile)
  82. lambda* λ
  83. command-line
  84. string-null?)
  85. (ice-9 peg)
  86. (prefix (srfi srfi-1) srfi-1:)))
  87. ;; Explanation:
  88. ;; Non-terminal symbols are written in capital characters.
  89. ;; ==================
  90. ;; SPECIAL CHARACTERS
  91. ;; ==================
  92. (define-peg-pattern SPACE none
  93. " ")
  94. (define-peg-pattern NEWLINE none
  95. "\n")
  96. (define-peg-pattern ATTRIBUTE-VALUE-SEPARATOR none
  97. ":")
  98. (define-peg-pattern COMMENT-STARTER all
  99. "#")
  100. (define-peg-pattern DIGIT body
  101. (or (range #\0 #\9)))
  102. (define-peg-pattern NON-ZERO-DIGIT body
  103. (or (range #\1 #\9)))
  104. ;; =================
  105. ;; CHARACTER CLASSES
  106. ;; =================
  107. (define-peg-pattern WHITESPACE none
  108. (or "\n"
  109. " "
  110. "\t"
  111. "\r"))
  112. (define-peg-pattern WHITESPACE-EXCEPT-NEWLINE none
  113. (or " "
  114. "\t"
  115. "\r"))
  116. ;; ===============
  117. ;; SPECIAL STRINGS
  118. ;; ===============
  119. (define-peg-pattern INTEGER body
  120. (or (and (? "-") NON-ZERO-DIGIT (* DIGIT))
  121. "0"))
  122. (define-peg-pattern POSITIVE-INTEGER body
  123. (or (and NON-ZERO-DIGIT (* DIGIT))
  124. "0"))
  125. (define-peg-pattern SIMPLE-POSITIVE-FLOAT-NUMBER body
  126. (or (and (* DIGIT) "." (+ DIGIT))))
  127. (define-peg-pattern SIMPLE-FLOAT-NUMBER body
  128. (or (and (? "-") (* DIGIT) "." (+ DIGIT))))
  129. (define-peg-pattern NUMBER body
  130. ;; Note: must put the more complex non-terminal first, to
  131. ;; avoid matching an INTEGER and then being stuck with a
  132. ;; SIMPLE-POSITIVE-FLOAT-NUMBER rest, which consists of
  133. ;; "." and any number of DIGIT, which would not be parsed,
  134. ;; because attributes expect only one number. --> (or ...)
  135. ;; is still an ordered choice operator!
  136. (or SIMPLE-FLOAT-NUMBER
  137. SIMPLE-POSITIVE-FLOAT-NUMBER
  138. INTEGER
  139. POSITIVE-INTEGER))
  140. ;; The act number is a reference to a frame inside
  141. ;; criminal.dat. Only some integer values work properly for
  142. ;; the act attribute.
  143. (define-peg-pattern MONK-ACT-NUMBER body "0")
  144. (define-peg-pattern MARK-ACT-NUMBER body "10")
  145. (define-peg-pattern JACK-ACT-NUMBER body "20")
  146. (define-peg-pattern SORCERER-ACT-NUMBER body "30")
  147. (define-peg-pattern BANDIT-ACT-NUMBER body "40")
  148. (define-peg-pattern HUNTER-ACT-NUMBER body "50")
  149. (define-peg-pattern JAN-ACT-NUMBER body "60")
  150. (define-peg-pattern ACT-NUMBER body
  151. (or MONK-ACT-NUMBER
  152. MARK-ACT-NUMBER
  153. JACK-ACT-NUMBER
  154. SORCERER-ACT-NUMBER
  155. BANDIT-ACT-NUMBER
  156. HUNTER-ACT-NUMBER
  157. JAN-ACT-NUMBER))
  158. ;; Note the pattern in the following non-terminal symbol
  159. ;; NON-NEWLINE-CONTAINING-STRING. To make an expression not match a specific
  160. ;; character or string, use (not-followed-by ...) first and (and ...) it the
  161. ;; other thing, which contains the things you excluded using (not-followed-by
  162. ;; ...). This way you are saying "I want this, but without the thing in
  163. ;; (not-followed-by ...).".
  164. (define-peg-pattern NON-NEWLINE-CONTAINING-STRING body
  165. (+ (and (not-followed-by NEWLINE) peg-any)))
  166. (define-peg-pattern NON-WHITESPACE-CONTAINING-STRING body
  167. (+ (and (not-followed-by WHITESPACE) peg-any)))
  168. (define-peg-pattern FILENAME all
  169. NON-NEWLINE-CONTAINING-STRING)
  170. (define-peg-pattern COMMENT-TEXT all
  171. NON-NEWLINE-CONTAINING-STRING)
  172. (define-peg-pattern ENTITY-COMMENT-TEXT all
  173. NON-WHITESPACE-CONTAINING-STRING)
  174. (define-peg-pattern IGNORED-WHITESPACE none
  175. (ignore (* WHITESPACE)))
  176. (define-peg-pattern IGNORED-WHITESPACE-EXCEPT-NEWLINE none
  177. (ignore (* WHITESPACE-EXCEPT-NEWLINE)))
  178. ;; ====
  179. ;; TAGS
  180. ;; ====
  181. (define-peg-pattern STAGE-TAG all
  182. "<stage>")
  183. (define-peg-pattern STAGE-END-TAG all
  184. "<stage_end>")
  185. (define-peg-pattern PHASE-TAG all
  186. "<phase>")
  187. (define-peg-pattern PHASE-END-TAG all
  188. "<phase_end>")
  189. (define-peg-pattern BOSS-TAG all
  190. "<boss>")
  191. (define-peg-pattern SOLDIER-TAG all
  192. "<soldier>")
  193. (define-peg-pattern END-TAG all
  194. "<end>")
  195. ;; NOTE: The <end> tag is actually completely useless in terms of semantics and
  196. ;; might as well be a sloppy remnant of a once imagined need for an over all
  197. ;; ending marker. It should be ignored whenever possible.
  198. (define-peg-pattern IGNORED-END-TAG none
  199. (ignore (* END-TAG)))
  200. ;; ==========
  201. ;; ATTRIBUTES
  202. ;; ==========
  203. (define-peg-pattern ID-ATTRIBUTE-NAME all
  204. "id")
  205. (define-peg-pattern BOUND-ATTRIBUTE-NAME all
  206. "bound")
  207. (define-peg-pattern MUSIC-ATTRIBUTE-NAME all
  208. "music")
  209. (define-peg-pattern X-COORD-ATTRIBUTE-NAME all
  210. "x")
  211. (define-peg-pattern Y-COORD-ATTRIBUTE-NAME all
  212. "y")
  213. (define-peg-pattern HP-ATTRIBUTE-NAME all
  214. "hp")
  215. (define-peg-pattern RATIO-ATTRIBUTE-NAME all
  216. "ratio")
  217. (define-peg-pattern TIMES-ATTRIBUTE-NAME all
  218. "times")
  219. (define-peg-pattern RESERVE-ATTRIBUTE-NAME all
  220. "reserve")
  221. (define-peg-pattern JOIN-ATTRIBUTE-NAME all
  222. "join")
  223. (define-peg-pattern JOIN-RESERVE-ATTRIBUTE-NAME all
  224. "join_reserve")
  225. (define-peg-pattern ACT-ATTRIBUTE-NAME all
  226. "act")
  227. (define-peg-pattern GOTO-PHASE-ATTRIBUTE-NAME all
  228. "when_clear_goto_phase")
  229. (define-peg-pattern ID-ATTRIBUTE all
  230. (and ID-ATTRIBUTE-NAME
  231. ATTRIBUTE-VALUE-SEPARATOR
  232. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  233. POSITIVE-INTEGER))
  234. (define-peg-pattern BOUND-ATTRIBUTE all
  235. (and BOUND-ATTRIBUTE-NAME
  236. ATTRIBUTE-VALUE-SEPARATOR
  237. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  238. POSITIVE-INTEGER))
  239. (define-peg-pattern MUSIC-ATTRIBUTE all
  240. (and MUSIC-ATTRIBUTE-NAME
  241. ATTRIBUTE-VALUE-SEPARATOR
  242. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  243. FILENAME))
  244. (define-peg-pattern X-COORD-ATTRIBUTE all
  245. (and X-COORD-ATTRIBUTE-NAME
  246. ATTRIBUTE-VALUE-SEPARATOR
  247. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  248. INTEGER))
  249. (define-peg-pattern Y-COORD-ATTRIBUTE all
  250. (and Y-COORD-ATTRIBUTE-NAME
  251. ATTRIBUTE-VALUE-SEPARATOR
  252. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  253. INTEGER))
  254. (define-peg-pattern HP-ATTRIBUTE all
  255. (and HP-ATTRIBUTE-NAME
  256. ATTRIBUTE-VALUE-SEPARATOR
  257. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  258. POSITIVE-INTEGER))
  259. (define-peg-pattern RATIO-ATTRIBUTE all
  260. (and RATIO-ATTRIBUTE-NAME
  261. ATTRIBUTE-VALUE-SEPARATOR
  262. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  263. (or SIMPLE-POSITIVE-FLOAT-NUMBER
  264. POSITIVE-INTEGER)))
  265. (define-peg-pattern TIMES-ATTRIBUTE all
  266. (and TIMES-ATTRIBUTE-NAME
  267. ATTRIBUTE-VALUE-SEPARATOR
  268. (ignore (* WHITESPACE))
  269. POSITIVE-INTEGER))
  270. (define-peg-pattern RESERVE-ATTRIBUTE all
  271. (and RESERVE-ATTRIBUTE-NAME
  272. ATTRIBUTE-VALUE-SEPARATOR
  273. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  274. POSITIVE-INTEGER))
  275. (define-peg-pattern JOIN-ATTRIBUTE all
  276. (and JOIN-ATTRIBUTE-NAME
  277. ATTRIBUTE-VALUE-SEPARATOR
  278. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  279. POSITIVE-INTEGER))
  280. (define-peg-pattern JOIN-RESERVE-ATTRIBUTE all
  281. (and JOIN-RESERVE-ATTRIBUTE-NAME
  282. ATTRIBUTE-VALUE-SEPARATOR
  283. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  284. POSITIVE-INTEGER))
  285. (define-peg-pattern ACT-ATTRIBUTE all
  286. (and ACT-ATTRIBUTE-NAME
  287. ATTRIBUTE-VALUE-SEPARATOR
  288. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  289. ACT-NUMBER))
  290. (define-peg-pattern GOTO-PHASE-ATTRIBUTE all
  291. (and GOTO-PHASE-ATTRIBUTE-NAME
  292. ATTRIBUTE-VALUE-SEPARATOR
  293. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  294. POSITIVE-INTEGER))
  295. (define-peg-pattern STAGE-ID-ATTRIBUTE all
  296. ID-ATTRIBUTE)
  297. ;; (define-peg-pattern ENTITY-ID-ATTRIBUTE all
  298. ;; ID-ATTRIBUTE)
  299. ;; ==============
  300. ;; COMPOUND PARTS
  301. ;; ==============
  302. (define-peg-pattern COMMENT all
  303. (and COMMENT-STARTER
  304. ;; Ignore whitespace until next content.
  305. (ignore (* WHITESPACE))
  306. COMMENT-TEXT))
  307. (define-peg-pattern ENTITY-COMMENT all
  308. (and COMMENT-STARTER
  309. ENTITY-COMMENT-TEXT))
  310. (define-peg-pattern MUSIC-SWITCH all
  311. MUSIC-ATTRIBUTE)
  312. (define-peg-pattern ENTITY-ATTRIBUTE body
  313. (or ID-ATTRIBUTE
  314. X-COORD-ATTRIBUTE
  315. Y-COORD-ATTRIBUTE
  316. HP-ATTRIBUTE
  317. ACT-ATTRIBUTE
  318. RATIO-ATTRIBUTE
  319. TIMES-ATTRIBUTE
  320. RESERVE-ATTRIBUTE
  321. JOIN-ATTRIBUTE
  322. JOIN-RESERVE-ATTRIBUTE
  323. BOSS-TAG
  324. SOLDIER-TAG
  325. ENTITY-COMMENT))
  326. (define-peg-pattern ENTITY all
  327. (and
  328. ;; ensure, that one opponent only matches until the
  329. ;; end of the line
  330. (not-followed-by "\n")
  331. ;; In any order match all of the possible
  332. ;; attributes. This might technically be slightly
  333. ;; incorrect, because it allows for an attribute to
  334. ;; appear multiple times, but I do not know currently
  335. ;; how to comfortably solve this in a better way,
  336. ;; without creating many variants of opponent
  337. ;; definitions, each specifying an ordered set of
  338. ;; attributes appearing in the original stage.dat
  339. ;; file.
  340. (* (and ENTITY-ATTRIBUTE IGNORED-WHITESPACE-EXCEPT-NEWLINE))))
  341. (define-peg-pattern PHASE-ENTITIES all
  342. ;; NOTE: A phase must contain at least one entity. If (* ...) was used, then
  343. ;; an empty string prefix could be matched at the start of a string, leaving
  344. ;; the rest of the string to be matched later, but still resulting in a match.
  345. (+ (and ENTITY IGNORED-WHITESPACE)))
  346. (define-peg-pattern PHASE all
  347. (and PHASE-TAG
  348. IGNORED-WHITESPACE
  349. BOUND-ATTRIBUTE
  350. IGNORED-WHITESPACE
  351. (? COMMENT)
  352. IGNORED-WHITESPACE
  353. (? MUSIC-SWITCH)
  354. IGNORED-WHITESPACE
  355. PHASE-ENTITIES
  356. IGNORED-WHITESPACE
  357. ;; If there is any goto attribute, it is the last
  358. ;; thing in the phase.
  359. (? GOTO-PHASE-ATTRIBUTE)
  360. IGNORED-WHITESPACE
  361. ;; NOTE: A phase does not eat up trailing whitespace, as such does not
  362. ;; really belong to the phase. If the phase end tag is considered to be a
  363. ;; real end marker, then the phase has no business matching anything
  364. ;; coming after that.
  365. PHASE-END-TAG))
  366. (define-peg-pattern SURVIVAL-STAGE-PHASES all
  367. ;; NOTE: SURVIVAL-STAGE-PHASES is a pattern composing phases and as such takes
  368. ;; care of dropping the irrelevant whitespace between phases.
  369. (+ (and PHASE IGNORED-WHITESPACE)))
  370. (define-peg-pattern SURVIVAL-STAGE all
  371. (and
  372. ;; First match the stage tag ...
  373. STAGE-TAG
  374. ;; ... then delimit survival stage by disallowing another
  375. ;; stage tag to be parsed ...
  376. (not-followed-by STAGE-TAG)
  377. ;; ... then match the rest of the possible parts.
  378. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  379. STAGE-ID-ATTRIBUTE
  380. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  381. (? COMMENT)
  382. IGNORED-WHITESPACE
  383. SURVIVAL-STAGE-PHASES
  384. IGNORED-WHITESPACE))
  385. (define-peg-pattern NORMAL-STAGE all
  386. (and
  387. ;; First match the stage tag ...
  388. STAGE-TAG
  389. ;; ... then delimit stage by disallowing another
  390. ;; stage tag to be parsed ...
  391. (not-followed-by STAGE-TAG)
  392. ;; ... then match the rest of the possible parts.
  393. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  394. STAGE-ID-ATTRIBUTE
  395. IGNORED-WHITESPACE-EXCEPT-NEWLINE
  396. (? COMMENT)
  397. IGNORED-WHITESPACE
  398. SURVIVAL-STAGE-PHASES
  399. IGNORED-WHITESPACE
  400. STAGE-END-TAG))
  401. (define-peg-pattern NORMAL-STAGES all
  402. (+ (and NORMAL-STAGE
  403. IGNORED-WHITESPACE
  404. IGNORED-END-TAG
  405. IGNORED-WHITESPACE)))
  406. (define-peg-pattern STAGE-DAT all
  407. (and SURVIVAL-STAGE
  408. NORMAL-STAGES
  409. IGNORED-WHITESPACE
  410. IGNORED-END-TAG
  411. IGNORED-WHITESPACE))