使用ANTLR4解析Yaml,JSON和Latex

文章目录

    • ANTLR4基本使用
      • **1. 安装 Java 运行时(必需)**
      • **2. 安装 ANTLR4 命令行工具**
        • **方法一:通过包管理器(推荐)**
          • **macOS/Linux (Homebrew)**
          • **Windows (Chocolatey)**
        • **方法二:手动安装(通用)**
      • **3. 验证安装**
      • **4. 配置环境变量(可选)**
        • **macOS/Linux**
        • **Windows**
      • **5. 使用示例**
        • **(1) 生成解析器**
        • **(2) 测试语法树**
      • **6. 开发工具集成**
        • **Visual Studio Code**
        • **IntelliJ IDEA**
      • **常见问题解决**
    • YAML
      • 1. YAML 语法文件 (`YAML.g4`)
      • 2. 语法说明
      • 3. 生成解析器
      • 4. 解析树可视化
      • 5. 支持的 YAML 特性
      • 6. 扩展建议
      • 7. 完整解析流程
    • JSON
      • 1. JSON 语法文件 (`JSON.g4`)
      • 2. 语法说明
      • 3. 生成解析器
      • 4. 解析树可视化
      • 5. 支持的 JSON 特性
      • 6. 扩展建议
      • 7. 性能优化
    • Latex
      • 1. LaTeX 语法文件 (`LaTeX.g4`)
      • 2. 语法树结构说明
      • 3. 解析示例
        • 输入 LaTeX 文件 (`example.tex`):
        • Java 解析代码:
        • 生成的解析树结构:
      • 4. 关键特性支持
      • 5. 扩展建议
      • 6. 典型应用场景

最近接触到数学公式的解析,然后和ANTLR4进行了一场遭遇战。

以下是使用 ANTLR4 解析 YAML 文件的完整语法文件 (YAML.g4) 和解析示例:

ANTLR4基本使用

以下是安装 ANTLR4 命令行工具的详细步骤,适用于主流操作系统:


1. 安装 Java 运行时(必需)

ANTLR4 是基于 Java 的工具,需先安装 Java 11+

# 检查是否已安装 Java
java -version
  • 如果未安装,从 Oracle JDK 或 OpenJDK 下载。

2. 安装 ANTLR4 命令行工具

方法一:通过包管理器(推荐)
macOS/Linux (Homebrew)
brew install antlr
Windows (Chocolatey)
choco install antlr4
方法二:手动安装(通用)
  1. 下载最新版 ANTLR4 JAR 文件:

    curl -O https://www.antlr.org/download/antlr-4.12.0-complete.jar
    

    替换 4.12.0 为官网最新版本号。

  2. 将 JAR 文件移动到固定目录(如 ~/lib/antlr):

    mkdir -p ~/lib/antlr
    mv antlr-4.12.0-complete.jar ~/lib/antlr/
    
  3. 添加别名到 Shell 配置文件(.bashrc/.zshrc/.bash_profile):

    # ANTLR4 别名
    alias antlr4='java -jar ~/lib/antlr/antlr-4.12.0-complete.jar'
    alias grun='java org.antlr.v4.gui.TestRig'
    

    然后执行:

    source ~/.bashrc  # 或对应配置文件
    

3. 验证安装

antlr4

如果看到以下输出,表示安装成功:

ANTLR Parser Generator  Version 4.12.0
...

4. 配置环境变量(可选)

若不想用别名,可将 ANTLR4 加入 PATH

macOS/Linux
export CLASSPATH=".:~/lib/antlr/antlr-4.12.0-complete.jar:$CLASSPATH"
export PATH="$PATH:~/lib/antlr"
Windows
  1. 右键“此电脑” → 属性 → 高级系统设置 → 环境变量
  2. PATH 中添加 ANTLR4 JAR 所在目录
  3. 新建 CLASSPATH 变量,值为 .;C:\path\to\antlr-4.12.0-complete.jar

5. 使用示例

(1) 生成解析器
antlr4 YourGrammar.g4  # 生成词法/语法分析器
javac *.java           # 编译生成的 Java 文件
(2) 测试语法树
grun YourGrammar ruleName -gui  # 可视化解析树

输入文本后按 Ctrl+D (macOS/Linux) 或 Ctrl+Z (Windows) 结束输入。


6. 开发工具集成

Visual Studio Code
  1. 安装扩展:
    • ANTLR4 Grammar Syntax Support
  2. 右键 .g4 文件 → “Generate ANTLR Code”
IntelliJ IDEA
  1. 安装插件:
    • ANTLR v4 grammar plugin (内置)
  2. 右键 .g4 文件 → “Generate ANTLR Recognizer”

常见问题解决

  1. antlr4: command not found
    检查别名或环境变量配置是否正确。

  2. Java 版本不兼容
    确保使用 Java 11+:

    java -version
    
  3. 无法生成代码
    检查语法文件是否有错误,或尝试手动指定输出目录:

    antlr4 -o ./output YourGrammar.g4
    

通过以上步骤,您可以在任何主流操作系统上安装并运行 ANTLR4 命令行工具。如需更高级的功能(如自定义 Visitor/Listener),可参考 ANTLR4 官方文档。

YAML

1. YAML 语法文件 (YAML.g4)

grammar YAML;// 语法规则
document: blockMapping?;blockMapping: blockPair+;blockPair: key ':' value;key: SCALAR;value: SCALAR| blockMapping| blockSequence;blockSequence: '-' value ('\n' '-' value)*;// 词法规则
SCALAR: UNQUOTED_SCALAR| SINGLE_QUOTED_SCALAR| DOUBLE_QUOTED_SCALAR;UNQUOTED_SCALAR: [a-zA-Z0-9_\-\.]+;SINGLE_QUOTED_SCALAR: '\'' (~['\n] | '\'\'')* '\'';DOUBLE_QUOTED_SCALAR: '"' (~["\n] | '\\"')* '"';COMMENT: '#' ~[\n]* -> skip;WS: [ \t\r\n]+ -> skip;// 特殊字符处理
COLON : ':' ;
DASH  : '-' ;

2. 语法说明

  1. 文档结构

    • 一个 YAML 文档由可选的 blockMapping 组成
    • blockMapping 包含多个键值对 (blockPair)
  2. 键值对

    • 键 (key) 必须是标量 (SCALAR)
    • 值 (value) 可以是:
      • 标量
      • 嵌套的映射 (blockMapping)
      • 序列 (blockSequence)
  3. 序列

    • - 开头
    • 可以包含多行
  4. 标量类型

    • 未加引号的 (UNQUOTED_SCALAR):字母数字、下划线、连字符、点
    • 单引号 (SINGLE_QUOTED_SCALAR):支持单引号转义 ('')
    • 双引号 (DOUBLE_QUOTED_SCALAR):支持反斜杠转义 (\")
  5. 忽略

    • 注释 (# 开头)
    • 空白字符 (空格、制表符、换行)

3. 生成解析器

  1. 使用 ANTLR4 工具生成代码:
antlr4 YAML.g4
javac YAML*.java
  1. 使用生成的解析器 (Java 示例):
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;public class YAMLParserExample {public static void main(String[] args) throws Exception {String yaml = """name: John Doeage: 30address:street: 123 Main Stcity: Anytownhobbies:- hiking- reading""";CharStream input = CharStreams.fromString(yaml);YAMLLexer lexer = new YAMLLexer(input);CommonTokenStream tokens = new CommonTokenStream(lexer);YAMLParser parser = new YAMLParser(tokens);ParseTree tree = parser.document();// 打印解析树System.out.println(tree.toStringTree(parser));}
}

4. 解析树可视化

使用 ANTLR 的 grun 工具查看解析树:

grun YAML document -gui <<EOF
name: John Doe
age: 30
EOF

5. 支持的 YAML 特性

特性是否支持示例
键值对key: value
嵌套映射parent: {child: value}
列表- item1\n- item2
多行字符串`text:
锚点与引用&anchor\n key: value
复杂数据类型!!timestamp 2023-01-01

6. 扩展建议

  1. 支持多行字符串
    添加 MULTILINE_SCALAR 规则:

    MULTILINE_SCALAR: '|' '\n' (' ' | '\t')* ~[\n]* ('\n' (' ' | '\t')* ~[\n]*)*;
    
  2. 支持类型标签

    value: SCALAR| tag SCALAR| blockMapping| blockSequence;tag : '!!' [a-zA-Z]+ ;
    
  3. 错误处理
    添加 error 规则捕获非法输入:

    ERROR_CHAR : . ;
    

7. 完整解析流程

graph TDA[YAML 输入] --> B[词法分析 (Lexer)]B --> C[Token 流]C --> D[语法分析 (Parser)]D --> E[解析树]E --> F[遍历树 (Visitor/Listener)]

这个语法文件提供了 YAML 的核心功能解析,可根据实际需求进一步扩展。

JSON

以下是适用于 ANTLR4 的 JSON 语法文件 (JSON.g4),完整支持 JSON 标准(RFC 8259):


1. JSON 语法文件 (JSON.g4)

grammar JSON;// 语法规则
json: value;value: object| array| STRING| NUMBER| 'true'| 'false'| 'null';object: '{' pair (',' pair)* '}'| '{' '}';pair: STRING ':' value;array: '[' value (',' value)* ']'| '[' ']';// 词法规则
STRING: '"' (ESC | SAFE_CHAR)* '"';fragment ESC: '\\' (["\\/bfnrt] | UNICODE);fragment UNICODE: 'u' HEX HEX HEX HEX;fragment HEX: [0-9a-fA-F];fragment SAFE_CHAR: ~["\\\u0000-\u001F];NUMBER: '-'? INT ('.' [0-9]+)? EXP?;fragment INT: '0' | [1-9] [0-9]*;fragment EXP: [Ee] [+-]? [0-9]+;WS: [ \t\n\r]+ -> skip;

2. 语法说明

  1. 结构定义

    • json: 根规则,表示一个 JSON 文档
    • value: 可以是对象、数组、字符串、数字、布尔值或 null
    • object: 键值对集合(如 {"key": "value"}
    • array: 值列表(如 [1, "a", true]
  2. 词法规则

    • STRING: 支持转义字符(\n, \uXXXX 等)
    • NUMBER: 支持整数、浮点数和科学计数法
    • WS: 跳过空白字符
  3. 严格校验

    • 字符串必须用双引号(")包裹
    • 不允许尾随逗号(如 [1, 2,] 会报错)

3. 生成解析器

  1. 生成 Java 代码

    antlr4 JSON.g4
    javac JSON*.java
    
  2. 测试解析(Java 示例):

    import org.antlr.v4.runtime.*;
    import org.antlr.v4.runtime.tree.*;public class JSONParserExample {public static void main(String[] args) throws Exception {String json = """{"name": "Alice","age": 30,"scores": [90, 85, 95]}""";CharStream input = CharStreams.fromString(json);JSONLexer lexer = new JSONLexer(input);CommonTokenStream tokens = new CommonTokenStream(lexer);JSONParser parser = new JSONParser(tokens);ParseTree tree = parser.json(); // 从根规则开始解析System.out.println(tree.toStringTree(parser));}
    }
    

4. 解析树可视化

使用 ANTLR 的 grun 工具查看解析树:

grun JSON json -gui <<EOF
{"key": "value"}
EOF

会显示如下结构:

(json (value (object { (pair "key" : (value "value")) })))

5. 支持的 JSON 特性

特性示例是否支持
对象{"key": "value"}
数组[1, "a", true]
嵌套结构{"a": {"b": [1, 2]}}
字符串转义"Line\nBreak"
Unicode 字符"\u03B1" (α)
科学计数法数字1.23e-4
布尔值/nulltrue, false, null
尾随逗号{"a": 1,}
单引号字符串{'key': 'value'}

6. 扩展建议

  1. 支持注释(非标准 JSON):

    COMMENT: '/*' .*? '*/' -> skip| '//' ~[\n]* -> skip;
    
  2. 宽松模式(允许尾随逗号):

    object: '{' pair (',' pair)* ','? '}'| '{' '}';
    
  3. 自定义错误处理

    parser.addErrorListener(new BaseErrorListener() {@Overridepublic void syntaxError(...) {throw new RuntimeException("Syntax error at line " + line + ":" + charPositionInLine + " - " + msg);}
    });
    

7. 性能优化

  1. 预编译解析器:在多次解析时复用 Lexer/Parser 实例
  2. 关闭冗余功能:禁用 ANTLRErrorListener 提升速度
    lexer.removeErrorListeners();
    parser.removeErrorListeners();
    

此语法文件完全兼容标准 JSON,可直接用于构建 JSON 解析器、验证器或转换工具。如需处理非标准 JSON(如带注释的配置文件),按需扩展即可。

Latex

以下是适用于 ANTLR4 的 LaTeX 语法文件 (LaTeX.g4),定义了包含 documentclasssectionitemtask 等常见标记的语法树结构:


1. LaTeX 语法文件 (LaTeX.g4)

grammar LaTeX;// 语法规则
document: preamble? (section | item | task | textContent)*;preamble: '\\documentclass' '{' ID '}' ('[' options ']')?;section: '\\section' '{' textContent '}' (subsection)?;subsection: '\\subsection' '{' textContent '}';item: '\\item' (textContent | itemize | enumerate);itemize: '\\begin{itemize}' item* '\\end{itemize}';enumerate: '\\begin{enumerate}' item* '\\end{enumerate}';task: '\\task' '{' textContent '}' ('\\solution' '{' textContent '}')?;textContent: (TEXT | COMMAND | MATH)+;// 词法规则
COMMAND: '\\' [a-zA-Z]+;MATH: '$' .*? '$';ID: [a-zA-Z]+;TEXT: ~[\\{}[\]]+;OPTION_SEP: ',';LBRACE : '{';
RBRACE : '}';
LBRACK : '[';
RBRACK : ']';WS: [ \t\r\n]+ -> skip;// 复合规则
options: ID (OPTION_SEP ID)*;

2. 语法树结构说明

  1. 文档结构

    Document
    Preamble
    Section
    Item
    Task
    TextContent
  2. 节点类型

    • preamble: \documentclass 声明
    • section/subsection: 章节标题
    • item: 列表项(可嵌套在 itemizeenumerate 中)
    • task: 自定义任务环境(带可选的 \solution
    • textContent: 文本、命令或数学公式的混合内容
  3. 嵌套规则

    • 列表可以嵌套 (item 包含 itemize/enumerate)
    • textContent 可以包含任意文本和命令

3. 解析示例

输入 LaTeX 文件 (example.tex):
\documentclass{article}
\section{Introduction}
This is a \textbf{test}.
\begin{itemize}\item First point\item Second point with math: $E=mc^2$
\end{itemize}
\task{Solve the equation}{ \solution{ $x=1$ } }
Java 解析代码:
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;public class LaTeXParserExample {public static void main(String[] args) throws Exception {CharStream input = CharStreams.fromFileName("example.tex");LaTeXLexer lexer = new LaTeXLexer(input);CommonTokenStream tokens = new CommonTokenStream(lexer);LaTeXParser parser = new LaTeXParser(tokens);ParseTree tree = parser.document();// 打印解析树System.out.println(tree.toStringTree(parser));// 使用Visitor遍历new LaTeXBaseVisitor<Void>() {@Overridepublic Void visitSection(LaTeXParser.SectionContext ctx) {System.out.println("Section: " + ctx.textContent().getText());return super.visitSection(ctx);}}.visit(tree);}
}
生成的解析树结构:
(document (preamble \documentclass { article }) (section \section { Introduction } (textContent This is a \textbf { test })) (itemize (item \item (textContent First point)) (item \item (textContent Second point with math: $E=mc^2$))) (task \task { Solve the equation } (solution \solution { $x=1$ })))

4. 关键特性支持

LaTeX 结构是否支持示例
文档类声明\documentclass{article}
章节标题\section{Introduction}
无序列表\itemize \item ...
有序列表\enumerate \item ...
自定义命令\textbf{text}
数学公式$E=mc^2$
自定义环境\task{...}\solution{...}
可选参数\documentclass[12pt]{...}
嵌套结构列表中的列表

5. 扩展建议

  1. 支持更多环境

    figure: '\\begin{figure}' ('[' options ']')? content '\\end{figure}';
    
  2. 完善数学公式

    MATH: '$' .*? '$'| '\\[' .*? '\\]';
    
  3. 错误恢复
    添加 error 规则:

    UNKNOWN_CMD: '\\' ~[a-zA-Z] -> skip;
    
  4. 注释处理

    COMMENT: '%' ~[\n]* -> skip;
    

6. 典型应用场景

  1. LaTeX 文档分析

    • 提取所有章节标题
    • 统计数学公式数量
  2. 自动化批改系统

    • 解析 \task\solution 环境
    • 对比学生答案与标准解
  3. 文档转换

    • 将 LaTeX 列表转为 Markdown
    • 提取文档结构生成目录

这个语法文件提供了 LaTeX 的核心结构解析,可根据实际需求进一步扩展复杂环境(如表格、图表等)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/75975.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NixVis 开源轻量级 Nginx 日志分析工具

NixVis NixVis 是一款基于 Go 语言开发的、开源轻量级 Nginx 日志分析工具&#xff0c;专为自部署场景设计。它提供直观的数据可视化和全面的统计分析功能&#xff0c;帮助您实时监控网站流量、访问来源和地理分布等关键指标&#xff0c;无需复杂配置即可快速部署使用。 演示…

黑盒测试的等价类划分法(输入数据划分为有效的等价类和无效的等价类)

重点: 有效等价和单个无效等价各取1个即可 1、正向用例:一条尽可能覆盖多条2、逆向用例:每一条数据&#xff0c;都是一条单独用例。 步骤: 1、明确需求 2、确定有效和无效等价 3、根据有效和无效造数据编写用例 3、适用场景 针对:需要有大量数据测试输入&#xff0c; …

Linux Mem -- 通过reserved-memory缩减内存

目录 1. reserved-memory缩减内存 2. 为什么要通过2段512GB预留内存实现该缩减呢&#xff1f; 3. reserved-momery中的no-map属性 4. 预留的的内存是否会被统计到系统MemTotal中&#xff1f; 本文是解决具体的一些思考总结&#xff0c;和Linux内核的reserved-memory机制相关…

多线程—synchronized原理

上篇文章&#xff1a; 多线程—锁策略https://blog.csdn.net/sniper_fandc/article/details/146508232?fromshareblogdetail&sharetypeblogdetail&sharerId146508232&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link 目录 1 synchronized的锁…

AWS混合云部署实战:打造企业级数字化转型的“黄金架构”

引言 “上云是必然&#xff0c;但全部上云未必是必然。”在数字化转型的深水区&#xff0c;企业面临的核心矛盾日益凸显&#xff1a;如何在享受公有云敏捷性的同时&#xff0c;满足数据主权、低延迟和遗留系统兼容的刚性需求&#xff1f; AWS混合云凭借“云上云下一张网”的独…

进程模型5-0号进程

内核版本架构作者GitHubCSDNLinux-3.0.1armv7-ALux1206 0号进程的作用 在 Linux 中除了 init_task 0号进程&#xff0c;所有的线/进程都是通过 do_fork 函数复制父线/进程创建得到&#xff0c;因为 0号进程产生时没有任何进程可以参照&#xff0c;只能通过静态方式构造进程描述…

计算机二级考前急救(Word篇)

重点题&#xff08;20套&#xff0c;标黄为精选10套&#xff09;&#xff1a;4&#xff0c;15&#xff0c;17&#xff0c;19&#xff0c;21&#xff0c;24&#xff0c;25&#xff0c;27&#xff0c;36&#xff0c;40&#xff0c;12&#xff0c;18&#xff0c;20&#xff0c;22&…

constant(safe-area-inset-bottom)和env(safe-area-inset-bottom)在uniapp中的使用方法解析

在微信小程序中&#xff0c;padding-bottom: constant(safe-area-inset-bottom); 和 padding-bottom: env(safe-area-inset-bottom); 这两个 CSS 属性用于处理 iPhone X 及更高版本设备的安全区域&#xff08;safe area&#xff09;。这些设备的底部有一个“Home Indicator”&a…

十二、Cluster集群

目录 一、集群简介1、现状问题2、集群作用 二、集群结构设计1、集群存储设2、消息通信设计 三、Cluster集群三主三从结构搭建1、redis.conf配置文件可配置项2、配置集群3、链接集群4、命令客户端连接集群并使用 四、集群扩容1、添加节点2、槽位分配3、添加从节点 五、集群缩容1…

Java基础 3.29

1.数组的相关注意事项 错误示范一 String strs[] new String[2]{"a", "b"}; 正确示范一 String strs[] new String[]{"a", "b"}; 让JVM自己判断有几个数据&#xff0c;无需再其中写明有几组数据 错误示范二 String strs[] new…

从入门到精通:HTML 项目实战中的学习进度(一)

一、基础夯实阶段 1.1 HTML 文档结构与核心语法 在 HTML5 的世界里&#xff0c;构建一个文档就像是搭建一座大厦&#xff0c;坚实的基础至关重要。HTML5 文档的基础框架以<!DOCTYPE html>声明开场&#xff0c;这就好比是给浏览器下达的一份 “指令书”&#xff0c;明确…

FFmpeg —— 实时绘制音频波形图(附源码)

🔔 FFmpeg 相关音视频技术、疑难杂症文章合集(掌握后可自封大侠 ⓿_⓿)(记得收藏,持续更新中…) 实时绘制音频波形图 步骤                 FFmpeg打开媒体文件,读取每一包数据,将音频数据包进行缓冲,一包一包处理音频缓冲,对音频缓冲包进行解码,读…

大数据学习(88)-zookeeper实现的高可用(HA)

&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一…

基于MFC按钮逻辑

void CSUCCES1Dlg::SetDlgItemState()//IDC_BTN_INIT初始化按钮 { GigeState state = GigeState::ARV_NONE;//GigeState是一个枚举类型,stat状态为ARV_NONE int idx = ((CListBox*)GetDlgItem(IDC_LIST_GIGE))->GetCurSel();//GetDlgItem 是 MFC 框架提供的一个成员…

EF Core 乐观并发控制(并发令牌)

文章目录 前言一、乐观并发的核心思想二、实现方法1&#xff09;使用并发令牌&#xff08;Concurrency Token&#xff09;2&#xff09;处理并发冲突 三、工作原理四、适用场景五、与悲观并发的对比六、最佳实践总结 前言 Entity Framework (EF) Core 默认支持 乐观并发控制&a…

解决 FFmpeg 使用 C/C++ 接口时,解码没有 shell 快的问题(使用多线程)

一、问题 硬件设备为香橙派 5Plus&#xff0c;最近需要使用硬件视频解码来加速 YOLO 的检测&#xff0c;shell 窗口的FFmpeg已经调通&#xff0c;详见文章&#xff1a; 编译支持 RKmpp 和 RGA 的 ffmpeg 源码_rk3588 ffmpeg mpp-CSDN博客https://blog.csdn.net/plmm__/article…

工业控制网络中常用的通信协议

1. 现场总线协议 Modbus 概述&#xff1a;Modbus 是最广泛使用的工业协议之一&#xff0c;主要用于串行通信&#xff0c;支持主/从架构&#xff0c;通过 RS-232 或 RS-485 传输&#xff0c;也有基于以太网的 Modbus TCP 版本。特点&#xff1a;简单易用&#xff0c;易于实现&am…

【Mac】npm error Error: EACCES: permission denied, mkdir‘/Users/...

问题描述&#xff1a;Mac电脑中的 vscode 下载依赖的时候提示没有权限&#xff1a; 故障分析 首先账号是有权限的&#xff0c;电脑就建了一个账号是管理员&#xff1b;在桌面用shell直接执行命令npm init 命令可以执行成功&#xff0c;那么问题就出在vscodes上面了&#xff0…

Ruby 简介

Ruby 简介 引言 Ruby 是一种广泛使用的动态、开源的编程语言,自 1995 年由日本程序员 Yukihiro Matsumoto(通称 Matz)设计以来,它以其优雅的语法、强大的库支持和跨平台特性赢得了全球开发者的青睐。本文将详细介绍 Ruby 的起源、特点、应用领域以及它在现代软件开发中的…

[Qt5] QMetaObject::invokeMethod使用

&#x1f4e2;博客主页&#xff1a;https://loewen.blog.csdn.net&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由 丶布布原创&#xff0c;首发于 CSDN&#xff0c;转载注明出处&#x1f649;&#x1f4e2;现…