仓颉编程语言:语法节点

华为仓颉语言的技术梗概,底层原理是什么?什么架构,以后会替换JAVA语言了,信创背景下,要不要开始进入仓颉赛道,详细为您剖析仓颉语言 仓颉语言允许开发者定义自己的控制结构,通过使用闭包和高阶函数来实现。action();"); 阅读详情

在仓颉语言的编译过程中,首先通过词法分析将代码转换成 Tokens,然后对 Tokens 进行语法解析,得到一个语法树。每个语法树的节点可能是一个表达式、声明、类型、模式等。仓颉 ast 库提供了每种节点对应的类,它们之间具有适当的继承关系。其中,主要的抽象类如下:

  • Node:所有语法节点的父类
  • TypeNode:所有类型节点的父类
  • Expr:所有表达式节点的父类
  • Decl:所有声明节点的父类
  • Pattern:所有模式节点的父类

具体节点的类型众多,具体细节请参考 《仓颉编程语言库 API》文档。在下面的案例中,我们主要使用以下节点:

  • BinaryExpr:二元运算表达式
  • FuncDecl:函数的声明

节点的解析

通过 ast 库,基本上每种节点都可以从 Tokens 解析。有两种调用解析的方法。

使用解析表达式和声明的函数。

以下函数用于从 Tokens 解析任意的表达式或任意的声明:

  • parseExpr(input: Tokens): Expr:将输入的 Tokens 解析为表达式
  • parseExprFragment(input: Tokens, startFrom!: Int64 = 0): (Expr, Int64):将输入 Tokens 的一个片段解析为表达式,片段从 startFrom 索引开始,解析可能只消耗从索引 startFrom 开始的片段的一部分,并返回第一个未被消耗的 Token 的索引(如果消耗了整个片段,返回值为 input.size)
  • parseDecl(input: Tokens, astKind!: String = ""):将输入的 Tokens 解析为声明,astKind 为额外的设置,具体请见《仓颉编程语言库 API》文档。
  • parseDeclFragment(input: Tokens, startFrom!: Int64 = 0): (Decl, Int64):将输入 Tokens 的一个片段解析为声明,startFrom 参数和返回索引的含义和 parseExpr 相同。

我们通过代码案例展示这些函数的使用:

let tks1 = quote(a + b)
let tks2 = quote(a + b, x + y)
let tks3 = quote(
    func f1(x: Int64) { return x + 1 }
)
let tks4 = quote(
    func f1(x: Int64) { return x + 1 }
    func f2(x: Int64) { return x + 2 }
)

let binExpr1 = parseExpr(tks1)
println("binExpr1 is BinaryExpr: ${binExpr1 is BinaryExpr}")
let (binExpr2, mid) = parseExprFragment(tks2)
let (binExpr3, end) = parseExprFragment(tks2, startFrom: mid + 1) // 跳过逗号
println("size = ${tks2.size}, mid = ${mid}, end = ${end}")
let funcDecl1 = parseDecl(tks3)
println("funcDecl1 is FuncDecl: ${funcDecl1 is FuncDecl}")
let (funcDecl2, mid2) = parseDeclFragment(tks4)
let (funcDecl3, end2) = parseDeclFragment(tks4, startFrom: mid2)
println("size = ${tks4.size}, mid = ${mid2}, end = ${end2}")

输出结果是:

binExpr1 is BinaryExpr: true
size = 7, mid = 3, end = 7
funcDecl1 is FuncDecl: true
size = 29, mid = 15, end = 29

使用构造函数进行解析

大多数节点类型都支持 init(input: Tokens) 构造函数,将输入的 Tokens 解析为相应类型的节点,例如:

let binExpr = BinaryExpr(quote(a + b))
let funcDecl = FuncDecl(quote(func f1(x: Int64) { return x + 1 }))

如果解析失败将抛出异常。这种解析方式适用于类型已知的代码片段,解析后不需要再手动转换成具体的子类型。

节点的组成部分

从 Tokens 解析出节点之后,我们可以查看节点的组成部分。作为例子,我们列出 BinaryExpr 和 FuncDecl 的组成部分,关于其他节点的更详细的解释请见《仓颉编程语言库 API》文档。

  • BinaryExpr 节点:
    • leftExpr: Expr:运算符左侧的表达式
    • op: Token:运算符
    • rightExpr: Expr:运算符右侧的表达式
  • FuncDecl 节点(部分):
    • identifier: Token:函数名
    • funcParams: ArrayList<FuncParam>:参数列表
    • declType: TypeNode:返回值类型
    • block: Block:函数体
  • FuncParam节点(部分):
    • identifier: Token:参数名
    • paramType: TypeNode:参数类型
  • Block节点(部分):
    • nodes: ArrayList<Node>:块中的表达式和声明

每个组成部分都是 public mut prop,因此可以被查看和更新。我们通过一些例子展示更新的结果。

BinaryExpr 案例

let binExpr = BinaryExpr(quote(x * y))
binExpr.leftExpr = BinaryExpr(quote(a + b))
println(binExpr.toTokens())

binExpr.op = Token(TokenKind.ADD)
println(binExpr.toTokens())

输出结果是:

(a + b) * y
a + b + y

首先,通过解析,获得 binExpr 为节点 x * y,图示如下:

    *
  /   \
 x     y

第二步,我们将左侧的节点(即 x)替换为 a + b,因此,获得的语法树如下:

      *
    /   \
   +     y
  / \
 a   b

当输出这个语法树的时候,我们必须在 a + b 周围添加括号,得到 (a + b) * y(如果输出a + b * y,含义为先做乘法,再做加法,与语法树的含义不同)。**ast 库具备在输出语法树时自动添加括号的功能**。

第三步,我们将语法树根部的运算符从 * 替换为 +,因此得到语法树如下:

      +
    /   \
   +     y
  / \
 a   b

这个语法树可以输出为 a + b + y,因为加法本身就是左结合的,不需要在左侧添加括号。

FuncDecl 案例

let funcDecl = FuncDecl(quote(func f1(x: Int64) { x + 1 }))
funcDecl.identifier = Token(TokenKind.IDENTIFIER, "foo")
println("Number of parameters: ${funcDecl.funcParams.size}")
funcDecl.funcParams[0].identifier = Token(TokenKind.IDENTIFIER, "a")
println("Number of nodes in body: ${funcDecl.block.nodes.size}")
let binExpr = (funcDecl.block.nodes[0] as BinaryExpr).getOrThrow()
binExpr.leftExpr = parseExpr(quote(a))
println(funcDecl.toTokens())

在这个案例中,我们首先通过解析构造出了一个 FuncDecl 节点,然后分别修改了该节点的函数名、参数名,以及函数体中表达式的一部分。输出结果是:

Number of parameters: 1
Number of nodes in body: 1
func foo(a: Int64) {
    a + 1
}

使用 quote 插值语法节点

任何 AST 节点都可以在 quote 语句中插值,部分 AST 节点的 ArrayList 列表也可以被插值(主要对应实际情况中会出现这类节点列表的情况)。插值直接通过 $(node) 表达即可,其中 node 是任意节点类型的实例。

下面,我们通过一些案例展示节点的插值。

var binExpr = BinaryExpr(quote(1 + 2))
let a = quote($(binExpr))
let b = quote($binExpr)
let c = quote($(binExpr.leftExpr))
let d = quote($binExpr.leftExpr)
println("a: ${a.toTokens()}")
println("b: ${b.toTokens()}")
println("c: ${c.toTokens()}")
println("d: ${d.toTokens()}")

输出结果是:

a: 1 + 2
b: 1 + 2
c: 1
d: 1 + 2.leftExpr

一般来说,插值运算符后面的表达式使用小括号限定作用域,例如 $(binExpr)。但是当后面只跟单个标识符的时候,小括号可省略,即可写为 $binExpr。因此,在案例中 a 和 b 都在 quote 中插入了 binExpr节点,结果为 1 + 2。然而,如果插值运算符后面的表达式更复杂,不加小括号可能造成作用域出错。例如,表达式 binExpr.leftExpr 求值为 1 + 2 的左表达式,即 1,因此 c 正确赋值为 1。但 d 中的插值被解释为 ($binExpr).leftExpr,因此结果是 1 + 2.leftExpr。为了明确插值的作用域,我们推荐在插值运算符中使用小括号。

下面的案例展示节点列表(ArrayList)的插值。

var incrs = ArrayList<Node>()
for (i in 1..=5) {
    incrs.append(parseExpr(quote(x += $(i))))
}
var foo = quote(
    func foo(n: Int64) {
        let x = n
        $(incrs)
        x
    })
println(foo)

输出结果是:

func foo(n: Int64) {
    let x = n
    x += 1
    x += 2
    x += 3
    x += 4
    x += 5
    x
}

在这个案例中,我们创建了一个节点列表 incrs,包含表达式 x += 1,...,x += 5。对 incrs 的插值将节点依次列出,在每个节点后换行。这适用于插入需要依次执行的表达式和声明的情况。

下面的案例展示在某些情况下,需要在插值周围添加括号,以保证正确性。

var binExpr1 = BinaryExpr(quote(x + y))
var binExpr2 = BinaryExpr(quote($(binExpr1) * z))       // 错误:得到 x + y * z
println("binExpr2: ${binExpr2.toTokens()}")
println("binExpr2.leftExpr: ${binExpr2.leftExpr.toTokens()}")
println("binExpr2.rightExpr: ${binExpr2.rightExpr.toTokens()}")
var binExpr3 = BinaryExpr(quote(($(binExpr1)) * z))     // 正确:得到 (x + y) * z
println("binExpr3: ${binExpr3.toTokens()}")

输出结果是:

binExpr2: x + y * z
binExpr2.leftExpr: x
binExpr2.rightExpr: y * z
binExpr3: (x + y) * z

首先,我们构建了表达式 x + y,然后将该表达式插入到模版 $(binExpr1) * z 中。这里的意图是得到一个先计算 x + y,然后再乘 z 的表达式,但是,插值的结果是 x + y * z,先做 y * z,然后再加 x。这是因为插值不会自动添加括号以保证被插入的表达式的原子性(这和前一阶介绍的 leftExpr 的替换不同)。因此,需要在 $(binExpr1) 周围添加小括号,保证得到正确的结果。

仓颉:华为的编程语言革新,是技术突围还是生态豪赌? 华为仓颉编程语言将于2025年7月30日开源,作为鸿蒙生态的原生开发语言,致力于突破西方技术垄断。仓颉在语言层面集成智能编程、全场景运行时和并发安全等特性,语法融合多种现代语言优点并适配中文开发。尽管拥有鸿蒙生态支持和完备工具链,仓颉仍面临第三方库不足、社区规模小等挑战。该语言不仅是技术自主的重要尝试,更承载着构建安全可控数字基座的战略意义。其未来发展将取决于开源后的生态建设成效。 阅读详情

相关推荐

仓颉编程语言快速入门:从零开始构建你的第一个程序

编程语言的演进本质是对计算本质的重新定义。仓颉语言通过融合学术前沿成果与工业级工程实践,不仅为开发者提供了高效可靠的工具,更在重塑我们对“智能时代软件开发”的认知。从一个简单的“Hello World”出发,每一次代码提交都在参与书写中国基础软件的未来。

未来已来,AI时代,学AI编程,做AI量化,就来大鹏AI教育。 2372

仓颉编程语言的语法和主要的库

开发者可通过获取文档和开源库资源。- 工具与中间件:`eventbus4cj`(事件总线)、`protobuf4cj`(Protocol Buffers 解析)、`xml-ffi`(XML 解析)。- 网络框架:如 `Hyperion`(TCP 通信框架)、`rpc4cj`(基于 Protobuf 的 RPC 库)、`mqtt4cj`(物联网协议支持)。- std:核心模块,包含基础数据结构(`ArrayList`、`HashMap`)、数学运算、文件操作(`fs`)、网络通信(`net`)等。

mrzyun0811的博客 1253

华为仓颉编程语言基础语法与代码全解析(含详细注释)

本文通过52个核心知识点和22个深度解析的代码示例,系统揭示了华为仓颉编程语言在语法设计、内存模型、并发处理等层面的创新。其融合了现代语言的精华设计——如Rust的所有权系统、Go的协程调度、C++的零成本抽象,并通过硬件抽象层(HAL)和领域特定扩展(如量子计算),构建了面向下一代计算的开发范式。开发者可通过这些基础构建模块,深入探索鸿蒙生态与边缘计算场景的底层开发。

conkl的博客 1642

跟我一起学“仓颉”编程语言-AST

本章为大家详细的介绍了仓颉编程语言中AST的内容。

Cool_foolisher的博客 448

华为仓颉编程语言深度解析

华为仓颉编程语言是华为公司面向万物互联时代研发的系统级编程语言,其设计目标聚焦于高效能计算、分布式系统开发和嵌入式设备优化三大领域。静态类型安全:通过类型推导与编译期检查实现零成本抽象异步原语内置:在语言层面支持协程与Actor模型硬件抽象层:提供统一的跨架构内存管理接口2022年推出0.9实验版,支持ARMv8指令集2023年发布1.0正式版,新增RISC-V架构支持2024年计划推出2.0版本,集成量子计算模拟器。

conkl的博客 1988

手动测试台架搭建,让你的车载测试更轻松

如果你也在经常进行车载测试,就知道有时候手头的设备并不能完全满足需求。 在我之前的测试中,发现了一些问题,但是却找不到根本原因。于是,我开始思考如何打造一个更为完美的手动测试台架,让测试变得更加轻松。 经过不断地实践和调试,我终于成功搭建出了一个能够满足自己需求的测试台架。现在,我想和大家分享这个搭建的经验,希望能够帮助到在车载测试领域工作的小伙伴们,让你们的测试更加准确、高效!

weixin_67553250的博客 1万+

cangjie仓颉编程语言学习Note-1.基础语法

仓颉是一帮子rust开发者,吸收了rust的语法,参考kotlin, golang, typescript 而做出的糅合怪!它使用方舟编译器,以llvm为后端,开发的一个国产编程语言。因为吸取了很多编程语言的优点,所以体验不错,但是融合的稍显生硬。又因为作为鸿蒙操作系统底层语言,所以标准库很完善,使用相对方便。和golang类似,简单的功能开发,几乎可以不依赖第三方库。

笨笨D幸福 - 后花园 1608

Windows下用Python调用科大讯飞语音唤醒SDK的避坑指南(附完整代码)

本文详细介绍了在Windows平台使用Python调用科大讯飞语音唤醒SDK的全流程,包括环境配置、核心代码实现、典型问题解决方案及进阶开发技巧。通过完整的代码示例和避坑指南,帮助开发者快速集成语音唤醒功能,提升开发效率。

u0v1w2x3的博客 407

仓颉编程语言开发指南(下)

文章目录仓颉编程语言开发指南(上)十五、宏1.宏的简介2.Tokens 相关类型和 quote 表达式Token 类型Tokens 类型quote 表达式和插值3.语法节点节点的解析使用解析表达式和声明的函数使用构造函数进行解析节点的组成部分BinaryExpr 案例FuncDecl 案例使用 quote 插值语法节点4.宏的实现非属性宏属性宏嵌套宏宏定义中嵌套宏调用宏调用中嵌套宏调用嵌套宏之间的消息传递5.编译、报错与调试宏的编译和使用并行宏展开diagReport 报错机制使用 --debug-macr

欢迎来到我的学习笔记薄 2994

Android SSL证书固定实战:原理、方案与避坑指南

SSL/TLS协议是保障网络通信安全的基石,其核心原理是通过非对称加密和数字证书实现身份认证与数据加密。在移动应用开发中,为了防止中间人攻击,证书固定技术应运而生,它通过将服务器证书或公钥的哈希值预置在应用内,强制校验服务器身份,从而大幅提升通信链路的安全性。这一技术对于金融、电商等高安全要求场景尤为重要。本文聚焦Android平台,深入解析SPKI固定、Network Security Configuration与OkHttp CertificatePinner等主流方案,并针对证书更新、调试兼容等常见痛

weixin_33935636的博客 405

复现基于PYNQ-Z2的手写数字识别卷积加速器设计

来源雪天鱼。

eachanm的博客 969

【仓颉语言基础】语言概念、环境配置与语法解析

华为仓颉语言是一门专为分布式系统设计的现代编程语言,以简洁的语法和强大的分布式能力为核心,提供高效的资源管理和任务调度方案。本篇文章将带您从概念入手,逐步掌握环境配置与语法基础,为分布式开发奠定坚实基础。

专注于 C/C++ 后端开发,涵盖基础语法、Linux系统与网络、MySQL数据库、常见算法及项目经验。 3710

保姆级教程:用NILMTK和REDD数据集,5分钟跑通你的第一个负荷分解模型

本文提供了一份详细的NILMTK和REDD数据集负荷分解模型教程,适合零基础用户快速上手。从环境准备、数据获取到模型构建和评估,全程仅需5分钟即可完成。特别适合希望快速入门非侵入式负荷分解(NILM)的开发者,涵盖数据预处理、模型训练及结果可视化等关键步骤。

weixin_30493401的博客 442

仓颉编程语言

仓颉编程语言(Cangjie Programming Language)是华为自研的一款面向全场景智能的新一代编程语言。

数字人生 1522

【RT-DETR涨点改进】独家注意力改进篇 | 手把手教你在RT-DETR上使用LSKAttention大核注意力机制(助力目标检测极限涨点)含多种创新改进点

本文提出了一种LSKA大核注意力机制优化RT-DETR模型的方法。LSKA通过将2D深度卷积核分解为级联的1D水平和垂直核,显著降低了计算复杂度和内存占用,尤其在处理大卷积核时优势明显。该模块在图像分类、目标检测等视觉任务中保持与LKA相当的性能,同时展现出更强的鲁棒性。文章详细介绍了LSKA的网络结构、核心代码实现方法,并提供了多种RT-DETR改进方案,包括rtdetr-r18-LSKA、rtdetr-l-LSKA等7种yaml配置文件,通过实验验证了该方法的有效性。

Ai缝合怪、助力小伙伴高效发论文 253

科研级YOLOv8 Neck革新:HS-FPN模块赋能,让特征融合更高效且参数量直降100W的实战指南

在文件夹下新建HS_FPN.py,将上述和HS_FPN类的代码写入其中。这一步是为了让YOLOv8的代码架构能识别我们的自定义Neck模块。

FJN110的博客 153

仓颉编程语言入门 -- I/O 节点流详解

节点流,作为数据流体系中的基石,直接关联到外部数据源,如文件、网络等。在仓颉编程语言中,节点流扮演了关键角色,它们不仅是数据流动的起点或终点,也是与外部世界交互的桥梁。

几许的博客 1万+

基于ESP32和OV5640的目标检测系统

本文详细介绍了基于ESP32-S3和OV5640摄像头构建目标检测系统的完整方案。系统采用YOLOv8-Nano轻量级模型,通过INT8量化实现边缘部署,在UXGA分辨率下达到25fps帧率。文章从硬件选型、图像采集优化、模型量化部署、实时推理流水线构建等维度展开,重点解决了内存管理、电源稳定性和异常处理等嵌入式系统关键问题。该方案在资源受限条件下实现了150ms以内的端到端延迟,为物联网视觉应用提供了低成本、低功耗的解决方案,适用于智能家居、工业检测等多个场景。

reset2021的博客 329

仓颉编程语言:I/O 节点流

节点流是指直接提供数据源的流,节点流的构造方式通常是依赖某种直接的外部资源(即文件、网络等)。

Androidbye的博客 1336

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

仓颉编程语言:全场景开发的未来选择

仓颉编程语言是一款面向全场景应用开发的高性能语言,具有语法简洁、多后端支持、跨设备适配等核心特性。它深度集成鸿蒙系统,适用于智能家居、穿戴设备及分布式系统开发,同时提供完善的安全机制。学习资源包括官方文档、专业书籍和在线课程,是开发者把握未来技术趋势的理想选择。

软件科学-郝学胜 1067

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

仓颉编程语言入门 -- I/O 流概述

在仓颉编程语言的设计理念中,与外部实体(如文件系统、网络、用户输入等)的数据交换活动被统称为I/O操作,其中“I”代表输入(Input),而“O”则代表输出(Output)。这些操作的核心在于数据流(Stream)的概念,数据流作为字节数据的连续序列,扮演着数据传输管道的角色。仓颉编程语言对I/O机制进行了高度的抽象,引入了输入流(InputStream)和输出流(OutputStream)的概念。输入流负责从外部存储(如硬盘、网络等)向内存连续地传输数据,允许数据以片段形式逐步被读取并构建成完整的数据流。

几许的博客 1262

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

国产之光--仓颉编程语言的实战案例分析

通过以上案例可以看出,仓颉编程语言以其自然语言式语法、高效的开发能力以及丰富的内置模块,在多个领域展现出了强大的实战能力。无论是前端、后端,还是人工智能、物联网,仓颉语言都能高效地解决开发中的各种需求,极大地提升了开发效率与代码可读性。对于开发者而言,掌握仓颉语言不仅能应对当前复杂的开发需求,也为未来技术趋势做好了准备。

2406_83947720的博客 3242

仓颉编程语言开发指南(上)

仓颉编程语言是一种面向全场景应用开发的通用编程语言,可以兼顾开发效率和运行性能,并提供良好的编程体验,主要具有如下特点:语法简明高效:仓颉编程语言提供了一系列简明高效的语法,旨在减少冗余书写、提升开发效率,例如插值字符串、主构造函数、Flow 表达式、match、if-let、while-let 和重导出等语法,让开发者可以用较少编码表达相关逻辑。 多范式编程:仓颉编程语言支持函数式、命令式和面向对象等多范式编程,融合了高阶函数、代数数据类型、模式匹配、泛型等函数式语言的先进特性,还有封装、接口、继承、子类

欢迎来到我的学习笔记薄 2086

cangjie仓颉编程语言学习Note-2.标准库学习

当前仓颉标准库提供了几乎涵盖常见开发所使用的常见库,这一点很赞! 详细模块如下: - std: 意指标准库,标准库是指在编程语言中预先定义的一组函数、类、结构体等,旨在提供常用的功能和工具,以便开发者能够更快速、更高效地编写程序。 - core 包是标准库的核心包,提供了适用仓颉语言编程最基本的一些 API 能力。 - argopt 包提供从命令行参数字符串解析出参数名和参数值的相关能力。 - ast 包主要包含了仓颉源码的语法解析器和仓颉语法树节点,提供语法解析函数。

笨笨D幸福 - 后花园 1724

仓颉编程语言:条件编译

开发者可以通过预定义或自定义的条件完成条件编译

Androidbye的博客 1485

仓颉编程语言:I/O 流

在仓颉编程语言中,我们将与应用程序外部载体交互的操作称之为 I/O 操作。

Androidbye的博客 1242
上一篇: 仓颉编程语言:WebSocket 编程
下一篇: 仓颉编程语言:宏的实现
懂你的大海
博客等级 码龄6年 9049粉丝 1381原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值