利用python,将python语法代码翻译成js语法代码

将python自动翻译成js脚本


说明

由于想用通过写python代码直接翻译出来对应的js代码,python代码有它自身的简洁性,代码量比较少,可以做一个脚本翻译成运行速度高但是代码量打的编程语言,由于js相对java来说更加接近动态脚本语言的特性,所以先做了python翻译成js的方法。

翻译的不能保证能够正常运行,但是反正总比手动改方便多了。起码括号自动加上了,结构上都符合js的标准了。

以后可能还会打算做自动类型检测和推断,然后做出python翻译成java或者C++,这可能有助于做一些算法题。

展示

可以用while循环来做成实时翻译,一边写代码,一边运行脚本,一边实时更新翻译出来的结果

左侧是python代码,右侧是实时翻译成的js代码左侧是python代码,右侧是实时翻译成的js代码

主要思路

  1. 清除函数注解
  2. 根据缩进添加大括号结构
  3. 增加赋值语句的 let 关键字
  4. 进行一些关键字和函数名的简单替换
  5. 处理主程序入口翻译
  6. 多行注释的语法转化
  7. 模板字符串的翻译 f"{}" 换成 " ${} " (ES6的反引号)
  8. 添加分号

源代码

说明:直接调用trans函数,输入python代码字符串,返回的是翻译后的js代码字符串。

# -*- encoding: utf-8 -*-
"""
将python代码转化成js代码的主程序
2021年12月08日
by littlefean
"""
import os
from time import sleep


def main():
    while True:
        os.system("cls")
        with open(f"..\\in\\py4.py", encoding="utf-8") as f:
            content = f.read()
            print(trans(content))
        sleep(0.5)
    # pyList = os.listdir("..\\in")
    # print(pyList)
    # for pyPath in pyList:
    #     with open(f"..\\in\\{pyPath}", encoding="utf-8") as f:
    #         content = f.read()
    #         print(trans(content))
    return None


def trans(inputString: str) -> str:
    """
    :param inputString: python代码字符串
    :return: js代码字符串
    """
    res = inputString
    res = clearFuncNote(res)
    res = changeContainerCode(res)
    res = addLet(res)
    res = simpleReplace(res)
    res = mainScript(res)
    res = changeMulLineCommonCode(res)
    res = templeStrTrans(res)
    res = addSemicolon(res)
    return res


def iterCode(lineStr: str) -> str:
    """对循环条件表达式的处理
    <i in range(n)>   let i = 0; i < n; i++
    <nChild in self.graphDic[n]>
    <nChild == n>
    <mChild in self.graphDic[m]>
    <mChild == m>
    <n in self.graphDic[m]>
    <k, v in self.graphDic.items()>
    <meeting in meetings>
    <time not in timeDic>
    <time, connectList in timeDic.items()>
    <con in connectList>
    <know in knows>"""
    words = lineStr.split()
    wordCount = len(words)
    res = lineStr
    if wordCount == 3:
        if "in" in lineStr and "range(" in lineStr:
            # 循环表达式处理
            parInner = getParInner(lineStr)
            parInnerArr = parInner.split(",")
            if len(parInnerArr) == 1:
                return f"let {words[0]} = 0; {words[0]} < {parInner}; {words[0]}++"
            elif len(parInnerArr) == 2:
                # 需要做 循环 [n,m) 的
                ...
            else:
                return f"let {words[0]} = 0; {words[0]} < {parInner}; {words[0]}++"
        elif "in" in lineStr and "range(" not in lineStr:
            return f"let {words[0]} of {words[2]}"

    return res


def changeContainerCode(res: str) -> str:
    """将将 `xx(...) {` 类型语句替换
    注意:这个操作会更改代码的行数,会插入一些行"""
    lineArr = res.split("\n")
    lineNum = len(lineArr)
    """ 额外加小括号类型
    while a == b:
    while (a == b) {
    if a == b:
    if (a == b) {
    """
    words = ["while", "for", "if", "elif"]
    """ 直接替换类型
    class Main:
    class Main {
    def does():
    function does() {
    else:
    else {
    """
    words2 = ["class", "def", "else"]

    for i, line in enumerate(lineArr):
        if i == lineNum - 1:
            # 不去检查最后一行,因为最后一行不可能是容器头行
            break

        firstWord = getFirstWord(line)
        # print(firstWord, "firstWord")
        if (firstWord in words or firstWord in words2) and line.strip().endswith(":"):
            # 需要添加 },找
            tabs = getLeftCount(line, " ")
            for j in range(i + 1, lineNum):
                if lineArr[j].strip() == "":
                    if j + 1 == lineNum:
                        lineArr[j] = "}"
                    else:
                        continue
                elif getLeftCount(lineArr[j], " ") <= tabs:
                    lineArr[j - 1] = lineArr[j - 1] + f"\n{tabs * ' '}" + "}"
                    break
        if firstWord in words:
            left = lineArr[i].find(firstWord) + 1
            # 等式
            eqCode = lineArr[i][left + len(firstWord):-1]
            # 对等式的特殊处理
            lineArr[i] = lineArr[i][:left + len(firstWord)] + f"({iterCode(eqCode)})" + " {"
            lineArr[i] = lineArr[i].replace(":", " {")
        elif firstWord in words2:
            lineArr[i] = lineArr[i].replace(":", " {")
    # 声明变量结束
    return "\n".join(lineArr)


def addSemicolon(pyStr: str) -> str:
    """添加分号"""
    lineArr = pyStr.split("\n")

    def doNotNeed(lineStr: str):
        lineStrip = lineStr.strip()
        for string in ["", "/**", "*/", ":"]:
            if string == lineStrip:
                return True
        endCode = "{}[("
        for char in endCode:
            if lineStr.strip().endswith(char):
                return True
        return False

    for i, line in enumerate(lineArr):
        if doNotNeed(line):
            continue
        lineArr[i] = lineArr[i] + ";"
        ...
    return "\n".join(lineArr)


def changeMulLineCommonCode(pyStr: str) -> str:
    """将多行注释转化成C风格类型的多行注释"""
    lineArr = pyStr.split("\n")
    numArr = [0] * len(lineArr)  # 不是多行注释开始或者结束行,那就会标志0,如果是开始或者结束,就会累加
    n = 1
    for i, line in enumerate(lineArr):
        stripLine = line.strip()
        if stripLine.startswith('"""') and stripLine.endswith('"""') and len(stripLine) > 3:
            # 多行注释注释在一行上了
            lineArr[i] = line.replace('"""', "")
            spaceN = getLeftCount(lineArr[i], " ")
            lineArr[i] = lineArr[i][:spaceN] + "// " + lineArr[i][spaceN:]
        elif stripLine.startswith("'''") and stripLine.endswith("'''") and len(stripLine) > 3:
            # 多行注释注释在一行上了
            lineArr[i] = line.replace("'''", "")
            spaceN = getLeftCount(lineArr[i], " ")
            lineArr[i] = lineArr[i][:spaceN] + "// " + lineArr[i][spaceN:]
        elif stripLine.startswith('"""'):
            numArr[i] = n
            n += 1
        elif stripLine.endswith('"""'):
            numArr[i] = n
            n += 1
    for i, num in enumerate(numArr):
        if num != 0:
            if num % 2 == 1:
                lineArr[i] = lineArr[i].replace('"""', "/**")
                for j in range(i + 1, len(numArr)):
                    if numArr[j] != 0:
                        break
                    spaceN = getLeftCount(lineArr[i], " ")
                    lineArr[j] = lineArr[j][:spaceN] + " * " + lineArr[j][spaceN:]
            else:
                lineArr[i] = lineArr[i].replace('"""', " */")
    return "\n".join(lineArr)


def templeStrTrans(pyStr: str) -> str:
    """进行模板字符串处理"""

    def tempLineTrans(lineStr: str) -> str:
        """
        print(f"{1+2}")
        print(`${1+2}`)
        缺陷:目前一行上只能处理一个
        :param lineStr:
        :return:
        """
        if "f\"" in lineStr:
            index = lineStr.find("f\"")
            newLine = lineStr[:index]
            newLine += "`"
            isIn = True
            for j in range(index + 2, len(lineStr)):
                if lineStr[j] == "{" and isIn:
                    newLine += "$"
                if lineStr[j] == "\"":
                    isIn = False
                    newLine += "`"
                    continue
                newLine += lineStr[j]
            return newLine

        return lineStr

    lineArr = pyStr.split("\n")
    for i, line in enumerate(lineArr):
        lineArr[i] = tempLineTrans(line)
        ...
    return "\n".join(lineArr)


def clearFuncNote(pyStr: str) -> str:
    """清除函数注解"""
    lineArr = pyStr.split("\n")
    for i, line in enumerate(lineArr):
        if line.strip().startswith("def"):
            # 这个行是
            if "->" in line:
                line = line[:line.find("->")] + ":"
            left = line.find("(")
            right = line.rfind(")")
            midCode = line[left + 1: right]
            midArr = midCode.split(",")
            newMidArr = []
            for arg in midArr:
                if ":" in arg:
                    newMidArr.append(arg[:arg.find(":")])
            midCode = ",".join(newMidArr)
            lineArr[i] = line[:left + 1] + midCode + line[right:]
            ...
    return "\n".join(lineArr)


def mainScript(pyStr: str) -> str:
    """处理程序入口"""
    lineArr = pyStr.split("\n")
    find = False
    findLine = 0
    for i, line in enumerate(lineArr):
        if "if" in line and "__name__" in line and "__main__" in line:
            lineArr[i] = 'window.onload = function() {'
            find = True
            findLine = i
    if find:
        for i in range(findLine, len(lineArr)):
            if lineArr[i] == "":
                lineArr[i] = "}"
    return "\n".join(lineArr)


def addLet(pyStr: str) -> str:
    """添加变量声明let语句"""
    lineArr = pyStr.split("\n")
    for i in range(len(lineArr)):
        if isSetValueLine(lineArr[i]):
            # 这是一个创建变量的语句
            lineArr[i] = setValue(lineArr[i])
    return "\n".join(lineArr)


def simpleReplace(pyStr: str) -> str:
    """简单替换"""
    res = pyStr
    # 简单替换
    replaceDic = {
        "def ": "function ",
        "None": "null",
        "#": "//",

        "print(": "console.log(",
        "input(": "prompt(",
        "elif": "else if",
        "abs(": "Math.abs(",
        "int(": "parseInt(",
        ".append(": ".push(",
        " and ": " && ",
        " or ": " || ",
        "...": "pass",
        " not ": " ! ",
        " == ": " === ",
        "True": "true",
        "False": "false",

        "self.": "this.",
        "function __init__": "constructor",
        "def __init__(": "constructor",
        "(self)": "()",
        "(self,": "(",
        ".pop(0)": ".shift()",
        "__str__": "toString",
    }
    for k, v in replaceDic.items():
        res = res.replace(k, v)
    return res


def isPrintLine(line: str) -> bool:
    """判断这一行是否是打印行"""
    return "print(" in line


def isCommonLine(line: str) -> bool:
    """判断这一行是否是注释行
    传入的是python字符串"""
    return " #" in line


def isSetValueLine(word: str) -> bool:
    """判断一行是否是变量赋值行"""
    words = [
        "print",
        "console.log",
        "while",
        "for",
        "elif",
        "else if",
    ]
    if " = " in word:
        for keyWord in words:
            if keyWord in word:
                return False
        return True
    else:
        return False


def setValue(pyStr: str) -> str:
    """把一个python赋值语句转化成js的"""
    # [    a = 12] => [    let a = 12]
    # 获取变量字符串
    spaceN = getLeftCount(pyStr, " ")
    res = pyStr[:spaceN] + "let " + pyStr[spaceN:]
    return res


def getFirstWord(lineStr: str) -> str:
    """获取这个行代码的第一个关键字, 如果没有关键字就返回空字符串"""
    res = ""
    strip = lineStr.strip()
    if len(strip) == 0:
        return ""
    if strip[0].isalpha():
        for char in strip:
            if char.isalpha():
                res += char
            else:
                break
    return res


def getLeftCount(string: str, char: str) -> int:
    """获取一个字符串左侧有多少个字符"""
    res = 0
    for c in string:
        if c == char:
            res += 1
        else:
            break
    return res


def getParInner(line: str) -> str:
    """获取一行中第一次发现括号中最外层括号里面内容
    for i in range(100)    100
    for i in range(len(arr))  len(arr)
    """
    res = ""
    find = False
    stackN = 0
    for char in line:
        if char == "(" and not find:
            find = True
            stackN += 1
            continue
        if find:
            if char == "(":
                stackN += 1
            if char == ")":
                stackN -= 1
                if stackN <= 0:
                    return res
            res += char
            ...
    return res


def test():
    print(getParInner("for i in range(1324):"))
    print(getParInner("for i in range(len(arr)):"))
    print(getParInner("for i in range(len(en(111), ())):"))
    ...


if __name__ == "__main__":
    main()
    # test()

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值