go语言写long解释器已开源
合作交流QQ1842810327 微信1842810327
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("请提供源文件名作为参数.")
return
}
sourceFileName := os.Args[1]
sourceFile, err := os.Open(sourceFileName)
if err != nil {
fmt.Println("Error opening source file:", err)
return
}
defer sourceFile.Close()
fmt.Println("成功打开文件:", sourceFileName)
outputFileName := strings.TrimSuffix(sourceFileName, ".txt") + ".html"
outputFile, err := os.Create(outputFileName)
if err != nil {
fmt.Println("Error creating output file:", err)
return
}
defer outputFile.Close()
fmt.Println("成功创建文件:", outputFileName)
// 写入 HTML 文件的头部
_, err = outputFile.WriteString("<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>合成后的 HTML</title>\n<style>\n.tab {display: none;}\n.active {display: block;}\n.tab-button {cursor: pointer; margin-right: 10px;}\n.tab-container {position: fixed; bottom: 0; left: 0; right: 0; display: flex; justify-content: space-around; background-color: #f1f1f1; padding: 10px; box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);}\n</style>\n</head>\n<body>\n")
if err != nil {
fmt.Println("Error writing to output file:", err)
return
}
reader := bufio.NewReader(sourceFile)
var tabs []string
var tabContents = make(map[string]string)
for {
line, err := reader.ReadString('\n')
if err != nil {
break
}
line = strings.TrimSpace(line)
if strings.Contains(line, "{") { // 处理 tab 内容
tabName := extractValue(line)
content := parseTabContent(reader) // 解析 tab 内容
tabContents[tabName] = content
tabs = append(tabs, tabName)
} else {
html := processLine(line, &tabs)
if html != "" {
_, err = outputFile.WriteString(html + "\n")
if err != nil {
fmt.Println("Error writing to output file:", err)
return
}
}
}
}
// 生成 tab 按钮和内容
if len(tabs) > 0 {
_, err = outputFile.WriteString("<div class=\"tab-container\">\n")
for _, tab := range tabs {
_, err = outputFile.WriteString(fmt.Sprintf("<span class=\"tab-button\" onclick=\"showTab('%s')\">%s</span>\n", tab, tab))
}
_, err = outputFile.WriteString("</div>\n")
if err != nil {
fmt.Println("Error writing to output file:", err)
return
}
for tabName, content := range tabContents {
_, err = outputFile.WriteString(fmt.Sprintf("<div class=\"tab\" id=\"%s\">%s</div>\n", tabName, content))
if err != nil {
fmt.Println("Error writing to output file:", err)
return
}
}
}
// 在文件末尾写入 JavaScript 代码和关闭 HTML
_, err = outputFile.WriteString(`
<script>
function showTab(tabName) {
var i, tab, buttons;
tab = document.getElementsByClassName("tab");
for (i = 0; i < tab.length; i++) {
tab[i].style.display = "none";
}
document.getElementById(tabName).style.display = "block";
}
</script>
</body>\n</html>`)
if err != nil {
fmt.Println("Error writing to output file:", err)
return
}
fmt.Printf("HTML 文件生成成功: %s\n", outputFileName)
}
func parseTabContent(reader *bufio.Reader) string {
var content string
for {
line, err := reader.ReadString('\n')
if err != nil {
break
}
line = strings.TrimSpace(line)
if strings.HasSuffix(line, "};") {
break
}
content += processLine(line, nil) + "\n"
}
return content
}
func processLine(line string, tabs *[]string) string {
if strings.HasPrefix(line, "button(") {
return generateButton(line)
} else if strings.HasPrefix(line, "text(") {
return generateText(line)
} else if strings.HasPrefix(line, "input(") {
return generateInputField(line)
} else if strings.HasPrefix(line, "tab(") {
return generateTab(line, tabs)
} else if strings.HasPrefix(line, "image(") {
return generateImage(line)
} else if strings.HasPrefix(line, "music(") {
return generateMusic(line)
} else if strings.HasPrefix(line, "video(") {
return generateVideo(line)
}
// 处理其他类型的内容
parts := strings.Split(line, ".")
if len(parts) == 0 {
return ""
}
title := parts[0]
style := extractStyles(parts[1:])
if style != "" {
html := fmt.Sprintf("<div style=\"%s\" class=\"tab\" id=\"%s\">%s</div>", style, title, title)
return html
}
return ""
}
func generateImage(line string) string {
imageUrl := extractValue(line)
style := extractStyles(strings.Split(line, ".")[1:])
if imageUrl == "" {
return ""
}
return fmt.Sprintf("<img src=\"%s\" style=\"%s; width: %s; height: %s;\">", imageUrl, style)
}
func generateMusic(line string) string {
musicUrl := extractValue(line)
style := extractStyles(strings.Split(line, ".")[1:])
if musicUrl == "" {
return ""
}
return fmt.Sprintf("<audio controls style=\"%s\"><source src=\"%s\" type=\"audio/mpeg\">你的浏览器不支持音频元素。</audio>", style, musicUrl)
}
func generateVideo(line string) string {
videoUrl := extractValue(line)
style := extractStyles(strings.Split(line, ".")[1:])
if videoUrl == "" {
return ""
}
return fmt.Sprintf("<video controls style=\"%s\"><source src=\"%s\" type=\"video/mp4\">你的浏览器不支持视频元素。</video>", style, videoUrl)
}
func generateText(line string) string {
textContent := extractValue(line)
style := extractStyles(strings.Split(line, ".")[1:])
if textContent == "" {
return ""
}
return fmt.Sprintf("<div style=\"%s\">%s</div>", style, textContent)
}
func generateButton(line string) string {
label := extractValue(line)
style := extractStyles(strings.Split(line, ".")[1:])
alertMessage := extractAlertMessage(line)
if label == "" {
return ""
}
if alertMessage != "" {
return fmt.Sprintf("<button style=\"%s\" onclick=\"alert('%s')\">%s</button>", style, escapeJavaScript(alertMessage), label)
}
return fmt.Sprintf("<button style=\"%s\">%s</button>", style, label)
}
// escapeJavaScript 函数用于处理字符串中的特殊字符
func escapeJavaScript(message string) string {
message = strings.ReplaceAll(message, "'", "\\'")
message = strings.ReplaceAll(message, "\"", "\\\"")
message = strings.ReplaceAll(message, "\n", "\\n")
return message
}
func generateInputField(line string) string {
placeholder := extractValue(line)
style := extractStyles(strings.Split(line, ".")[1:])
if placeholder == "" {
return ""
}
return fmt.Sprintf("<input type=\"text\" placeholder=\"%s\" style=\"%s\">", placeholder, style)
}
func generateTab(line string, tabs *[]string) string {
tabName := extractValue(line)
style := extractStyles(strings.Split(line, ".")[1:])
if tabName != "" {
*tabs = append(*tabs, tabName)
return fmt.Sprintf("<div style=\"%s\" class=\"tab\" id=\"%s\">%s 内容</div>", style, tabName, tabName)
}
return ""
}
func extractStyles(parts []string) string {
style := ""
for _, part := range parts {
if strings.HasPrefix(part, "fontSize(") {
size := extractValue(part)
style += fmt.Sprintf("font-size: %s;", size)
} else if strings.HasPrefix(part, "color(") {
color := extractValue(part)
style += fmt.Sprintf("color: %s;", color)
} else if strings.HasPrefix(part, "left(") {
left := extractValue(part)
style += fmt.Sprintf("margin-left: %s;", left)
} else if strings.HasPrefix(part, "right(") {
right := extractValue(part)
style += fmt.Sprintf("margin-right: %s;", right)
} else if strings.HasPrefix(part, "top(") {
top := extractValue(part)
style += fmt.Sprintf("margin-top: %s;", top)
} else if strings.HasPrefix(part, "bottom(") {
bottom := extractValue(part)
style += fmt.Sprintf("margin-bottom: %s;", bottom)
} else if strings.HasPrefix(part, "width(") {
width := extractValue(part)
style += fmt.Sprintf("width: %s;", width)
} else if strings.HasPrefix(part, "height(") {
height := extractValue(part)
style += fmt.Sprintf("height: %s;", height)
}
}
return style
}
func extractValue(part string) string {
start := strings.Index(part, "(")
end := strings.Index(part, ")")
if start != -1 && end != -1 && end > start {
return strings.TrimSpace(part[start+1 : end])
}
return ""
}
func extractAlertMessage(line string) string {
if strings.Contains(line, "alert(") {
// 找到 alert( 的位置
start := strings.Index(line, "alert(") + len("alert(")
// 在 alert( 之后找到对应的 )
end := strings.Index(line[start:], ")") + start
if end > start {
// 提取 alert 的内容
return line[start:end]
}
}
return ""
}
龙long语言代码 source.txt 见单词顾名思义 还是很容易看的
目前实现了tab组件 image组件 music组件 video组件 text组件 button组件 input组件
tab(首页).router(home).fontSize(20px).color(#FF00FF).left(50px).right(50px).top(50px).bottom(0px){
image(https://fastly.picsum.photos/id/740/200/200.jpg?hmac=9ZHqyCz7Gy7V9lyQcKw8m1VAVXW6mjx26txirRYVaSc).width(100px).height(100px).left(50px).right(50px).top(50px).bottom(50px);
music(http://downsc.chinaz.net/Files/DownLoad/sound1/201906/11582.mp3).width(500px).height(100px).left(50px).right(50px).top(50px).bottom(50px)
video(https://media.w3.org/2010/05/sintel/trailer.mp4).width(500px).height(500px).left(50px).right(50px).top(50px).bottom(50px)
};
tab(动态).router(dong).fontSize(20px).color(#FF00FF).left(50px).right(50px).top(50px).bottom(0px){
text(标题2).fontSize(50px).color(#FF00FF).left(10px).right(10px).top(10px).bottom(10px);
button(点击2).fontSize(20px).color(#FF00FF).left(50px).right(50px).top(50px).bottom(50px).alert(hello worid);
input(请输入内容).fontSize(18px).color(#000000).left(10px).right(10px).top(10px).bottom(10px);
};
tab(会员).router(huiyuan).fontSize(20px).color(#FF00FF).left(50px).right(50px).top(50px).bottom(0px){
text(标题3).fontSize(50px).color(#FF00FF).left(10px).right(10px).top(10px).bottom(10px);
button(点击3).fontSize(20px).color(#FF00FF).left(50px).right(50px).top(50px).bottom(50px).alert(hello worid);
input(请输入内容).fontSize(18px).color(#000000).left(10px).right(10px).top(10px).bottom(10px);
};
tab(我的).router(wode).fontSize(20px).color(#FF00FF).left(50px).right(50px).top(50px).bottom(0px){
text(标题4).fontSize(50px).color(#FF00FF).left(10px).right(10px).top(10px).bottom(10px);
button(点击4).fontSize(20px).color(#FF00FF).left(50px).right(50px).top(50px).bottom(50px).alert(hello worid);
input(请输入内容).fontSize(18px).color(#000000).left(10px).right(10px).top(10px).bottom(10px);
};
//source.txt go build -o long.exe main.go .\long.exe .\source.txt
使用 go build -o long.exe main.go 编程为解释器 long.exe
cmd中 .\long.exe .\source.txt 生成为source.html文件
生成后的文件如下
source.html
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>合成后的 HTML</title>
<style>
.tab {display: none;}
.active {display: block;}
.tab-button {cursor: pointer; margin-right: 10px;}
.tab-container {position: fixed; bottom: 0; left: 0; right: 0; display: flex; justify-content: space-around; background-color: #f1f1f1; padding: 10px; box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);}
</style>
</head>
<body>
<div class="tab-container">
<span class="tab-button" onclick="showTab('首页')">首页</span>
<span class="tab-button" onclick="showTab('动态')">动态</span>
<span class="tab-button" onclick="showTab('会员')">会员</span>
<span class="tab-button" onclick="showTab('我的')">我的</span>
</div>
<div class="tab" id="首页">
<img src="https://fastly.picsum.photos/id/740/200/200.jpg?hmac=9ZHqyCz7Gy7V9lyQcKw8m1VAVXW6mjx26txirRYVaSc" style="width: 100px;height: 100px;margin-left: 50px;margin-right: 50px;margin-top: 50px;margin-bottom: 50px;; width: %!s(MISSING); height: %!s(MISSING);">
<audio controls style="width: 500px;height: 100px;margin-left: 50px;margin-right: 50px;margin-top: 50px;margin-bottom: 50px;"><source src="http://downsc.chinaz.net/Files/DownLoad/sound1/201906/11582.mp3" type="audio/mpeg">你的浏览器不支持音频元素。</audio>
<video controls style="width: 500px;height: 500px;margin-left: 50px;margin-right: 50px;margin-top: 50px;margin-bottom: 50px;"><source src="https://media.w3.org/2010/05/sintel/trailer.mp4" type="video/mp4">你的浏览器不支持视频元素。</video>
</div>
<div class="tab" id="动态">
<div style="font-size: 50px;color: #FF00FF;margin-left: 10px;margin-right: 10px;margin-top: 10px;margin-bottom: 10px;">标题2</div>
<button style="font-size: 20px;color: #FF00FF;margin-left: 50px;margin-right: 50px;margin-top: 50px;margin-bottom: 50px;" onclick="alert('hello worid')">点击2</button>
<input type="text" placeholder="请输入内容" style="font-size: 18px;color: #000000;margin-left: 10px;margin-right: 10px;margin-top: 10px;margin-bottom: 10px;">
</div>
<div class="tab" id="会员">
<div style="font-size: 50px;color: #FF00FF;margin-left: 10px;margin-right: 10px;margin-top: 10px;margin-bottom: 10px;">标题3</div>
<button style="font-size: 20px;color: #FF00FF;margin-left: 50px;margin-right: 50px;margin-top: 50px;margin-bottom: 50px;" onclick="alert('hello worid')">点击3</button>
<input type="text" placeholder="请输入内容" style="font-size: 18px;color: #000000;margin-left: 10px;margin-right: 10px;margin-top: 10px;margin-bottom: 10px;">
</div>
<div class="tab" id="我的">
<div style="font-size: 50px;color: #FF00FF;margin-left: 10px;margin-right: 10px;margin-top: 10px;margin-bottom: 10px;">标题4</div>
<button style="font-size: 20px;color: #FF00FF;margin-left: 50px;margin-right: 50px;margin-top: 50px;margin-bottom: 50px;" onclick="alert('hello worid')">点击4</button>
<input type="text" placeholder="请输入内容" style="font-size: 18px;color: #000000;margin-left: 10px;margin-right: 10px;margin-top: 10px;margin-bottom: 10px;">
</div>
<script>
function showTab(tabName) {
var i, tab, buttons;
tab = document.getElementsByClassName("tab");
for (i = 0; i < tab.length; i++) {
tab[i].style.display = "none";
}
document.getElementById(tabName).style.display = "block";
}
</script>
</body>\n</html>