lexer_spec.lua 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. local helpers = require('test.unit.helpers')(after_each)
  2. local itp = helpers.gen_itp(it)
  3. local viml_helpers = require('test.unit.viml.helpers')
  4. local child_call_once = helpers.child_call_once
  5. local conv_enum = helpers.conv_enum
  6. local cimport = helpers.cimport
  7. local ffi = helpers.ffi
  8. local eq = helpers.eq
  9. local shallowcopy = helpers.shallowcopy
  10. local intchar2lua = helpers.intchar2lua
  11. local conv_ccs = viml_helpers.conv_ccs
  12. local new_pstate = viml_helpers.new_pstate
  13. local conv_cmp_type = viml_helpers.conv_cmp_type
  14. local pstate_set_str = viml_helpers.pstate_set_str
  15. local conv_expr_asgn_type = viml_helpers.conv_expr_asgn_type
  16. local lib = cimport('./src/nvim/viml/parser/expressions.h')
  17. local eltkn_type_tab, eltkn_mul_type_tab, eltkn_opt_scope_tab
  18. child_call_once(function()
  19. eltkn_type_tab = {
  20. [tonumber(lib.kExprLexInvalid)] = 'Invalid',
  21. [tonumber(lib.kExprLexMissing)] = 'Missing',
  22. [tonumber(lib.kExprLexSpacing)] = 'Spacing',
  23. [tonumber(lib.kExprLexEOC)] = 'EOC',
  24. [tonumber(lib.kExprLexQuestion)] = 'Question',
  25. [tonumber(lib.kExprLexColon)] = 'Colon',
  26. [tonumber(lib.kExprLexOr)] = 'Or',
  27. [tonumber(lib.kExprLexAnd)] = 'And',
  28. [tonumber(lib.kExprLexComparison)] = 'Comparison',
  29. [tonumber(lib.kExprLexPlus)] = 'Plus',
  30. [tonumber(lib.kExprLexMinus)] = 'Minus',
  31. [tonumber(lib.kExprLexDot)] = 'Dot',
  32. [tonumber(lib.kExprLexMultiplication)] = 'Multiplication',
  33. [tonumber(lib.kExprLexNot)] = 'Not',
  34. [tonumber(lib.kExprLexNumber)] = 'Number',
  35. [tonumber(lib.kExprLexSingleQuotedString)] = 'SingleQuotedString',
  36. [tonumber(lib.kExprLexDoubleQuotedString)] = 'DoubleQuotedString',
  37. [tonumber(lib.kExprLexOption)] = 'Option',
  38. [tonumber(lib.kExprLexRegister)] = 'Register',
  39. [tonumber(lib.kExprLexEnv)] = 'Env',
  40. [tonumber(lib.kExprLexPlainIdentifier)] = 'PlainIdentifier',
  41. [tonumber(lib.kExprLexBracket)] = 'Bracket',
  42. [tonumber(lib.kExprLexFigureBrace)] = 'FigureBrace',
  43. [tonumber(lib.kExprLexParenthesis)] = 'Parenthesis',
  44. [tonumber(lib.kExprLexComma)] = 'Comma',
  45. [tonumber(lib.kExprLexArrow)] = 'Arrow',
  46. [tonumber(lib.kExprLexAssignment)] = 'Assignment',
  47. }
  48. eltkn_mul_type_tab = {
  49. [tonumber(lib.kExprLexMulMul)] = 'Mul',
  50. [tonumber(lib.kExprLexMulDiv)] = 'Div',
  51. [tonumber(lib.kExprLexMulMod)] = 'Mod',
  52. }
  53. eltkn_opt_scope_tab = {
  54. [tonumber(lib.kExprOptScopeUnspecified)] = 'Unspecified',
  55. [tonumber(lib.kExprOptScopeGlobal)] = 'Global',
  56. [tonumber(lib.kExprOptScopeLocal)] = 'Local',
  57. }
  58. end)
  59. local function conv_eltkn_type(typ)
  60. return conv_enum(eltkn_type_tab, typ)
  61. end
  62. local bracket_types = {
  63. Bracket = true,
  64. FigureBrace = true,
  65. Parenthesis = true,
  66. }
  67. local function eltkn2lua(pstate, tkn)
  68. local ret = {
  69. type = conv_eltkn_type(tkn.type),
  70. }
  71. pstate_set_str(pstate, tkn.start, tkn.len, ret)
  72. if not ret.error and (#(ret.str) ~= ret.len) then
  73. ret.error = '#str /= len'
  74. end
  75. if ret.type == 'Comparison' then
  76. ret.data = {
  77. type = conv_cmp_type(tkn.data.cmp.type),
  78. ccs = conv_ccs(tkn.data.cmp.ccs),
  79. inv = (not not tkn.data.cmp.inv),
  80. }
  81. elseif ret.type == 'Multiplication' then
  82. ret.data = { type = conv_enum(eltkn_mul_type_tab, tkn.data.mul.type) }
  83. elseif bracket_types[ret.type] then
  84. ret.data = { closing = (not not tkn.data.brc.closing) }
  85. elseif ret.type == 'Register' then
  86. ret.data = { name = intchar2lua(tkn.data.reg.name) }
  87. elseif (ret.type == 'SingleQuotedString'
  88. or ret.type == 'DoubleQuotedString') then
  89. ret.data = { closed = (not not tkn.data.str.closed) }
  90. elseif ret.type == 'Option' then
  91. ret.data = {
  92. scope = conv_enum(eltkn_opt_scope_tab, tkn.data.opt.scope),
  93. name = ffi.string(tkn.data.opt.name, tkn.data.opt.len),
  94. }
  95. elseif ret.type == 'PlainIdentifier' then
  96. ret.data = {
  97. scope = intchar2lua(tkn.data.var.scope),
  98. autoload = (not not tkn.data.var.autoload),
  99. }
  100. elseif ret.type == 'Number' then
  101. ret.data = {
  102. is_float = (not not tkn.data.num.is_float),
  103. base = tonumber(tkn.data.num.base),
  104. }
  105. ret.data.val = tonumber(tkn.data.num.is_float
  106. and tkn.data.num.val.floating
  107. or tkn.data.num.val.integer)
  108. elseif ret.type == 'Assignment' then
  109. ret.data = { type = conv_expr_asgn_type(tkn.data.ass.type) }
  110. elseif ret.type == 'Invalid' then
  111. ret.data = { error = ffi.string(tkn.data.err.msg) }
  112. end
  113. return ret, tkn
  114. end
  115. local function next_eltkn(pstate, flags)
  116. return eltkn2lua(pstate, lib.viml_pexpr_next_token(pstate, flags))
  117. end
  118. describe('Expressions lexer', function()
  119. local flags = 0
  120. local should_advance = true
  121. local function check_advance(pstate, bytes_to_advance, initial_col)
  122. local tgt = initial_col + bytes_to_advance
  123. if should_advance then
  124. if pstate.reader.lines.items[0].size == tgt then
  125. eq(1, pstate.pos.line)
  126. eq(0, pstate.pos.col)
  127. else
  128. eq(0, pstate.pos.line)
  129. eq(tgt, pstate.pos.col)
  130. end
  131. else
  132. eq(0, pstate.pos.line)
  133. eq(initial_col, pstate.pos.col)
  134. end
  135. end
  136. local function singl_eltkn_test(typ, str, data)
  137. local pstate = new_pstate({str})
  138. eq({data=data, len=#str, start={col=0, line=0}, str=str, type=typ},
  139. next_eltkn(pstate, flags))
  140. check_advance(pstate, #str, 0)
  141. if not (
  142. typ == 'Spacing'
  143. or (typ == 'Register' and str == '@')
  144. or ((typ == 'SingleQuotedString' or typ == 'DoubleQuotedString')
  145. and not data.closed)
  146. ) then
  147. pstate = new_pstate({str .. ' '})
  148. eq({data=data, len=#str, start={col=0, line=0}, str=str, type=typ},
  149. next_eltkn(pstate, flags))
  150. check_advance(pstate, #str, 0)
  151. end
  152. pstate = new_pstate({'x' .. str})
  153. pstate.pos.col = 1
  154. eq({data=data, len=#str, start={col=1, line=0}, str=str, type=typ},
  155. next_eltkn(pstate, flags))
  156. check_advance(pstate, #str, 1)
  157. end
  158. local function scope_test(scope)
  159. singl_eltkn_test('PlainIdentifier', scope .. ':test#var', {autoload=true, scope=scope})
  160. singl_eltkn_test('PlainIdentifier', scope .. ':', {autoload=false, scope=scope})
  161. end
  162. local function comparison_test(op, inv_op, cmp_type)
  163. singl_eltkn_test('Comparison', op, {type=cmp_type, inv=false, ccs='UseOption'})
  164. singl_eltkn_test('Comparison', inv_op, {type=cmp_type, inv=true, ccs='UseOption'})
  165. singl_eltkn_test('Comparison', op .. '#', {type=cmp_type, inv=false, ccs='MatchCase'})
  166. singl_eltkn_test('Comparison', inv_op .. '#', {type=cmp_type, inv=true, ccs='MatchCase'})
  167. singl_eltkn_test('Comparison', op .. '?', {type=cmp_type, inv=false, ccs='IgnoreCase'})
  168. singl_eltkn_test('Comparison', inv_op .. '?', {type=cmp_type, inv=true, ccs='IgnoreCase'})
  169. end
  170. local function simple_test(pstate_arg, exp_type, exp_len, exp)
  171. local pstate = new_pstate(pstate_arg)
  172. exp = shallowcopy(exp)
  173. exp.type = exp_type
  174. exp.len = exp_len or #(pstate_arg[0])
  175. exp.start = { col = 0, line = 0 }
  176. eq(exp, next_eltkn(pstate, flags))
  177. end
  178. local function stable_tests()
  179. singl_eltkn_test('Parenthesis', '(', {closing=false})
  180. singl_eltkn_test('Parenthesis', ')', {closing=true})
  181. singl_eltkn_test('Bracket', '[', {closing=false})
  182. singl_eltkn_test('Bracket', ']', {closing=true})
  183. singl_eltkn_test('FigureBrace', '{', {closing=false})
  184. singl_eltkn_test('FigureBrace', '}', {closing=true})
  185. singl_eltkn_test('Question', '?')
  186. singl_eltkn_test('Colon', ':')
  187. singl_eltkn_test('Dot', '.')
  188. singl_eltkn_test('Assignment', '.=', {type='Concat'})
  189. singl_eltkn_test('Plus', '+')
  190. singl_eltkn_test('Assignment', '+=', {type='Add'})
  191. singl_eltkn_test('Comma', ',')
  192. singl_eltkn_test('Multiplication', '*', {type='Mul'})
  193. singl_eltkn_test('Multiplication', '/', {type='Div'})
  194. singl_eltkn_test('Multiplication', '%', {type='Mod'})
  195. singl_eltkn_test('Spacing', ' \t\t \t\t')
  196. singl_eltkn_test('Spacing', ' ')
  197. singl_eltkn_test('Spacing', '\t')
  198. singl_eltkn_test('Invalid', '\x01\x02\x03', {error='E15: Invalid control character present in input: %.*s'})
  199. singl_eltkn_test('Number', '0123', {is_float=false, base=8, val=83})
  200. singl_eltkn_test('Number', '01234567', {is_float=false, base=8, val=342391})
  201. singl_eltkn_test('Number', '012345678', {is_float=false, base=10, val=12345678})
  202. singl_eltkn_test('Number', '0x123', {is_float=false, base=16, val=291})
  203. singl_eltkn_test('Number', '0x56FF', {is_float=false, base=16, val=22271})
  204. singl_eltkn_test('Number', '0xabcdef', {is_float=false, base=16, val=11259375})
  205. singl_eltkn_test('Number', '0xABCDEF', {is_float=false, base=16, val=11259375})
  206. singl_eltkn_test('Number', '0x0', {is_float=false, base=16, val=0})
  207. singl_eltkn_test('Number', '00', {is_float=false, base=8, val=0})
  208. singl_eltkn_test('Number', '0b0', {is_float=false, base=2, val=0})
  209. singl_eltkn_test('Number', '0b010111', {is_float=false, base=2, val=23})
  210. singl_eltkn_test('Number', '0b100111', {is_float=false, base=2, val=39})
  211. singl_eltkn_test('Number', '0', {is_float=false, base=10, val=0})
  212. singl_eltkn_test('Number', '9', {is_float=false, base=10, val=9})
  213. singl_eltkn_test('Env', '$abc')
  214. singl_eltkn_test('Env', '$')
  215. singl_eltkn_test('PlainIdentifier', 'test', {autoload=false, scope=0})
  216. singl_eltkn_test('PlainIdentifier', '_test', {autoload=false, scope=0})
  217. singl_eltkn_test('PlainIdentifier', '_test_foo', {autoload=false, scope=0})
  218. singl_eltkn_test('PlainIdentifier', 't', {autoload=false, scope=0})
  219. singl_eltkn_test('PlainIdentifier', 'test5', {autoload=false, scope=0})
  220. singl_eltkn_test('PlainIdentifier', 't0', {autoload=false, scope=0})
  221. singl_eltkn_test('PlainIdentifier', 'test#var', {autoload=true, scope=0})
  222. singl_eltkn_test('PlainIdentifier', 'test#var#val###', {autoload=true, scope=0})
  223. singl_eltkn_test('PlainIdentifier', 't#####', {autoload=true, scope=0})
  224. singl_eltkn_test('And', '&&')
  225. singl_eltkn_test('Or', '||')
  226. singl_eltkn_test('Invalid', '&', {error='E112: Option name missing: %.*s'})
  227. singl_eltkn_test('Option', '&opt', {scope='Unspecified', name='opt'})
  228. singl_eltkn_test('Option', '&t_xx', {scope='Unspecified', name='t_xx'})
  229. singl_eltkn_test('Option', '&t_\r\r', {scope='Unspecified', name='t_\r\r'})
  230. singl_eltkn_test('Option', '&t_\t\t', {scope='Unspecified', name='t_\t\t'})
  231. singl_eltkn_test('Option', '&t_ ', {scope='Unspecified', name='t_ '})
  232. singl_eltkn_test('Option', '&g:opt', {scope='Global', name='opt'})
  233. singl_eltkn_test('Option', '&l:opt', {scope='Local', name='opt'})
  234. singl_eltkn_test('Invalid', '&l:', {error='E112: Option name missing: %.*s'})
  235. singl_eltkn_test('Invalid', '&g:', {error='E112: Option name missing: %.*s'})
  236. singl_eltkn_test('Register', '@', {name=-1})
  237. singl_eltkn_test('Register', '@a', {name='a'})
  238. singl_eltkn_test('Register', '@\r', {name=13})
  239. singl_eltkn_test('Register', '@ ', {name=' '})
  240. singl_eltkn_test('Register', '@\t', {name=9})
  241. singl_eltkn_test('SingleQuotedString', '\'test', {closed=false})
  242. singl_eltkn_test('SingleQuotedString', '\'test\'', {closed=true})
  243. singl_eltkn_test('SingleQuotedString', '\'\'\'\'', {closed=true})
  244. singl_eltkn_test('SingleQuotedString', '\'x\'\'\'', {closed=true})
  245. singl_eltkn_test('SingleQuotedString', '\'\'\'x\'', {closed=true})
  246. singl_eltkn_test('SingleQuotedString', '\'\'\'', {closed=false})
  247. singl_eltkn_test('SingleQuotedString', '\'x\'\'', {closed=false})
  248. singl_eltkn_test('SingleQuotedString', '\'\'\'x', {closed=false})
  249. singl_eltkn_test('DoubleQuotedString', '"test', {closed=false})
  250. singl_eltkn_test('DoubleQuotedString', '"test"', {closed=true})
  251. singl_eltkn_test('DoubleQuotedString', '"\\""', {closed=true})
  252. singl_eltkn_test('DoubleQuotedString', '"x\\""', {closed=true})
  253. singl_eltkn_test('DoubleQuotedString', '"\\"x"', {closed=true})
  254. singl_eltkn_test('DoubleQuotedString', '"\\"', {closed=false})
  255. singl_eltkn_test('DoubleQuotedString', '"x\\"', {closed=false})
  256. singl_eltkn_test('DoubleQuotedString', '"\\"x', {closed=false})
  257. singl_eltkn_test('Not', '!')
  258. singl_eltkn_test('Assignment', '=', {type='Plain'})
  259. comparison_test('==', '!=', 'Equal')
  260. comparison_test('=~', '!~', 'Matches')
  261. comparison_test('>', '<=', 'Greater')
  262. comparison_test('>=', '<', 'GreaterOrEqual')
  263. singl_eltkn_test('Minus', '-')
  264. singl_eltkn_test('Assignment', '-=', {type='Subtract'})
  265. singl_eltkn_test('Arrow', '->')
  266. singl_eltkn_test('Invalid', '~', {error='E15: Unidentified character: %.*s'})
  267. simple_test({{data=nil, size=0}}, 'EOC', 0, {error='start.col >= #pstr'})
  268. simple_test({''}, 'EOC', 0, {error='start.col >= #pstr'})
  269. simple_test({'2.'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  270. simple_test({'2e5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  271. simple_test({'2.x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  272. simple_test({'2.2.'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  273. simple_test({'2.0x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  274. simple_test({'2.0e'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  275. simple_test({'2.0e+'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  276. simple_test({'2.0e-'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  277. simple_test({'2.0e+x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  278. simple_test({'2.0e-x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  279. simple_test({'2.0e+1a'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  280. simple_test({'2.0e-1a'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  281. simple_test({'0b102'}, 'Number', 4, {data={is_float=false, base=2, val=2}, str='0b10'})
  282. simple_test({'10F'}, 'Number', 2, {data={is_float=false, base=10, val=10}, str='10'})
  283. simple_test({'0x0123456789ABCDEFG'}, 'Number', 18, {data={is_float=false, base=16, val=81985529216486895}, str='0x0123456789ABCDEF'})
  284. simple_test({{data='00', size=2}}, 'Number', 2, {data={is_float=false, base=8, val=0}, str='00'})
  285. simple_test({{data='009', size=2}}, 'Number', 2, {data={is_float=false, base=8, val=0}, str='00'})
  286. simple_test({{data='01', size=1}}, 'Number', 1, {data={is_float=false, base=10, val=0}, str='0'})
  287. end
  288. local function regular_scope_tests()
  289. scope_test('s')
  290. scope_test('g')
  291. scope_test('v')
  292. scope_test('b')
  293. scope_test('w')
  294. scope_test('t')
  295. scope_test('l')
  296. scope_test('a')
  297. simple_test({'g:'}, 'PlainIdentifier', 2, {data={scope='g', autoload=false}, str='g:'})
  298. simple_test({'g:is#foo'}, 'PlainIdentifier', 8, {data={scope='g', autoload=true}, str='g:is#foo'})
  299. simple_test({'g:isnot#foo'}, 'PlainIdentifier', 11, {data={scope='g', autoload=true}, str='g:isnot#foo'})
  300. end
  301. local function regular_is_tests()
  302. comparison_test('is', 'isnot', 'Identical')
  303. simple_test({'is'}, 'Comparison', 2, {data={type='Identical', inv=false, ccs='UseOption'}, str='is'})
  304. simple_test({'isnot'}, 'Comparison', 5, {data={type='Identical', inv=true, ccs='UseOption'}, str='isnot'})
  305. simple_test({'is?'}, 'Comparison', 3, {data={type='Identical', inv=false, ccs='IgnoreCase'}, str='is?'})
  306. simple_test({'isnot?'}, 'Comparison', 6, {data={type='Identical', inv=true, ccs='IgnoreCase'}, str='isnot?'})
  307. simple_test({'is#'}, 'Comparison', 3, {data={type='Identical', inv=false, ccs='MatchCase'}, str='is#'})
  308. simple_test({'isnot#'}, 'Comparison', 6, {data={type='Identical', inv=true, ccs='MatchCase'}, str='isnot#'})
  309. simple_test({'is#foo'}, 'Comparison', 3, {data={type='Identical', inv=false, ccs='MatchCase'}, str='is#'})
  310. simple_test({'isnot#foo'}, 'Comparison', 6, {data={type='Identical', inv=true, ccs='MatchCase'}, str='isnot#'})
  311. end
  312. local function regular_number_tests()
  313. simple_test({'2.0'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  314. simple_test({'2.0e5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  315. simple_test({'2.0e+5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  316. simple_test({'2.0e-5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  317. end
  318. local function regular_eoc_tests()
  319. singl_eltkn_test('EOC', '|')
  320. singl_eltkn_test('EOC', '\0')
  321. singl_eltkn_test('EOC', '\n')
  322. end
  323. itp('works (single tokens, zero flags)', function()
  324. stable_tests()
  325. regular_eoc_tests()
  326. regular_scope_tests()
  327. regular_is_tests()
  328. regular_number_tests()
  329. end)
  330. itp('peeks', function()
  331. flags = tonumber(lib.kELFlagPeek)
  332. should_advance = false
  333. stable_tests()
  334. regular_eoc_tests()
  335. regular_scope_tests()
  336. regular_is_tests()
  337. regular_number_tests()
  338. end)
  339. itp('forbids scope', function()
  340. flags = tonumber(lib.kELFlagForbidScope)
  341. stable_tests()
  342. regular_eoc_tests()
  343. regular_is_tests()
  344. regular_number_tests()
  345. simple_test({'g:'}, 'PlainIdentifier', 1, {data={scope=0, autoload=false}, str='g'})
  346. end)
  347. itp('allows floats', function()
  348. flags = tonumber(lib.kELFlagAllowFloat)
  349. stable_tests()
  350. regular_eoc_tests()
  351. regular_scope_tests()
  352. regular_is_tests()
  353. simple_test({'2.2'}, 'Number', 3, {data={is_float=true, base=10, val=2.2}, str='2.2'})
  354. simple_test({'2.0e5'}, 'Number', 5, {data={is_float=true, base=10, val=2e5}, str='2.0e5'})
  355. simple_test({'2.0e+5'}, 'Number', 6, {data={is_float=true, base=10, val=2e5}, str='2.0e+5'})
  356. simple_test({'2.0e-5'}, 'Number', 6, {data={is_float=true, base=10, val=2e-5}, str='2.0e-5'})
  357. simple_test({'2.500000e-5'}, 'Number', 11, {data={is_float=true, base=10, val=2.5e-5}, str='2.500000e-5'})
  358. simple_test({'2.5555e2'}, 'Number', 8, {data={is_float=true, base=10, val=2.5555e2}, str='2.5555e2'})
  359. simple_test({'2.5555e+2'}, 'Number', 9, {data={is_float=true, base=10, val=2.5555e2}, str='2.5555e+2'})
  360. simple_test({'2.5555e-2'}, 'Number', 9, {data={is_float=true, base=10, val=2.5555e-2}, str='2.5555e-2'})
  361. simple_test({{data='2.5e-5', size=3}},
  362. 'Number', 3, {data={is_float=true, base=10, val=2.5}, str='2.5'})
  363. simple_test({{data='2.5e5', size=4}},
  364. 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
  365. simple_test({{data='2.5e-50', size=6}},
  366. 'Number', 6, {data={is_float=true, base=10, val=2.5e-5}, str='2.5e-5'})
  367. end)
  368. itp('treats `is` as an identifier', function()
  369. flags = tonumber(lib.kELFlagIsNotCmp)
  370. stable_tests()
  371. regular_eoc_tests()
  372. regular_scope_tests()
  373. regular_number_tests()
  374. simple_test({'is'}, 'PlainIdentifier', 2, {data={scope=0, autoload=false}, str='is'})
  375. simple_test({'isnot'}, 'PlainIdentifier', 5, {data={scope=0, autoload=false}, str='isnot'})
  376. simple_test({'is?'}, 'PlainIdentifier', 2, {data={scope=0, autoload=false}, str='is'})
  377. simple_test({'isnot?'}, 'PlainIdentifier', 5, {data={scope=0, autoload=false}, str='isnot'})
  378. simple_test({'is#'}, 'PlainIdentifier', 3, {data={scope=0, autoload=true}, str='is#'})
  379. simple_test({'isnot#'}, 'PlainIdentifier', 6, {data={scope=0, autoload=true}, str='isnot#'})
  380. simple_test({'is#foo'}, 'PlainIdentifier', 6, {data={scope=0, autoload=true}, str='is#foo'})
  381. simple_test({'isnot#foo'}, 'PlainIdentifier', 9, {data={scope=0, autoload=true}, str='isnot#foo'})
  382. end)
  383. itp('forbids EOC', function()
  384. flags = tonumber(lib.kELFlagForbidEOC)
  385. stable_tests()
  386. regular_scope_tests()
  387. regular_is_tests()
  388. regular_number_tests()
  389. singl_eltkn_test('Invalid', '|', {error='E15: Unexpected EOC character: %.*s'})
  390. singl_eltkn_test('Invalid', '\0', {error='E15: Unexpected EOC character: %.*s'})
  391. singl_eltkn_test('Invalid', '\n', {error='E15: Unexpected EOC character: %.*s'})
  392. end)
  393. end)