1-- $Id: testes/literals.lua $
  2-- See Copyright Notice in file all.lua
  3
  4print('testing scanner')
  5
  6local debug = require "debug"
  7
  8
  9local function dostring (x) return assert(load(x), "")() end
 10
 11dostring("x \v\f = \t\r 'a\0a' \v\f\f")
 12assert(x == 'a\0a' and string.len(x) == 3)
 13_G.x = nil
 14
 15-- escape sequences
 16assert('\n\"\'\\' == [[
 17
 18"'\]])
 19
 20assert(string.find("\a\b\f\n\r\t\v", "^%c%c%c%c%c%c%c$"))
 21
 22-- assume ASCII just for tests:
 23assert("\09912" == 'c12')
 24assert("\99ab" == 'cab')
 25assert("\099" == '\99')
 26assert("\099\n" == 'c\10')
 27assert('\0\0\0alo' == '\0' .. '\0\0' .. 'alo')
 28
 29assert(010 .. 020 .. -030 == "1020-30")
 30
 31-- hexadecimal escapes
 32assert("\x00\x05\x10\x1f\x3C\xfF\xe8" == "\0\5\16\31\60\255\232")
 33
 34local function lexstring (x, y, n)
 35  local f = assert(load('return ' .. x ..
 36            ', require"debug".getinfo(1).currentline', ''))
 37  local s, l = f()
 38  assert(s == y and l == n)
 39end
 40
 41lexstring("'abc\\z  \n   efg'", "abcefg", 2)
 42lexstring("'abc\\z  \n\n\n'", "abc", 4)
 43lexstring("'\\z  \n\t\f\v\n'",  "", 3)
 44lexstring("[[\nalo\nalo\n\n]]", "alo\nalo\n\n", 5)
 45lexstring("[[\nalo\ralo\n\n]]", "alo\nalo\n\n", 5)
 46lexstring("[[\nalo\ralo\r\n]]", "alo\nalo\n", 4)
 47lexstring("[[\ralo\n\ralo\r\n]]", "alo\nalo\n", 4)
 48lexstring("[[alo]\n]alo]]", "alo]\n]alo", 2)
 49
 50assert("abc\z
 51        def\z
 52        ghi\z
 53       " == 'abcdefghi')
 54
 55
 56-- UTF-8 sequences
 57assert("\u{0}\u{00000000}\x00\0" == string.char(0, 0, 0, 0))
 58
 59-- limits for 1-byte sequences
 60assert("\u{0}\u{7F}" == "\x00\x7F")
 61
 62-- limits for 2-byte sequences
 63assert("\u{80}\u{7FF}" == "\xC2\x80\xDF\xBF")
 64
 65-- limits for 3-byte sequences
 66assert("\u{800}\u{FFFF}" ==   "\xE0\xA0\x80\xEF\xBF\xBF")
 67
 68-- limits for 4-byte sequences
 69assert("\u{10000}\u{1FFFFF}" == "\xF0\x90\x80\x80\xF7\xBF\xBF\xBF")
 70
 71-- limits for 5-byte sequences
 72assert("\u{200000}\u{3FFFFFF}" == "\xF8\x88\x80\x80\x80\xFB\xBF\xBF\xBF\xBF")
 73
 74-- limits for 6-byte sequences
 75assert("\u{4000000}\u{7FFFFFFF}" ==
 76       "\xFC\x84\x80\x80\x80\x80\xFD\xBF\xBF\xBF\xBF\xBF")
 77
 78
 79-- Error in escape sequences
 80local function lexerror (s, err)
 81  local st, msg = load('return ' .. s, '')
 82  if err ~= '<eof>' then err = err .. "'" end
 83  assert(not st and string.find(msg, "near .-" .. err))
 84end
 85
 86lexerror([["abc\x"]], [[\x"]])
 87lexerror([["abc\x]], [[\x]])
 88lexerror([["\x]], [[\x]])
 89lexerror([["\x5"]], [[\x5"]])
 90lexerror([["\x5]], [[\x5]])
 91lexerror([["\xr"]], [[\xr]])
 92lexerror([["\xr]], [[\xr]])
 93lexerror([["\x.]], [[\x.]])
 94lexerror([["\x8%"]], [[\x8%%]])
 95lexerror([["\xAG]], [[\xAG]])
 96lexerror([["\g"]], [[\g]])
 97lexerror([["\g]], [[\g]])
 98lexerror([["\."]], [[\%.]])
 99
100lexerror([["\999"]], [[\999"]])
101lexerror([["xyz\300"]], [[\300"]])
102lexerror([["   \256"]], [[\256"]])
103
104-- errors in UTF-8 sequences
105lexerror([["abc\u{100000000}"]], [[abc\u{100000000]])   -- too large
106lexerror([["abc\u11r"]], [[abc\u1]])    -- missing '{'
107lexerror([["abc\u"]], [[abc\u"]])    -- missing '{'
108lexerror([["abc\u{11r"]], [[abc\u{11r]])    -- missing '}'
109lexerror([["abc\u{11"]], [[abc\u{11"]])    -- missing '}'
110lexerror([["abc\u{11]], [[abc\u{11]])    -- missing '}'
111lexerror([["abc\u{r"]], [[abc\u{r]])     -- no digits
112
113-- unfinished strings
114lexerror("[=[alo]]", "<eof>")
115lexerror("[=[alo]=", "<eof>")
116lexerror("[=[alo]", "<eof>")
117lexerror("'alo", "<eof>")
118lexerror("'alo \\z  \n\n", "<eof>")
119lexerror("'alo \\z", "<eof>")
120lexerror([['alo \98]], "<eof>")
121
122-- valid characters in variable names
123for i = 0, 255 do
124  local s = string.char(i)
125  assert(not string.find(s, "[a-zA-Z_]") == not load(s .. "=1", ""))
126  assert(not string.find(s, "[a-zA-Z_0-9]") ==
127         not load("a" .. s .. "1 = 1", ""))
128end
129
130
131-- long variable names
132
133local var1 = string.rep('a', 15000) .. '1'
134local var2 = string.rep('a', 15000) .. '2'
135local prog = string.format([[
136  %s = 5
137  %s = %s + 1
138  return function () return %s - %s end
139]], var1, var2, var1, var1, var2)
140local f = dostring(prog)
141assert(_G[var1] == 5 and _G[var2] == 6 and f() == -1)
142_G[var1], _G[var2] = nil
143print('+')
144
145-- escapes --
146assert("\n\t" == [[
147
148	]])
149assert([[
150
151 $debug]] == "\n $debug")
152assert([[ [ ]] ~= [[ ] ]])
153-- long strings --
154local b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
155assert(string.len(b) == 960)
156prog = [=[
157print('+')
158
159local a1 = [["this is a 'string' with several 'quotes'"]]
160local a2 = "'quotes'"
161
162assert(string.find(a1, a2) == 34)
163print('+')
164
165a1 = [==[temp = [[an arbitrary value]]; ]==]
166assert(load(a1))()
167assert(temp == 'an arbitrary value')
168_G.temp = nil
169-- long strings --
170local b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
171assert(string.len(b) == 960)
172print('+')
173
174local a = [[00123456789012345678901234567890123456789123456789012345678901234567890123456789
17500123456789012345678901234567890123456789123456789012345678901234567890123456789
17600123456789012345678901234567890123456789123456789012345678901234567890123456789
17700123456789012345678901234567890123456789123456789012345678901234567890123456789
17800123456789012345678901234567890123456789123456789012345678901234567890123456789
17900123456789012345678901234567890123456789123456789012345678901234567890123456789
18000123456789012345678901234567890123456789123456789012345678901234567890123456789
18100123456789012345678901234567890123456789123456789012345678901234567890123456789
18200123456789012345678901234567890123456789123456789012345678901234567890123456789
18300123456789012345678901234567890123456789123456789012345678901234567890123456789
18400123456789012345678901234567890123456789123456789012345678901234567890123456789
18500123456789012345678901234567890123456789123456789012345678901234567890123456789
18600123456789012345678901234567890123456789123456789012345678901234567890123456789
18700123456789012345678901234567890123456789123456789012345678901234567890123456789
18800123456789012345678901234567890123456789123456789012345678901234567890123456789
18900123456789012345678901234567890123456789123456789012345678901234567890123456789
19000123456789012345678901234567890123456789123456789012345678901234567890123456789
19100123456789012345678901234567890123456789123456789012345678901234567890123456789
19200123456789012345678901234567890123456789123456789012345678901234567890123456789
19300123456789012345678901234567890123456789123456789012345678901234567890123456789
19400123456789012345678901234567890123456789123456789012345678901234567890123456789
19500123456789012345678901234567890123456789123456789012345678901234567890123456789
19600123456789012345678901234567890123456789123456789012345678901234567890123456789
197]]
198assert(string.len(a) == 1863)
199assert(string.sub(a, 1, 40) == string.sub(b, 1, 40))
200x = 1
201]=]
202
203print('+')
204_G.x = nil
205dostring(prog)
206assert(x)
207_G.x = nil
208
209
210
211do  -- reuse of long strings
212
213  -- get the address of a string
214  local function getadd (s) return string.format("%p", s) end
215
216  local s1 <const> = "01234567890123456789012345678901234567890123456789"
217  local s2 <const> = "01234567890123456789012345678901234567890123456789"
218  local s3 = "01234567890123456789012345678901234567890123456789"
219  local function foo() return s1 end
220  local function foo1() return s3 end
221  local function foo2()
222    return "01234567890123456789012345678901234567890123456789"
223  end
224  local a1 = getadd(s1)
225  assert(a1 == getadd(s2))
226  assert(a1 == getadd(foo()))
227  assert(a1 == getadd(foo1()))
228  assert(a1 == getadd(foo2()))
229
230  local sd = "0123456789" .. "0123456789012345678901234567890123456789"
231  assert(sd == s1 and getadd(sd) ~= a1)
232end
233
234
235-- testing line ends
236prog = [[
237local a = 1        -- a comment
238local b = 2
239
240
241x = [=[
242hi
243]=]
244y = "\
245hello\r\n\
246"
247return require"debug".getinfo(1).currentline
248]]
249
250for _, n in pairs{"\n", "\r", "\n\r", "\r\n"} do
251  local prog, nn = string.gsub(prog, "\n", n)
252  assert(dostring(prog) == nn)
253  assert(_G.x == "hi\n" and _G.y == "\nhello\r\n\n")
254end
255_G.x, _G.y = nil
256
257
258-- testing comments and strings with long brackets
259local a = [==[]=]==]
260assert(a == "]=")
261
262a = [==[[===[[=[]]=][====[]]===]===]==]
263assert(a == "[===[[=[]]=][====[]]===]===")
264
265a = [====[[===[[=[]]=][====[]]===]===]====]
266assert(a == "[===[[=[]]=][====[]]===]===")
267
268a = [=[]]]]]]]]]=]
269assert(a == "]]]]]]]]")
270
271
272--[===[
273x y z [==[ blu foo
274]==
275]
276]=]==]
277error error]=]===]
278
279-- generate all strings of four of these chars
280local x = {"=", "[", "]", "\n"}
281local len = 4
282local function gen (c, n)
283  if n==0 then coroutine.yield(c)
284  else
285    for _, a in pairs(x) do
286      gen(c..a, n-1)
287    end
288  end
289end
290
291for s in coroutine.wrap(function () gen("", len) end) do
292  assert(s == load("return [====[\n"..s.."]====]", "")())
293end
294
295
296-- testing decimal point locale
297if os.setlocale("pt_BR") or os.setlocale("ptb") then
298  assert(tonumber("3,4") == 3.4 and tonumber"3.4" == 3.4)
299  assert(tonumber("  -.4  ") == -0.4)
300  assert(tonumber("  +0x.41  ") == 0X0.41)
301  assert(not load("a = (3,4)"))
302  assert(assert(load("return 3.4"))() == 3.4)
303  assert(assert(load("return .4,3"))() == .4)
304  assert(assert(load("return 4."))() == 4.)
305  assert(assert(load("return 4.+.5"))() == 4.5)
306
307  assert(" 0x.1 " + " 0x,1" + "-0X.1\t" == 0x0.1)
308
309  assert(not tonumber"inf" and not tonumber"NAN")
310
311  assert(assert(load(string.format("return %q", 4.51)))() == 4.51)
312
313  local a,b = load("return 4.5.")
314  assert(string.find(b, "'4%.5%.'"))
315
316  assert(os.setlocale("C"))
317else
318  (Message or print)(
319   '\n >>> pt_BR locale not available: skipping decimal point tests <<<\n')
320end
321
322
323-- testing %q x line ends
324local s = "a string with \r and \n and \r\n and \n\r"
325local c = string.format("return %q", s)
326assert(assert(load(c))() == s)
327
328-- testing errors
329assert(not load"a = 'non-ending string")
330assert(not load"a = 'non-ending string\n'")
331assert(not load"a = '\\345'")
332assert(not load"a = [=x]")
333
334local function malformednum (n, exp)
335  local s, msg = load("return " .. n)
336  assert(not s and string.find(msg, exp))
337end
338
339malformednum("0xe-", "near <eof>")
340malformednum("0xep-p", "malformed number")
341malformednum("1print()", "malformed number")
342
343print('OK')