Advertisement
Kep13

LuaX

Dec 21st, 2020
24
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.06 KB | None | 0 0
  1. --[[--------------------------------------------------------------------
  2.  
  3. llex.lua
  4. Lua lexical analyzer in Lua
  5. This file is part of Yueliang.
  6.  
  7. Copyright (c) 2005-2006 Kein-Hong Man <khman@users.sf.net>
  8. The COPYRIGHT file describes the conditions
  9. under which this software may be distributed.
  10.  
  11. See the ChangeLog for more information.
  12.  
  13. ----------------------------------------------------------------------]]
  14.  
  15. --[[--------------------------------------------------------------------
  16. -- Notes:
  17. -- * intended to 'imitate' llex.c code; performance is not a concern
  18. -- * tokens are strings; code structure largely retained
  19. -- * deleted stuff (compared to llex.c) are noted, comments retained
  20. -- * nextc() returns the currently read character to simplify coding
  21. -- here; next() in llex.c does not return anything
  22. -- * compatibility code is marked with "--#" comments
  23. --
  24. -- Added:
  25. -- * luaX:chunkid (function luaO_chunkid from lobject.c)
  26. -- * luaX:str2d (function luaO_str2d from lobject.c)
  27. -- * luaX.LUA_QS used in luaX:lexerror (from luaconf.h)
  28. -- * luaX.LUA_COMPAT_LSTR in luaX:read_long_string (from luaconf.h)
  29. -- * luaX.MAX_INT used in luaX:inclinenumber (from llimits.h)
  30. --
  31. -- To use the lexer:
  32. -- (1) luaX:init() to initialize the lexer
  33. -- (2) luaX:setinput() to set the input stream to lex
  34. -- (3) call luaX:next() or luaX:luaX:lookahead() to get tokens,
  35. -- until "TK_EOS": luaX:next()
  36. -- * since EOZ is returned as a string, be careful when regexp testing
  37. --
  38. -- Not implemented:
  39. -- * luaX_newstring: not required by this Lua implementation
  40. -- * buffer MAX_SIZET size limit (from llimits.h) test not implemented
  41. -- in the interest of performance
  42. -- * locale-aware number handling is largely redundant as Lua's
  43. -- tonumber() function is already capable of this
  44. --
  45. -- Changed in 5.1.x:
  46. -- * TK_NAME token order moved down
  47. -- * string representation for TK_NAME, TK_NUMBER, TK_STRING changed
  48. -- * token struct renamed to lower case (LS -> ls)
  49. -- * LexState struct: removed nestlevel, added decpoint
  50. -- * error message functions have been greatly simplified
  51. -- * token2string renamed to luaX_tokens, exposed in llex.h
  52. -- * lexer now handles all kinds of newlines, including CRLF
  53. -- * shbang first line handling removed from luaX:setinput;
  54. -- it is now done in lauxlib.c (luaL_loadfile)
  55. -- * next(ls) macro renamed to nextc(ls) due to new luaX_next function
  56. -- * EXTRABUFF and MAXNOCHECK removed due to lexer changes
  57. -- * checkbuffer(ls, len) macro deleted
  58. -- * luaX:read_numeral now has 3 support functions: luaX:trydecpoint,
  59. -- luaX:buffreplace and (luaO_str2d from lobject.c) luaX:str2d
  60. -- * luaX:read_numeral is now more promiscuous in slurping characters;
  61. -- hexadecimal numbers was added, locale-aware decimal points too
  62. -- * luaX:skip_sep is new; used by luaX:read_long_string
  63. -- * luaX:read_long_string handles new-style long blocks, with some
  64. -- optional compatibility code
  65. -- * luaX:llex: parts changed to support new-style long blocks
  66. -- * luaX:llex: readname functionality has been folded in
  67. -- * luaX:llex: removed test for control characters
  68. --
  69. --------------------------------------------------------------------]]
  70.  
  71. local luaZ = require(script.Parent.LuaZ)
  72.  
  73. local luaX = {}
  74.  
  75. -- FIRST_RESERVED is not required as tokens are manipulated as strings
  76. -- TOKEN_LEN deleted; maximum length of a reserved word not needed
  77.  
  78. ------------------------------------------------------------------------
  79. -- "ORDER RESERVED" deleted; enumeration in one place: luaX.RESERVED
  80. ------------------------------------------------------------------------
  81.  
  82. -- terminal symbols denoted by reserved words: TK_AND to TK_WHILE
  83. -- other terminal symbols: TK_NAME to TK_EOS
  84. luaX.RESERVED = [[
  85. TK_AND and
  86. TK_BREAK break
  87. TK_DO do
  88. TK_ELSE else
  89. TK_ELSEIF elseif
  90. TK_END end
  91. TK_FALSE false
  92. TK_FOR for
  93. TK_FUNCTION function
  94. TK_IF if
  95. TK_IN in
  96. TK_LOCAL local
  97. TK_NIL nil
  98. TK_NOT not
  99. TK_OR or
  100. TK_REPEAT repeat
  101. TK_RETURN return
  102. TK_THEN then
  103. TK_TRUE true
  104. TK_UNTIL until
  105. TK_WHILE while
  106. TK_CONCAT ..
  107. TK_DOTS ...
  108. TK_EQ ==
  109. TK_GE >=
  110. TK_LE <=
  111. TK_NE ~=
  112. TK_NAME <name>
  113. TK_NUMBER <number>
  114. TK_STRING <string>
  115. TK_EOS <eof>]]
  116.  
  117. -- NUM_RESERVED is not required; number of reserved words
  118.  
  119. --[[--------------------------------------------------------------------
  120. -- Instead of passing seminfo, the Token struct (e.g. ls.t) is passed
  121. -- so that lexer functions can use its table element, ls.t.seminfo
  122. --
  123. -- SemInfo (struct no longer needed, a mixed-type value is used)
  124. --
  125. -- Token (struct of ls.t and ls.lookahead):
  126. -- token -- token symbol
  127. -- seminfo -- semantics information
  128. --
  129. -- LexState (struct of ls; ls is initialized by luaX:setinput):
  130. -- current -- current character (charint)
  131. -- linenumber -- input line counter
  132. -- lastline -- line of last token 'consumed'
  133. -- t -- current token (table: struct Token)
  134. -- lookahead -- look ahead token (table: struct Token)
  135. -- fs -- 'FuncState' is private to the parser
  136. -- L -- LuaState
  137. -- z -- input stream
  138. -- buff -- buffer for tokens
  139. -- source -- current source name
  140. -- decpoint -- locale decimal point
  141. -- nestlevel -- level of nested non-terminals
  142. ----------------------------------------------------------------------]]
  143.  
  144. -- luaX.tokens (was luaX_tokens) is now a hash; see luaX:init
  145.  
  146. luaX.MAXSRC = 80
  147. luaX.MAX_INT = 2147483645 -- constants from elsewhere (see above)
  148. luaX.LUA_QS = "'%s'"
  149. luaX.LUA_COMPAT_LSTR = 1
  150. --luaX.MAX_SIZET = 4294967293
  151.  
  152. ------------------------------------------------------------------------
  153. -- initialize lexer
  154. -- * original luaX_init has code to create and register token strings
  155. -- * luaX.tokens: TK_* -> token
  156. -- * luaX.enums: token -> TK_* (used in luaX:llex)
  157. ------------------------------------------------------------------------
  158. function luaX:init()
  159. local tokens, enums = {}, {}
  160. for v in string.gmatch(self.RESERVED, "[^\n]+") do
  161. local _, _, tok, str = string.find(v, "(%S+)%s+(%S+)")
  162. tokens[tok] = str
  163. enums[str] = tok
  164. end
  165. self.tokens = tokens
  166. self.enums = enums
  167. end
  168.  
  169. ------------------------------------------------------------------------
  170. -- returns a suitably-formatted chunk name or id
  171. -- * from lobject.c, used in llex.c and ldebug.c
  172. -- * the result, out, is returned (was first argument)
  173. ------------------------------------------------------------------------
  174. function luaX:chunkid(source, bufflen)
  175. local out
  176. local first = string.sub(source, 1, 1)
  177. if first == "=" then
  178. out = string.sub(source, 2, bufflen) -- remove first char
  179. else -- out = "source", or "...source"
  180. if first == "@" then
  181. source = string.sub(source, 2) -- skip the '@'
  182. bufflen = bufflen - #" '...' "
  183. local l = #source
  184. out = ""
  185. if l > bufflen then
  186. source = string.sub(source, 1 + l - bufflen) -- get last part of file name
  187. out = out.."..."
  188. end
  189. out = out..source
  190. else -- out = [string "string"]
  191. local len = string.find(source, "[\n\r]") -- stop at first newline
  192. len = len and (len - 1) or #source
  193. bufflen = bufflen - #(" [string \"...\"] ")
  194. if len > bufflen then len = bufflen end
  195. out = "[string \""
  196. if len < #source then -- must truncate?
  197. out = out..string.sub(source, 1, len).."..."
  198. else
  199. out = out..source
  200. end
  201. out = out.."\"]"
  202. end
  203. end
  204. return out
  205. end
  206.  
  207. --[[--------------------------------------------------------------------
  208. -- Support functions for lexer
  209. -- * all lexer errors eventually reaches lexerror:
  210. syntaxerror -> lexerror
  211. ----------------------------------------------------------------------]]
  212.  
  213. ------------------------------------------------------------------------
  214. -- look up token and return keyword if found (also called by parser)
  215. ------------------------------------------------------------------------
  216. function luaX:token2str(ls, token)
  217. if string.sub(token, 1, 3) ~= "TK_" then
  218. if string.find(token, "%c") then
  219. return string.format("char(%d)", string.byte(token))
  220. end
  221. return token
  222. else
  223. end
  224. return self.tokens[token]
  225. end
  226.  
  227. ------------------------------------------------------------------------
  228. -- throws a lexer error
  229. -- * txtToken has been made local to luaX:lexerror
  230. -- * can't communicate LUA_ERRSYNTAX, so it is unimplemented
  231. ------------------------------------------------------------------------
  232. function luaX:lexerror(ls, msg, token)
  233. local function txtToken(ls, token)
  234. if token == "TK_NAME" or
  235. token == "TK_STRING" or
  236. token == "TK_NUMBER" then
  237. return ls.buff
  238. else
  239. return self:token2str(ls, token)
  240. end
  241. end
  242. local buff = self:chunkid(ls.source, self.MAXSRC)
  243. local msg = string.format("%s:%d: %s", buff, ls.linenumber, msg)
  244. if token then
  245. msg = string.format("%s near "..self.LUA_QS, msg, txtToken(ls, token))
  246. end
  247. -- luaD_throw(ls->L, LUA_ERRSYNTAX)
  248. error(msg)
  249. end
  250.  
  251. ------------------------------------------------------------------------
  252. -- throws a syntax error (mainly called by parser)
  253. -- * ls.t.token has to be set by the function calling luaX:llex
  254. -- (see luaX:next and luaX:lookahead elsewhere in this file)
  255. ------------------------------------------------------------------------
  256. function luaX:syntaxerror(ls, msg)
  257. self:lexerror(ls, msg, ls.t.token)
  258. end
  259.  
  260. ------------------------------------------------------------------------
  261. -- move on to next line
  262. ------------------------------------------------------------------------
  263. function luaX:currIsNewline(ls)
  264. return ls.current == "\n" or ls.current == "\r"
  265. end
  266.  
  267. function luaX:inclinenumber(ls)
  268. local old = ls.current
  269. -- lua_assert(currIsNewline(ls))
  270. self:nextc(ls) -- skip '\n' or '\r'
  271. if self:currIsNewline(ls) and ls.current ~= old then
  272. self:nextc(ls) -- skip '\n\r' or '\r\n'
  273. end
  274. ls.linenumber = ls.linenumber + 1
  275. if ls.linenumber >= self.MAX_INT then
  276. self:syntaxerror(ls, "chunk has too many lines")
  277. end
  278. end
  279.  
  280. ------------------------------------------------------------------------
  281. -- initializes an input stream for lexing
  282. -- * if ls (the lexer state) is passed as a table, then it is filled in,
  283. -- otherwise it has to be retrieved as a return value
  284. -- * LUA_MINBUFFER not used; buffer handling not required any more
  285. ------------------------------------------------------------------------
  286. function luaX:setinput(L, ls, z, source)
  287. if not ls then ls = {} end -- create struct
  288. if not ls.lookahead then ls.lookahead = {} end
  289. if not ls.t then ls.t = {} end
  290. ls.decpoint = "."
  291. ls.L = L
  292. ls.lookahead.token = "TK_EOS" -- no look-ahead token
  293. ls.z = z
  294. ls.fs = nil
  295. ls.linenumber = 1
  296. ls.lastline = 1
  297. ls.source = source
  298. self:nextc(ls) -- read first char
  299. end
  300.  
  301. --[[--------------------------------------------------------------------
  302. -- LEXICAL ANALYZER
  303. ----------------------------------------------------------------------]]
  304.  
  305. ------------------------------------------------------------------------
  306. -- checks if current character read is found in the set 'set'
  307. ------------------------------------------------------------------------
  308. function luaX:check_next(ls, set)
  309. if not string.find(set, ls.current, 1, 1) then
  310. return false
  311. end
  312. self:save_and_next(ls)
  313. return true
  314. end
  315.  
  316. ------------------------------------------------------------------------
  317. -- retrieve next token, checking the lookahead buffer if necessary
  318. -- * note that the macro next(ls) in llex.c is now luaX:nextc
  319. -- * utilized used in lparser.c (various places)
  320. ------------------------------------------------------------------------
  321. function luaX:next(ls)
  322. ls.lastline = ls.linenumber
  323. if ls.lookahead.token ~= "TK_EOS" then -- is there a look-ahead token?
  324. -- this must be copy-by-value
  325. ls.t.seminfo = ls.lookahead.seminfo -- use this one
  326. ls.t.token = ls.lookahead.token
  327. ls.lookahead.token = "TK_EOS" -- and discharge it
  328. else
  329. ls.t.token = self:llex(ls, ls.t) -- read next token
  330. end
  331. end
  332.  
  333. ------------------------------------------------------------------------
  334. -- fill in the lookahead buffer
  335. -- * utilized used in lparser.c:constructor
  336. ------------------------------------------------------------------------
  337. function luaX:lookahead(ls)
  338. -- lua_assert(ls.lookahead.token == "TK_EOS")
  339. ls.lookahead.token = self:llex(ls, ls.lookahead)
  340. end
  341.  
  342. ------------------------------------------------------------------------
  343. -- gets the next character and returns it
  344. -- * this is the next() macro in llex.c; see notes at the beginning
  345. ------------------------------------------------------------------------
  346. function luaX:nextc(ls)
  347. local c = luaZ:zgetc(ls.z)
  348. ls.current = c
  349. return c
  350. end
  351.  
  352. ------------------------------------------------------------------------
  353. -- saves the given character into the token buffer
  354. -- * buffer handling code removed, not used in this implementation
  355. -- * test for maximum token buffer length not used, makes things faster
  356. ------------------------------------------------------------------------
  357.  
  358. function luaX:save(ls, c)
  359. local buff = ls.buff
  360. -- if you want to use this, please uncomment luaX.MAX_SIZET further up
  361. --if #buff > self.MAX_SIZET then
  362. -- self:lexerror(ls, "lexical element too long")
  363. --end
  364. ls.buff = buff..c
  365. end
  366.  
  367. ------------------------------------------------------------------------
  368. -- save current character into token buffer, grabs next character
  369. -- * like luaX:nextc, returns the character read for convenience
  370. ------------------------------------------------------------------------
  371. function luaX:save_and_next(ls)
  372. self:save(ls, ls.current)
  373. return self:nextc(ls)
  374. end
  375.  
  376. ------------------------------------------------------------------------
  377. -- LUA_NUMBER
  378. -- * luaX:read_numeral is the main lexer function to read a number
  379. -- * luaX:str2d, luaX:buffreplace, luaX:trydecpoint are support functions
  380. ------------------------------------------------------------------------
  381.  
  382. ------------------------------------------------------------------------
  383. -- string to number converter (was luaO_str2d from lobject.c)
  384. -- * returns the number, nil if fails (originally returns a boolean)
  385. -- * conversion function originally lua_str2number(s,p), a macro which
  386. -- maps to the strtod() function by default (from luaconf.h)
  387. ------------------------------------------------------------------------
  388. function luaX:str2d(s)
  389. local result = tonumber(s)
  390. if result then return result end
  391. -- conversion failed
  392. if string.lower(string.sub(s, 1, 2)) == "0x" then -- maybe an hexadecimal constant?
  393. result = tonumber(s, 16)
  394. if result then return result end -- most common case
  395. -- Was: invalid trailing characters?
  396. -- In C, this function then skips over trailing spaces.
  397. -- true is returned if nothing else is found except for spaces.
  398. -- If there is still something else, then it returns a false.
  399. -- All this is not necessary using Lua's tonumber.
  400. end
  401. return nil
  402. end
  403.  
  404. ------------------------------------------------------------------------
  405. -- single-character replacement, for locale-aware decimal points
  406. ------------------------------------------------------------------------
  407. function luaX:buffreplace(ls, from, to)
  408. local result, buff = "", ls.buff
  409. for p = 1, #buff do
  410. local c = string.sub(buff, p, p)
  411. if c == from then c = to end
  412. result = result..c
  413. end
  414. ls.buff = result
  415. end
  416.  
  417. ------------------------------------------------------------------------
  418. -- Attempt to convert a number by translating '.' decimal points to
  419. -- the decimal point character used by the current locale. This is not
  420. -- needed in Yueliang as Lua's tonumber() is already locale-aware.
  421. -- Instead, the code is here in case the user implements localeconv().
  422. ------------------------------------------------------------------------
  423. function luaX:trydecpoint(ls, Token)
  424. -- format error: try to update decimal point separator
  425. local old = ls.decpoint
  426. -- translate the following to Lua if you implement localeconv():
  427. -- struct lconv *cv = localeconv();
  428. -- ls->decpoint = (cv ? cv->decimal_point[0] : '.');
  429. self:buffreplace(ls, old, ls.decpoint) -- try updated decimal separator
  430. local seminfo = self:str2d(ls.buff)
  431. Token.seminfo = seminfo
  432. if not seminfo then
  433. -- format error with correct decimal point: no more options
  434. self:buffreplace(ls, ls.decpoint, ".") -- undo change (for error message)
  435. self:lexerror(ls, "malformed number", "TK_NUMBER")
  436. end
  437. end
  438.  
  439. ------------------------------------------------------------------------
  440. -- main number conversion function
  441. -- * "^%w$" needed in the scan in order to detect "EOZ"
  442. ------------------------------------------------------------------------
  443. function luaX:read_numeral(ls, Token)
  444. -- lua_assert(string.find(ls.current, "%d"))
  445. repeat
  446. self:save_and_next(ls)
  447. until string.find(ls.current, "%D") and ls.current ~= "."
  448. if self:check_next(ls, "Ee") then -- 'E'?
  449. self:check_next(ls, "+-") -- optional exponent sign
  450. end
  451. while string.find(ls.current, "^%w$") or ls.current == "_" do
  452. self:save_and_next(ls)
  453. end
  454. self:buffreplace(ls, ".", ls.decpoint) -- follow locale for decimal point
  455. local seminfo = self:str2d(ls.buff)
  456. Token.seminfo = seminfo
  457. if not seminfo then -- format error?
  458. self:trydecpoint(ls, Token) -- try to update decimal point separator
  459. end
  460. end
  461.  
  462. ------------------------------------------------------------------------
  463. -- count separators ("=") in a long string delimiter
  464. -- * used by luaX:read_long_string
  465. ------------------------------------------------------------------------
  466. function luaX:skip_sep(ls)
  467. local count = 0
  468. local s = ls.current
  469. -- lua_assert(s == "[" or s == "]")
  470. self:save_and_next(ls)
  471. while ls.current == "=" do
  472. self:save_and_next(ls)
  473. count = count + 1
  474. end
  475. return (ls.current == s) and count or (-count) - 1
  476. end
  477.  
  478. ------------------------------------------------------------------------
  479. -- reads a long string or long comment
  480. ------------------------------------------------------------------------
  481. function luaX:read_long_string(ls, Token, sep)
  482. local cont = 0
  483. self:save_and_next(ls) -- skip 2nd '['
  484. if self:currIsNewline(ls) then -- string starts with a newline?
  485. self:inclinenumber(ls) -- skip it
  486. end
  487. while true do
  488. local c = ls.current
  489. if c == "EOZ" then
  490. self:lexerror(ls, Token and "unfinished long string" or
  491. "unfinished long comment", "TK_EOS")
  492. elseif c == "[" then
  493. --# compatibility code start
  494. if self.LUA_COMPAT_LSTR then
  495. if self:skip_sep(ls) == sep then
  496. self:save_and_next(ls) -- skip 2nd '['
  497. cont = cont + 1
  498. --# compatibility code start
  499. if self.LUA_COMPAT_LSTR == 1 then
  500. if sep == 0 then
  501. self:lexerror(ls, "nesting of [[...]] is deprecated", "[")
  502. end
  503. end
  504. --# compatibility code end
  505. end
  506. end
  507. --# compatibility code end
  508. elseif c == "]" then
  509. if self:skip_sep(ls) == sep then
  510. self:save_and_next(ls) -- skip 2nd ']'
  511. --# compatibility code start
  512. if self.LUA_COMPAT_LSTR and self.LUA_COMPAT_LSTR == 2 then
  513. cont = cont - 1
  514. if sep == 0 and cont >= 0 then break end
  515. end
  516. --# compatibility code end
  517. break
  518. end
  519. elseif self:currIsNewline(ls) then
  520. self:save(ls, "\n")
  521. self:inclinenumber(ls)
  522. if not Token then ls.buff = "" end -- avoid wasting space
  523. else -- default
  524. if Token then
  525. self:save_and_next(ls)
  526. else
  527. self:nextc(ls)
  528. end
  529. end--if c
  530. end--while
  531. if Token then
  532. local p = 3 + sep
  533. Token.seminfo = string.sub(ls.buff, p, -p)
  534. end
  535. end
  536.  
  537. ------------------------------------------------------------------------
  538. -- reads a string
  539. -- * has been restructured significantly compared to the original C code
  540. ------------------------------------------------------------------------
  541.  
  542. function luaX:read_string(ls, del, Token)
  543. self:save_and_next(ls)
  544. while ls.current ~= del do
  545. local c = ls.current
  546. if c == "EOZ" then
  547. self:lexerror(ls, "unfinished string", "TK_EOS")
  548. elseif self:currIsNewline(ls) then
  549. self:lexerror(ls, "unfinished string", "TK_STRING")
  550. elseif c == "\\" then
  551. c = self:nextc(ls) -- do not save the '\'
  552. if self:currIsNewline(ls) then -- go through
  553. self:save(ls, "\n")
  554. self:inclinenumber(ls)
  555. elseif c ~= "EOZ" then -- will raise an error next loop
  556. -- escapes handling greatly simplified here:
  557. local i = string.find("abfnrtv", c, 1, 1)
  558. if i then
  559. self:save(ls, string.sub("\a\b\f\n\r\t\v", i, i))
  560. self:nextc(ls)
  561. elseif not string.find(c, "%d") then
  562. self:save_and_next(ls) -- handles \\, \", \', and \?
  563. else -- \xxx
  564. c, i = 0, 0
  565. repeat
  566. c = 10 * c + ls.current
  567. self:nextc(ls)
  568. i = i + 1
  569. until i >= 3 or not string.find(ls.current, "%d")
  570. if c > 255 then -- UCHAR_MAX
  571. self:lexerror(ls, "escape sequence too large", "TK_STRING")
  572. end
  573. self:save(ls, string.char(c))
  574. end
  575. end
  576. else
  577. self:save_and_next(ls)
  578. end--if c
  579. end--while
  580. self:save_and_next(ls) -- skip delimiter
  581. Token.seminfo = string.sub(ls.buff, 2, -2)
  582. end
  583.  
  584. ------------------------------------------------------------------------
  585. -- main lexer function
  586. ------------------------------------------------------------------------
  587. function luaX:llex(ls, Token)
  588. ls.buff = ""
  589. while true do
  590. local c = ls.current
  591. ----------------------------------------------------------------
  592. if self:currIsNewline(ls) then
  593. self:inclinenumber(ls)
  594. ----------------------------------------------------------------
  595. elseif c == "-" then
  596. c = self:nextc(ls)
  597. if c ~= "-" then return "-" end
  598. -- else is a comment
  599. local sep = -1
  600. if self:nextc(ls) == '[' then
  601. sep = self:skip_sep(ls)
  602. ls.buff = "" -- 'skip_sep' may dirty the buffer
  603. end
  604. if sep >= 0 then
  605. self:read_long_string(ls, nil, sep) -- long comment
  606. ls.buff = ""
  607. else -- else short comment
  608. while not self:currIsNewline(ls) and ls.current ~= "EOZ" do
  609. self:nextc(ls)
  610. end
  611. end
  612. ----------------------------------------------------------------
  613. elseif c == "[" then
  614. local sep = self:skip_sep(ls)
  615. if sep >= 0 then
  616. self:read_long_string(ls, Token, sep)
  617. return "TK_STRING"
  618. elseif sep == -1 then
  619. return "["
  620. else
  621. self:lexerror(ls, "invalid long string delimiter", "TK_STRING")
  622. end
  623. ----------------------------------------------------------------
  624. elseif c == "=" then
  625. c = self:nextc(ls)
  626. if c ~= "=" then return "="
  627. else self:nextc(ls); return "TK_EQ" end
  628. ----------------------------------------------------------------
  629. elseif c == "<" then
  630. c = self:nextc(ls)
  631. if c ~= "=" then return "<"
  632. else self:nextc(ls); return "TK_LE" end
  633. ----------------------------------------------------------------
  634. elseif c == ">" then
  635. c = self:nextc(ls)
  636. if c ~= "=" then return ">"
  637. else self:nextc(ls); return "TK_GE" end
  638. ----------------------------------------------------------------
  639. elseif c == "~" then
  640. c = self:nextc(ls)
  641. if c ~= "=" then return "~"
  642. else self:nextc(ls); return "TK_NE" end
  643. ----------------------------------------------------------------
  644. elseif c == "\"" or c == "'" then
  645. self:read_string(ls, c, Token)
  646. return "TK_STRING"
  647. ----------------------------------------------------------------
  648. elseif c == "." then
  649. c = self:save_and_next(ls)
  650. if self:check_next(ls, ".") then
  651. if self:check_next(ls, ".") then
  652. return "TK_DOTS" -- ...
  653. else return "TK_CONCAT" -- ..
  654. end
  655. elseif not string.find(c, "%d") then
  656. return "."
  657. else
  658. self:read_numeral(ls, Token)
  659. return "TK_NUMBER"
  660. end
  661. ----------------------------------------------------------------
  662. elseif c == "EOZ" then
  663. return "TK_EOS"
  664. ----------------------------------------------------------------
  665. else -- default
  666. if string.find(c, "%s") then
  667. -- lua_assert(self:currIsNewline(ls))
  668. self:nextc(ls)
  669. elseif string.find(c, "%d") then
  670. self:read_numeral(ls, Token)
  671. return "TK_NUMBER"
  672. elseif string.find(c, "[_%a]") then
  673. -- identifier or reserved word
  674. repeat
  675. c = self:save_and_next(ls)
  676. until c == "EOZ" or not string.find(c, "[_%w]")
  677. local ts = ls.buff
  678. local tok = self.enums[ts]
  679. if tok then return tok end -- reserved word?
  680. Token.seminfo = ts
  681. return "TK_NAME"
  682. else
  683. self:nextc(ls)
  684. return c -- single-char tokens (+ - / ...)
  685. end
  686. ----------------------------------------------------------------
  687. end--if c
  688. end--while
  689. end
  690.  
  691. return luaX
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement