PageRenderTime 50ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/library/lexical/src/skeleton/yy_interactive_scanner_skeleton.e

http://github.com/gobo-eiffel/gobo
Specman e | 386 lines | 289 code | 15 blank | 82 comment | 28 complexity | d7557d920b073a8f3557d1ebe5c8c0a9 MD5 | raw file
  1. note
  2. description:
  3. "Skeletons of interactive scanners implemented with compressed tables"
  4. library: "Gobo Eiffel Lexical Library"
  5. copyright: "Copyright (c) 2001-2019, Eric Bezault and others"
  6. license: "MIT License"
  7. date: "$Date$"
  8. revision: "$Revision$"
  9. deferred class YY_INTERACTIVE_SCANNER_SKELETON
  10. inherit
  11. YY_COMPRESSED_SCANNER_SKELETON
  12. redefine
  13. make_with_buffer,
  14. set_input_buffer,
  15. read_token
  16. end
  17. feature {NONE} -- Initialization
  18. make_with_buffer (a_buffer: like input_buffer)
  19. -- Create a new scanner with
  20. -- `a_buffer' as input buffer.
  21. do
  22. input_buffer := a_buffer
  23. input_buffer.set_interactive (True)
  24. yy_initialize
  25. yy_load_input_buffer
  26. end
  27. feature -- Scanning
  28. read_token
  29. -- Read a token from `input_buffer'.
  30. -- Make result available in `last_token'.
  31. local
  32. yy_cp, yy_bp: INTEGER
  33. yy_current_state: INTEGER
  34. yy_next_state: INTEGER
  35. yy_matched_count: INTEGER
  36. yy_act: INTEGER
  37. yy_goto: INTEGER
  38. yy_c: INTEGER
  39. yy_code: NATURAL_32
  40. yy_found: BOOLEAN
  41. yy_rejected_line: INTEGER
  42. yy_rejected_column: INTEGER
  43. yy_rejected_position: INTEGER
  44. yy_done: BOOLEAN
  45. l_content_area: like yy_content_area
  46. l_unicode_content_area: like yy_unicode_content_area
  47. do
  48. -- This routine is implemented with a loop whose body
  49. -- is a big inspect instruction. This is a mere
  50. -- translation of C gotos into Eiffel. Needless to
  51. -- say that I'm not very proud of this piece of code.
  52. -- However I performed some benchmarks and the results
  53. -- were that this implementation runs amazingly faster
  54. -- than an alternative implementation with no loop nor
  55. -- inspect instructions and where every branch of the
  56. -- old inspect instruction was written in a separate
  57. -- routine. I think that the performance penalty is due
  58. -- to the routine call overhead and the depth of the call
  59. -- stack. Anyway, I prefer to provide you with a big and
  60. -- ugly but fast scanning routine rather than a nice and
  61. -- slow version. I hope you won't blame me for that! :-)
  62. from
  63. last_token := yyUnknown_token
  64. yy_goto := yyNext_token
  65. until
  66. last_token /= yyUnknown_token
  67. loop
  68. inspect yy_goto
  69. when yyNext_token then
  70. if yy_more_flag then
  71. yy_more_len := yy_end - yy_start
  72. yy_more_flag := False
  73. else
  74. yy_more_len := 0
  75. line := yy_line
  76. column := yy_column
  77. position := yy_position
  78. end
  79. yy_cp := yy_end
  80. -- `yy_bp' is the position of the first
  81. -- character of the current token.
  82. yy_bp := yy_cp
  83. -- Find the start state.
  84. yy_current_state := yy_start_state + yy_at_beginning_of_line
  85. if yyReject_or_variable_trail_context then
  86. -- Set up for storing up states.
  87. SPECIAL_INTEGER_.force (yy_state_stack, yy_current_state, 0)
  88. yy_state_count := 1
  89. end
  90. yy_goto := yyMatch
  91. when yyMatch then
  92. -- Find the next match.
  93. l_content_area := yy_content_area
  94. l_unicode_content_area := yy_unicode_content_area
  95. from
  96. yy_done := False
  97. until
  98. yy_done
  99. loop
  100. if not yyReject_or_variable_trail_context and then yy_accept.item (yy_current_state) /= 0 then
  101. -- Save the backing-up info before computing
  102. -- the next state because we always compute one
  103. -- more state than needed - we always proceed
  104. -- until we reach a jam state.
  105. yy_last_accepting_state := yy_current_state
  106. yy_last_accepting_cpos := yy_cp
  107. end
  108. if l_content_area /= Void then
  109. yy_c := l_content_area.item (yy_cp).code
  110. else
  111. if l_unicode_content_area /= Void then
  112. yy_code := l_unicode_content_area.item (yy_cp).natural_32_code
  113. else
  114. yy_code := yy_content.item_code (yy_cp)
  115. end
  116. if yy_code < {UC_UNICODE_CONSTANTS}.minimum_unicode_surrogate_natural_32_code then
  117. yy_c := yy_code.to_integer_32
  118. elseif yy_code <= {UC_UNICODE_CONSTANTS}.maximum_unicode_surrogate_natural_32_code then
  119. -- Surrogate.
  120. yy_c := -1
  121. elseif yy_code > {UC_UNICODE_CONSTANTS}.maximum_unicode_character_natural_32_code then
  122. -- Invalid Unicode character.
  123. yy_c := -1
  124. else
  125. yy_c := yy_code.to_integer_32
  126. yy_c := yy_c - {UC_UNICODE_CONSTANTS}.unicode_surrogate_count
  127. end
  128. if yy_c > yyMax_symbol_equiv_class then
  129. yy_c := yyMax_symbol_equiv_class
  130. end
  131. end
  132. if yy_c >= 0 then
  133. if attached yy_ec as l_yy_ec then
  134. yy_c := l_yy_ec.item (yy_c)
  135. end
  136. from
  137. until
  138. yy_chk.item (yy_base.item (yy_current_state) + yy_c) = yy_current_state
  139. loop
  140. yy_current_state := yy_def.item (yy_current_state)
  141. if attached yy_meta as l_yy_meta and then yy_current_state >= yyTemplate_mark then
  142. -- We've arranged it so that templates are
  143. -- never chained to one another. This means
  144. -- we can afford to make a very simple test
  145. -- to see if we need to convert to `yy_c''s
  146. -- meta-equivalence class without worrying
  147. -- about erroneously looking up the meta
  148. -- equivalence class twice.
  149. yy_c := l_yy_meta.item (yy_c)
  150. end
  151. end
  152. yy_current_state := yy_nxt.item (yy_base.item (yy_current_state) + yy_c)
  153. else
  154. yy_current_state := yyJam_state
  155. yy_done := True
  156. report_invalid_unicode_character_error (yy_code)
  157. if last_token = yyUnknown_token then
  158. last_token := yyInvalid_character_token
  159. end
  160. end
  161. if yyReject_or_variable_trail_context then
  162. SPECIAL_INTEGER_.force (yy_state_stack, yy_current_state, yy_state_count)
  163. yy_state_count := yy_state_count + 1
  164. end
  165. yy_cp := yy_cp + 1
  166. yy_done := (yy_base.item (yy_current_state) = yyJam_base)
  167. end
  168. yy_goto := yyFind_action
  169. when yyFind_action then
  170. -- Find the action number.
  171. if not yyReject_or_variable_trail_context then
  172. yy_act := yy_accept.item (yy_current_state)
  173. -- Do the garanteed-needed backing up
  174. -- to figure out the match.
  175. if yy_act = 0 then
  176. -- Have to back up.
  177. yy_cp := yy_last_accepting_cpos
  178. yy_current_state := yy_last_accepting_state
  179. yy_act := yy_accept.item (yy_current_state)
  180. end
  181. yy_goto := yyDo_action
  182. else
  183. yy_state_count := yy_state_count - 1
  184. yy_current_state := yy_state_stack.item (yy_state_count)
  185. yy_lp := yy_accept.item (yy_current_state)
  186. yy_goto := yyFind_rule
  187. end
  188. when yyFind_rule then
  189. -- We branch here when backing up.
  190. check
  191. reject_used: yyReject_or_variable_trail_context
  192. yy_acclist_not_void: attached yy_acclist as l_yy_acclist
  193. then
  194. from
  195. yy_found := False
  196. until
  197. yy_found
  198. loop
  199. if yy_lp /= 0 and yy_lp < yy_accept.item (yy_current_state + 1) then
  200. yy_act := l_yy_acclist.item (yy_lp)
  201. if yyVariable_trail_context then
  202. if yy_act < -yyNb_rules or yy_looking_for_trail_begin /= 0 then
  203. if yy_act = yy_looking_for_trail_begin then
  204. yy_looking_for_trail_begin := 0
  205. yy_act := -yy_act - yyNb_rules
  206. yy_found := True
  207. else
  208. yy_lp := yy_lp + 1
  209. end
  210. elseif yy_act < 0 then
  211. yy_looking_for_trail_begin := yy_act - yyNb_rules
  212. if yyReject_used then
  213. -- Remember matched text in case
  214. -- we back up due to `reject'.
  215. yy_full_match := yy_cp
  216. yy_full_state := yy_state_count
  217. yy_full_lp := yy_lp
  218. end
  219. yy_lp := yy_lp + 1
  220. else
  221. yy_full_match := yy_cp
  222. yy_full_state := yy_state_count
  223. yy_full_lp := yy_lp
  224. yy_found := True
  225. end
  226. else
  227. yy_full_match := yy_cp
  228. yy_found := True
  229. end
  230. else
  231. yy_cp := yy_cp - 1
  232. yy_state_count := yy_state_count - 1
  233. yy_current_state := yy_state_stack.item (yy_state_count)
  234. yy_lp := yy_accept.item (yy_current_state)
  235. end
  236. end
  237. yy_rejected_line := yy_line
  238. yy_rejected_column := yy_column
  239. yy_rejected_position := yy_position
  240. yy_goto := yyDo_action
  241. end
  242. when yyDo_action then
  243. -- Set up `text' before action.
  244. yy_bp := yy_bp - yy_more_len
  245. yy_start := yy_bp
  246. yy_end := yy_cp
  247. debug ("GELEX")
  248. end
  249. yy_goto := yyNext_token
  250. -- Semantic actions.
  251. if yy_act = 0 then
  252. -- Must back up.
  253. if not yyReject_or_variable_trail_context then
  254. -- Backing-up info for compressed tables is
  255. -- taken after `yy_cp' has been incremented
  256. -- for the next state.
  257. yy_cp := yy_last_accepting_cpos
  258. yy_bp := yy_bp + yy_more_len
  259. yy_current_state := yy_last_accepting_state
  260. yy_goto := yyFind_action
  261. else
  262. last_token := yyError_token
  263. fatal_error ("fatal scanner internal error: no action found")
  264. end
  265. elseif yy_act = yyEnd_of_buffer then
  266. -- Amount of text matched not including
  267. -- the EOB character.
  268. yy_matched_count := yy_cp - yy_bp - 1
  269. -- Note that here we test for `yy_end' "<="
  270. -- to the position of the first EOB in the buffer,
  271. -- since `yy_end' will already have been
  272. -- incremented past the NULL character (since all
  273. -- states make transitions on EOB to the
  274. -- end-of-buffer state). Contrast this with the
  275. -- test in `read_character'.
  276. if yy_end <= input_buffer.count + 1 then
  277. -- This was really a NULL character.
  278. yy_end := yy_bp + yy_matched_count
  279. yy_current_state := yy_previous_state
  280. -- We're now positioned to make the NULL
  281. -- transition. We couldn't have
  282. -- `yy_previous_state' go ahead and do it
  283. -- for us because it doesn't know how to deal
  284. -- with the possibility of jamming (and we
  285. -- don't want to build jamming into it because
  286. -- then it will run more slowly).
  287. yy_next_state := yy_null_trans_state (yy_current_state)
  288. yy_bp := yy_bp + yy_more_len
  289. if yy_next_state /= 0 then
  290. -- Consume the NULL character.
  291. yy_cp := yy_end + 1
  292. yy_end := yy_cp
  293. yy_current_state := yy_next_state
  294. yy_goto := yyMatch
  295. else
  296. -- Still need to initialize `yy_cp',
  297. -- though `yy_current_state' was set
  298. -- up by `yy_previous_state'.
  299. yy_cp := yy_end
  300. yy_goto := yyFind_action
  301. end
  302. else
  303. -- Do not take the EOB character
  304. -- into account.
  305. yy_end := yy_end - 1
  306. yy_refill_input_buffer
  307. if input_buffer.filled then
  308. yy_current_state := yy_previous_state
  309. yy_cp := yy_end
  310. yy_bp := yy_start + yy_more_len
  311. yy_goto := yyMatch
  312. elseif yy_end - yy_start - yy_more_len /= 0 then
  313. -- Some text has been matched prior to
  314. -- the EOB. First process it.
  315. yy_current_state := yy_previous_state
  316. yy_cp := yy_end
  317. yy_bp := yy_start + yy_more_len
  318. yy_goto := yyFind_action
  319. else
  320. -- Only the EOB character has been matched,
  321. -- so treat this as a final EOF.
  322. if wrap then
  323. yy_bp := yy_start
  324. yy_cp := yy_end
  325. yy_execute_eof_action ((yy_start_state - 1) // 2)
  326. end
  327. end
  328. end
  329. else
  330. yy_execute_action (yy_act)
  331. if yy_rejected then
  332. yy_rejected := False
  333. yy_line := yy_rejected_line
  334. yy_column := yy_rejected_column
  335. yy_position := yy_rejected_position
  336. -- Restore position backed-over text.
  337. yy_cp := yy_full_match
  338. if yyVariable_trail_context then
  339. -- Restore original accepting position.
  340. yy_lp := yy_full_lp
  341. -- Restore original state.
  342. yy_state_count := yy_full_state
  343. -- Restore current state.
  344. yy_current_state := yy_state_stack.item (yy_state_count - 1)
  345. end
  346. yy_lp := yy_lp + 1
  347. yy_goto := yyFind_rule
  348. end
  349. end
  350. end
  351. end
  352. debug ("GELEX")
  353. print_last_token
  354. end
  355. end
  356. feature -- Input
  357. set_input_buffer (a_buffer: like input_buffer)
  358. -- Set `input_buffer' to `a_buffer'.
  359. do
  360. if a_buffer /= input_buffer then
  361. -- Flush out information for old buffer.
  362. input_buffer.set_index (yy_end)
  363. input_buffer.set_position (yy_position, yy_line, yy_column)
  364. input_buffer := a_buffer
  365. input_buffer.set_interactive (True)
  366. yy_load_input_buffer
  367. end
  368. end
  369. invariant
  370. interactive_buffer: input_buffer.interactive
  371. end