2021-02-21 04:53:09 +00:00
|
|
|
#!/usr/bin/env python3
|
2013-01-25 00:46:29 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2015-06-07 21:19:26 +00:00
|
|
|
# Requires Python 2.7 or later
|
2013-01-25 00:46:29 +00:00
|
|
|
|
2013-08-28 00:44:27 +00:00
|
|
|
import io, os, sys, unittest
|
2013-01-25 00:46:29 +00:00
|
|
|
|
2013-08-28 00:44:27 +00:00
|
|
|
if sys.platform == "win32":
|
|
|
|
import XiteWin as Xite
|
|
|
|
else:
|
|
|
|
import XiteQt as Xite
|
2013-01-25 00:46:29 +00:00
|
|
|
|
|
|
|
keywordsHTML = [
|
|
|
|
b"b body content head href html link meta "
|
|
|
|
b"name rel script strong title type xmlns",
|
|
|
|
b"function",
|
|
|
|
b"sub"
|
|
|
|
]
|
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
keywordsPerl = [
|
|
|
|
b"NULL __FILE__ __LINE__ __PACKAGE__ __DATA__ __END__ AUTOLOAD "
|
|
|
|
b"BEGIN CORE DESTROY END EQ GE GT INIT LE LT NE CHECK abs accept "
|
|
|
|
b"alarm and atan2 bind binmode bless caller chdir chmod chomp chop "
|
|
|
|
b"chown chr chroot close closedir cmp connect continue cos crypt "
|
|
|
|
b"dbmclose dbmopen defined delete die do dump each else elsif endgrent "
|
|
|
|
b"endhostent endnetent endprotoent endpwent endservent eof eq eval "
|
|
|
|
b"exec exists exit exp fcntl fileno flock for foreach fork format "
|
|
|
|
b"formline ge getc getgrent getgrgid getgrnam gethostbyaddr gethostbyname "
|
|
|
|
b"gethostent getlogin getnetbyaddr getnetbyname getnetent getpeername "
|
|
|
|
b"getpgrp getppid getpriority getprotobyname getprotobynumber getprotoent "
|
|
|
|
b"getpwent getpwnam getpwuid getservbyname getservbyport getservent "
|
|
|
|
b"getsockname getsockopt glob gmtime goto grep gt hex if index "
|
|
|
|
b"int ioctl join keys kill last lc lcfirst le length link listen "
|
|
|
|
b"local localtime lock log lstat lt map mkdir msgctl msgget msgrcv "
|
|
|
|
b"msgsnd my ne next no not oct open opendir or ord our pack package "
|
|
|
|
b"pipe pop pos print printf prototype push quotemeta qu "
|
|
|
|
b"rand read readdir readline readlink readpipe recv redo "
|
|
|
|
b"ref rename require reset return reverse rewinddir rindex rmdir "
|
|
|
|
b"scalar seek seekdir select semctl semget semop send setgrent "
|
|
|
|
b"sethostent setnetent setpgrp setpriority setprotoent setpwent "
|
|
|
|
b"setservent setsockopt shift shmctl shmget shmread shmwrite shutdown "
|
|
|
|
b"sin sleep socket socketpair sort splice split sprintf sqrt srand "
|
|
|
|
b"stat study sub substr symlink syscall sysopen sysread sysseek "
|
|
|
|
b"system syswrite tell telldir tie tied time times truncate "
|
|
|
|
b"uc ucfirst umask undef unless unlink unpack unshift untie until "
|
|
|
|
b"use utime values vec wait waitpid wantarray warn while write "
|
|
|
|
b"xor "
|
|
|
|
b"given when default break say state UNITCHECK __SUB__ fc"
|
|
|
|
]
|
|
|
|
|
2013-01-25 00:46:29 +00:00
|
|
|
class TestLexers(unittest.TestCase):
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 00:44:27 +00:00
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 00:46:29 +00:00
|
|
|
self.ed = self.xite.ed
|
|
|
|
self.ed.ClearAll()
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
def AsStyled(self, withWindowsLineEnds):
|
2013-01-25 00:46:29 +00:00
|
|
|
text = self.ed.Contents()
|
|
|
|
data = io.BytesIO()
|
|
|
|
prevStyle = -1
|
|
|
|
for o in range(self.ed.Length):
|
|
|
|
styleNow = self.ed.GetStyleAt(o)
|
|
|
|
if styleNow != prevStyle:
|
|
|
|
styleBuf = "{%0d}" % styleNow
|
|
|
|
data.write(styleBuf.encode('utf-8'))
|
|
|
|
prevStyle = styleNow
|
|
|
|
data.write(text[o:o+1])
|
2019-05-04 18:14:48 +00:00
|
|
|
if withWindowsLineEnds:
|
|
|
|
return data.getvalue().replace(b"\n", b"\r\n")
|
|
|
|
else:
|
|
|
|
return data.getvalue()
|
2013-01-25 00:46:29 +00:00
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
def LexExample(self, name, lexerName, keywords, fileMode="b"):
|
|
|
|
self.ed.ClearAll()
|
|
|
|
self.ed.EmptyUndoBuffer()
|
2013-08-28 00:44:27 +00:00
|
|
|
self.ed.SetCodePage(65001)
|
2013-01-25 00:46:29 +00:00
|
|
|
self.ed.LexerLanguage = lexerName
|
2019-05-04 18:14:48 +00:00
|
|
|
mask = 0xff
|
2013-01-25 00:46:29 +00:00
|
|
|
for i in range(len(keywords)):
|
|
|
|
self.ed.SetKeyWords(i, keywords[i])
|
|
|
|
|
|
|
|
nameExample = os.path.join("examples", name)
|
|
|
|
namePrevious = nameExample +".styled"
|
|
|
|
nameNew = nameExample +".new"
|
|
|
|
with open(nameExample, "rb") as f:
|
|
|
|
prog = f.read()
|
2019-05-04 18:14:48 +00:00
|
|
|
if fileMode == "t" and sys.platform == "win32":
|
|
|
|
prog = prog.replace(b"\r\n", b"\n")
|
2013-01-25 00:46:29 +00:00
|
|
|
BOM = b"\xEF\xBB\xBF"
|
|
|
|
if prog.startswith(BOM):
|
|
|
|
prog = prog[len(BOM):]
|
|
|
|
lenDocument = len(prog)
|
|
|
|
self.ed.AddText(lenDocument, prog)
|
|
|
|
self.ed.Colourise(0, lenDocument)
|
|
|
|
self.assertEquals(self.ed.EndStyled, lenDocument)
|
2013-08-28 00:44:27 +00:00
|
|
|
try:
|
|
|
|
with open(namePrevious, "rb") as f:
|
|
|
|
prevStyled = f.read()
|
2019-05-04 18:14:48 +00:00
|
|
|
if fileMode == "t" and sys.platform == "win32":
|
|
|
|
prog = prog.replace(b"\r\n", b"\n")
|
|
|
|
except EnvironmentError:
|
2013-08-28 00:44:27 +00:00
|
|
|
prevStyled = ""
|
2019-05-04 18:14:48 +00:00
|
|
|
progStyled = self.AsStyled(fileMode == "t" and sys.platform == "win32")
|
2013-01-25 00:46:29 +00:00
|
|
|
if progStyled != prevStyled:
|
|
|
|
with open(nameNew, "wb") as f:
|
|
|
|
f.write(progStyled)
|
2019-05-04 18:14:48 +00:00
|
|
|
print("Incorrect lex for " + name)
|
2013-01-25 00:46:29 +00:00
|
|
|
print(progStyled)
|
|
|
|
print(prevStyled)
|
|
|
|
self.assertEquals(progStyled, prevStyled)
|
|
|
|
# The whole file doesn't parse like it did before so don't try line by line
|
|
|
|
# as that is likely to fail many times.
|
|
|
|
return
|
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
if fileMode == "b": # "t" files are large and this is a quadratic check
|
|
|
|
# Try partial lexes from the start of every line which should all be identical.
|
|
|
|
for line in range(self.ed.LineCount):
|
|
|
|
lineStart = self.ed.PositionFromLine(line)
|
|
|
|
self.ed.StartStyling(lineStart, mask)
|
|
|
|
self.assertEquals(self.ed.EndStyled, lineStart)
|
|
|
|
self.ed.Colourise(lineStart, lenDocument)
|
|
|
|
progStyled = self.AsStyled(fileMode == "t" and sys.platform == "win32")
|
|
|
|
if progStyled != prevStyled:
|
|
|
|
print("Incorrect partial lex for " + name + " at line " + line)
|
|
|
|
with open(nameNew, "wb") as f:
|
|
|
|
f.write(progStyled)
|
|
|
|
self.assertEquals(progStyled, prevStyled)
|
|
|
|
# Give up after one failure
|
|
|
|
return
|
|
|
|
|
|
|
|
# Test lexing just once from beginning to end in text form.
|
|
|
|
# This is used for test cases that are too long to be exhaustively tested by lines and
|
|
|
|
# may be sensitive to line ends so are tested as if using Unix LF line ends.
|
|
|
|
def LexLongCase(self, name, lexerName, keywords, fileMode="b"):
|
|
|
|
self.LexExample(name, lexerName, keywords, "t")
|
2013-01-25 00:46:29 +00:00
|
|
|
|
|
|
|
def testCXX(self):
|
|
|
|
self.LexExample("x.cxx", b"cpp", [b"int"])
|
|
|
|
|
|
|
|
def testPython(self):
|
|
|
|
self.LexExample("x.py", b"python",
|
|
|
|
[b"class def else for if import in print return while"])
|
|
|
|
|
|
|
|
def testHTML(self):
|
|
|
|
self.LexExample("x.html", b"hypertext", keywordsHTML)
|
|
|
|
|
|
|
|
def testASP(self):
|
|
|
|
self.LexExample("x.asp", b"hypertext", keywordsHTML)
|
|
|
|
|
|
|
|
def testPHP(self):
|
|
|
|
self.LexExample("x.php", b"hypertext", keywordsHTML)
|
|
|
|
|
|
|
|
def testVB(self):
|
|
|
|
self.LexExample("x.vb", b"vb", [b"as dim or string"])
|
|
|
|
|
2013-08-28 00:44:27 +00:00
|
|
|
def testLua(self):
|
|
|
|
self.LexExample("x.lua", b"lua", [b"function end"])
|
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
def testNim(self):
|
|
|
|
self.LexExample("x.nim", b"nim", [b"else end if let proc"])
|
|
|
|
|
2013-08-28 00:44:27 +00:00
|
|
|
def testRuby(self):
|
|
|
|
self.LexExample("x.rb", b"ruby", [b"class def end"])
|
|
|
|
|
|
|
|
def testPerl(self):
|
2019-05-04 18:14:48 +00:00
|
|
|
self.LexExample("x.pl", b"perl", keywordsPerl)
|
|
|
|
|
|
|
|
def testPerl52(self):
|
|
|
|
self.LexLongCase("perl-test-5220delta.pl", b"perl", keywordsPerl)
|
|
|
|
|
|
|
|
def testPerlPrototypes(self):
|
|
|
|
self.LexLongCase("perl-test-sub-prototypes.pl", b"perl", keywordsPerl)
|
2013-08-28 00:44:27 +00:00
|
|
|
|
2013-01-25 00:46:29 +00:00
|
|
|
def testD(self):
|
|
|
|
self.LexExample("x.d", b"d",
|
|
|
|
[b"keyword1", b"keyword2", b"", b"keyword4", b"keyword5",
|
|
|
|
b"keyword6", b"keyword7"])
|
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
def testTCL(self):
|
|
|
|
self.LexExample("x.tcl", b"tcl", [b"proc set socket vwait"])
|
|
|
|
|
2013-01-25 00:46:29 +00:00
|
|
|
if __name__ == '__main__':
|
2013-08-28 00:44:27 +00:00
|
|
|
Xite.main("lexTests")
|