Python编程 综合性实验: Java源代码高亮 实现将Java代码转换为html

前言

这个是大三下学期的Java课程设计,目前重构完成了代码转换并输出的部分.暂时还没有打算完成可视化界面.
代码不长,加起来也就100行左右(再次感受到Python的精简),实现了对注释,关键字,字符串,一些运算符的高亮.

代码实现

import re

class JavaSyntaxHighlighter:
    def __init__(self):
        self.x = 0
        self.line = ""  # 保存当前处理的行
        self.keywords = \
            ["abstract", "assert", "boolean", "break", "byte",
             "case", "catch", "char", "class", "const",
             "continue", "default", "do", "double", "else",
             "enum", "extends", "final", "finally", "float",
             "for", "goto", "if", "implements", "import",
             "instanceof", "int", "interface", "long", "native",
             "new", "package", "private", "protected", "public",
             "return", "strictfp", "short", "static", "super",
             "switch", "synchronized", "this", "throw", "throws",
             "transient", "try", "void", "volatile", "while"]
        self.regexkeywords = [r"(?<=\s)" + w + r"(?=\s)" for w in self.keywords]

    def highlight_note(self, note):
        '高亮注释行'
        if note != "":  # note为空,表示行尾无注释
            self.line = self.line.replace(note, " [note] " + note + " [end] ")

    def highlight_string(self, pos):
        '高亮字符串'
        codeline = self.line[:pos]  # 代码部分
        noteline = self.line[pos:]  # 不处理行尾注释
        strlist = re.findall(r'\".*?\"|\'.*?\'', codeline)  # 搜索所有字符串
        if strlist is not None:
            for string in strlist:
                codeline = codeline.replace(string, " [str] " + string + " [end] ")
        self.line = codeline + noteline

    def highlight_keyword(self, pos):
        '高亮关键字'
        codeline = " " + self.line[:pos] + " "
        noteline = self.line[pos:]
        for r, w in zip(self.regexkeywords, self.keywords):
            codeline = re.sub(r, " [key] " + w + " [end] ", codeline)
        self.line = codeline + noteline

    def highlight_operator(self):
        '高亮运算符'
        line = self.line
        opr = ['=', '(', ')', '{', '}', '|', '+', '-', '*', '/', '<', '>']
        for o in opr:
            line = line.replace(o, " [opr] " + o + " [end] ")  # 未实现关于字符串内的运算符处理
        self.line = line

    def translate(self, data=""):
        '转换为html标签'
        name = ["note", "key", "str", "opr"]
        for n in name:
            data = data.replace(" [" + n + "] ", "<span class='" + n + "'>")
        data = data.replace(" [end] ", "</span>")
        return data

    def highlight(self, line):
        '单行代码高亮'
        self.line = line
        if self.line.strip() == '': return line  # 空串不处理
        global note  # 注释
        note = ""
        find_note = re.match(r'/(/|\*)(.*)|\*(.*)|(.*)\*/$', self.line.strip())  # 查找单行注释
        if find_note:  # 处理单行注释
            note = find_note.group()
            self.highlight_note(note)
            return self.line
        pos = len(self.line)
        find_note = re.search(r'(?<=[){};])(.*)/(/|\*).*$', self.line.strip())  # 查找行尾注释
        if find_note:
            note = find_note.group()  # 标记行尾注释
            pos = find_note.span()[0]  # 标记注释位置
        self.highlight_note(note)  # 处理行尾注释
        self.highlight_keyword(pos)  # 处理关键字
        self.highlight_string(pos)  # 处理字符串
        self.highlight_operator()  # 处理运算符
        return self.line  # 返回处理好的行


if __name__ == '__main__':
    jsh = JavaSyntaxHighlighter()
    html_head = ['<!DOCTYPE html>',
                 '<html>', '<head>',
                 '<title>', 'generated by JavaSyntaxHighlighter', '</title>',
                 '<style type="text/css">',
                 'pre{font-family:\'Microsoft Yahei\';font-size:20;}',
                 '.key{color:#000080;font-weight:bold;}',
                 '.note{color:#808080;font-weight:bold;font-style:italic;}',
                 '.str{color:#008000;font-weight:bold;}',
                 '.opr{color:#DB380D;font-weight:bold;}',
                 '</style>', '</head>', '<body>', '<pre>']
    html_tail = ['</pre>', '</body>', '</html>']
    input_file = input("请输入Java文件路径: ")
    with open(input_file) as f:
        codelist = f.read().replace("<", "&lt").split('\n')  # 替换java中的“<”为html的显示符
    with open(input_file + ".html", 'w') as f:  # 保存html到同目录
        data = []
        f.write('\n'.join(html_head))
        for i in codelist:
            data.append(jsh.highlight(i))  # 每行加标签后存如data
        f.write(jsh.translate('\n'.join(data)))  # 转换为html的<>标签
        f.write('\n'.join(html_tail))
    print("转换成功!已保存为:", input_file + ".html")

说明

1.流程:

读取一个java文件到列表->对列表每一行调用highlight()进行高亮(加标签)->保存到data中->
对data中的标签转换为html的标准标签->将html的头部(<html>,<head>…)+data+html尾部(<head></html>…)输出为html格式文件

2.html:

html中使用了<pre>格式化代码显示,使用<span class=“xxx”>进行加标签
在css中设置class=“xxx"的属性,实现对不同的部分动态调整颜色,而且只需修改一次就可以了
(以前的版本中使用<font color=”#808080">这类标签,非常的笨重,不能动态修改颜色,字体等)

3.高亮函数的流程

(1) 调用highlight(line),送一行进去
(2) 用self.line = line保存当前处理的行
(2) self.line.strip()判断串,空串返回不处理
(3) 用正则模式/(/|\*)(.*)|\*(.*)|(.*)\*/$检查是否为单行注释(//xxx /*xxx*/ *xxx xxx*/)
如果是,highlight_note(self.line)高亮注释部分并返回
(4) 用正则模式(?<=[){};])(.*)/(/|\*).*$查找行尾注释,
如果有,返回注释本身note,以及代码与注释的分割位置pos
例如:int i = 0; //*Note*, note="//*Note*" pos=10
如果没有,note="" pos=len(self.line)分割位置在行尾
也就是说:self.line[:pos]为代码,self.line[pos:]为行尾注释
(5)highlight_note(note)处理行尾注释
(6)highlight_keyword(pos)处理关键字
(7)highlight_string(pos)处理字符串
(8)highlight_operator()处理运算符
(9)最后返回self.line

4.特殊部分处理

例如:
1.字符串内含有注释
string str = "abc//cde/*123*/"
2.注释内含有字符串
// something "i see.."
3.代码包含了关键字
public void importModule(){}中的import
4.字符串\注释内含运算符
str = "1+5/2*3"
1.含有注释的字符串属于代码行,通过单行注释的检查,又通过了行尾注释的检查,所以只会被highlight_string()高亮
2.含有字符串的注释,没通过单行注释的检查,被返回.如果通过行尾注释的检查,则被分割到注释部分高亮,不参与highlight_string()的高亮
3.用正则表达式r"(?<=\s)" + w + r"(?=\s)",w为关键字即可.
相当于关键字w在前面和后面都有不可见字符时"[空白字符a]public[空白字符b]"
对于出现在开头没有空白字符的关键字要加上一个空格
public static xxx->[空白字符]public static xxx
4.还没处理…

测试

这里粘一下Hashmap.java的输出效果和html源文件
大概感觉就是这样了,不过还是有一些问题,想想还有什么方法好解决?
测试用例Util百度网盘在这里插入图片描述
在这里插入图片描述

写在最后

复习了正则表达式的用法,re模块的使用等等,这是第一次重构,将来会有第二,第三次的改进…希望学习Python学得更好

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值