之前的 Go 笔记系列,已经完成到了开发环境搭建,原本接下来的计划就是到语法部分了,但后来一直没有前进。主要是因为当时的工作比较忙,分散了精力,于是就暂时放下了。

最近,准备重新把之前计划捡起来。

第一步,肯定是了解 Go 基础语法部分。原本计划是写 Go 编码的一些基础知识,但纯粹聊什么是关键字、标识符、字面量、操作符实在有点无聊。

突然想到,词法分析这块知识还没仔细研究过,那就从这个角度出发吧。通过逐步地拆解,将各个 token 进行归类。

概述

我们知道,编译型语言(比如 Go)的源码要经过编译和链接才能转化为计算机可以执行的程序,这个过程的第一步就是词法分析。

什么是词法分析呢?

它就是将源代码转化为一个个预先定义的 token。为了便于理解,我们将词法分析分为两个阶段。

第一阶段,对源码串进行扫描,按预先定义的 token 规则进行匹配并切分为一个个有语法含义、最小单元的字符串,即词素(lexme),并在此基础上将其划归为某一类 token。这个阶段,一些字符可能会被过滤掉,比如,空白符、注释等。

第二阶段,通过评估器 Evaluator 评估扫描出来的词素,并确定它字面值,生成最终的 Token。

是不是有点不好理解呢?

如果之前从未接触过这块内容,可能没有直观感受。其实,看着很复杂,但的确非常简单。

一个简单的示例

先看一段代码,经典的 hello world,如下:

package main

我们可以通过这个例子的源码逐步拆解词法分析的整个流程。

什么是词素

理论性的概念就不说了,直接看效果吧。

首先,将这段示例代码通过词法分析的第一阶段,我们将会得到如下内容:

packagemain\nimport"fmt"\nfuncmain(){\nfmt.Println("Hello World")\n}

输出的这一个个独立的字符序列就是词素。

词素的切分规划和语言的语法规则有关。此处的输出中除了一些可见的字符,换行符同样也具有语法含义,因为 Go 不像 C/C++ 必须是分号分隔语句,也可以通过换行符分隔。

源码分割为一个个词素的过程是有一定的规则的,这和具体的语言有关。但虽有差异,其实规则都差不多,无非两种,一是通过无语法含义的字符(空格符、制表符等)切分,还有是每个词素可以用作为分隔符。

什么是 token

token,也称为词法单元、记号等,它由名称和字面值两部分组成。从词素到 token 有固定的对应关系,而且并非所有的 token 都有字面值。

将 hello world 的源码转化为 token,我们将会得到如下的一张对应表格。

lexme name value
package PACKAGE "package"
main IDENT "main"
\n SEMICOLON "\n"
import IMPORT "import"
"fmt" STRING "\"fmt\""
\n SEMICOLON "\n"
func FUNC "func"
main IDENT "main"
( LPAREN ""
) RPAREN ""
{ LBRACE ""
fmt IDENT "fmt"
. PERIOD ""
Println IDENT "Println"
( LPAREN ""
"Hello World" STRING ""Hello World""
) RPAREN ""
\n SEMICOLON "\n"
} LBRACE ""
\n SEMICOLON "\n"

稍微有点长,因为这里没有省略。表格中的第一列是原始内容,第二列对应的 token 的名称,最后一列是 token 的字面值。

从表格中可以观察出,其中有一些 token 并没有值,比如,括号、点,名称本身已经表示了它们的内容。

token 的分类

token 一般可以分为关键字、标识符、字面量、操作符这四个大类。这个分类其实在 Go 的源码中有非常明显的体现。

查看源码文件 src/go/token/token.go[1],将会找到 Token 类型如下的几个方法。

// 是否是字面常量

代码非常简单,通过比较确定 Token 是否位于指定范围确定它的类型。上面的这三个方法分别对应于判断 Token 是字面常量、操作符还是关键字。

额?怎么没有标识符呢?

当然也有啦,只不过它不是 Token 的方法,而是单独的一个函数。如下:

func IsIdentifier(name string) bool {

我们常说的变量、常量、函数、方法的名称不能为关键字,且必须是由字母、下划线或数字组成,且名称的开头不能为数字的规则,看到这个函数是不是一些就明白了。

到这里,其实已经写的差不多了。但想想还是拿其中一个类型再简单说说吧。

关键字

就以关键字为例吧,Go 中的关键字有哪些呢?

继续看源码。将之前那段如何判断一个 token 是关键字的代码再看一遍。如下:

func (tok Token) IsKeyword() bool {

只要 Token 大于 keyword_beg 且小于 keyword_end 即为关键字,看起来还挺好理解的。那在 keyword_begkeyword_end 之间有哪些关键字呢?代码如下:

const (

总共梳理出了 25 个关键字。如下:

break       

关键字的确挺少的。可见。。。

嗯?!

是不是猜到我要说,Go 语言就是简洁,关键字的都这么少。你看 Java,足足有 53 个关键字,其中有两个是保留字,而 Go 并没有保留字,自信!

既然你猜到了,那我还是先不说了吧。

其他

操作符和字面常量就不追了,思路都是一样的。

Go 中的操作符有 47 个,比如赋值运算符、位运算符、算术运算符,比较运算符,还有其他的操作符。相信我吧,都是从源码中数出来的,没有看任何资料。[此处应该放个捂脸笑]。

字面常量呢?有 5 种类型,分别是 INT(整型)、FLOAT(浮点型)、IMG(复数类型)、CHAR(字符型)、STRING(字符串型),

总结

文章写完了,前面扯了那么一堆废话,其实就只是为了介绍 Go 语法中用到的关键字、标识符、运算符、字面量从哪里找。并且,最终它们如何使用也没有怎么说明。

纯粹为了好玩吗?当然不是(是)。因为。。。,先不剧透了,避免后面尴尬。

阅读资料

Go 程序是怎么跑起来的[2]

go-lexer 词法分析[3]

Lexical analysis[4]

词法分析[5]


喜欢本文的朋友,欢迎关注“Go语言中文网”:

参考资料

[1]

src/go/token/token.go: https://github.com/golang/go/blob/master/src/go/token/token.go

[2]

Go 程序是怎么跑起来的: https://zhuanlan.zhihu.com/p/71993748

[3]

go-lexer 词法分析: https://studygolang.com/articles/6708

[4]

Lexical analysis: https://en.wikipedia.org/wiki/Lexical_analysis#Evaluator

[5]

词法分析: https://cs.nju.edu.cn/changxu/2_compiler/slides/Chapter_3.pdf

ROST情感分析的语法规则_从词法分析角度聊 Go 代码组成相关推荐

  1. go string 换行_从词法分析角度聊 Go 代码组成

    之前的 Go 笔记系列,已经完成到了开发环境搭建,原本接下来的计划就是到语法部分了,但后来一直没有前进.主要是因为当时的工作比较忙,分散了精力,于是就暂时放下了. 最近,准备重新把之前计划捡起来. 第 ...

  2. 情感分析朴素贝叶斯_朴素贝叶斯推文的情感分析

    情感分析朴素贝叶斯 Millions of tweets are posted every second. It helps us know how the public is responding ...

  3. python评论情感分析计算分数值_使用python对淘宝评论进行情感分析并绘制词云

    淘宝商品评论分析系统简介 截至2018年12月,我国网络购物用户规模达6.10亿,网购已经慢慢占据了我们生活的方方面面,所以一份透明的网购指南就显得尤为重要. 大部分网购消费群体只能依赖于其他人在商品 ...

  4. mysql 名次语法规则_基于sql语句的一些常用语法积累总结

    1.当某一字段的值希望通过其它字值显示出来时(记录转换),可通过下面的语句实现:case Type when '1' then '普通通道' when '2' then '高端通道' end as T ...

  5. matlab的基本语法规则_【经验交流】matlab自定义回调函数语法规则

    给出我今天学到的两个例子来说明两种用法: (1)set(h, 'StartFcn', @myfile)型 function [varargout] = XIE_bwmorphfig(Size, var ...

  6. 正则表达式变量名命名的规则_如何简单有效地提高代码质量?修改变量名即可...

    全文共6633字,预计学习时长13分钟 图片来源:pexels.com/@digitalbuggu 请快速说出以下代码的功能: for i in range(n): for j in range(m) ...

  7. python中有哪些重要的书写规则_一文读懂Python代码的书写规范

    Python代码的书写规范 1. 一致性的建议 打破一条既定规则的两个好理由 当应用这个规则将导致代码可读性下降,即使对于某人来说他已经习惯于按照这条规则来阅读代码了 为了和周围的代码保持一致而打破规 ...

  8. java qq号码生成规则_只需亿小串代码,教你用java仿制qq

    只需亿小串代码,教你用java仿制qq 直奔主题,代码如下: import java.awt.Color; import java.awt.Container; import java.awt.Ima ...

  9. 开平方_复数有效值+角度的verilog代码

    1.逐位比较法-二进制 < FPGA篇(一) 基于verilog的定点开方运算(1)-逐次逼近算法 >该篇文章中有详细描述 假设被开方数rad_i[7:0],则结果qout[3:0]位宽为 ...

  10. [Python人工智能] 三十四.Bert模型 (3)keras-bert库构建Bert模型实现微博情感分析

    从本专栏开始,作者正式研究Python深度学习.神经网络及人工智能相关知识.前一篇文章开启了新的内容--Bert,首先介绍Keras-bert库安装及基础用法及文本分类工作.这篇文章将通过keras- ...

最新文章

  1. python【力扣LeetCode算法题库】面试题 01.07- 旋转矩阵
  2. 根据xml生成相应的对象类
  3. CAS单点登录 - 创建用户会话、全局门票、临时票据
  4. 【超级鼠标键盘锁】之远线程注入winlogon.exe进程屏蔽Ctrl+Alt+Del、Win+L
  5. mongo数据库插入数据_深入研究Mongo数据库
  6. 如何让DIV模块随着页面固定和不固定
  7. 介绍个好点的,JAVA技术群
  8. C# 很基础的那些东西
  9. 《Orange'S:一个操作系统的实现》与上一版之比较
  10. 完全卸载NI系列软件的方法
  11. 中国麻将:世界上最早的区块链项目
  12. 机器学习基石 之 三大学习原则(Three Learning Principles)
  13. 圆柱体积怎么算立方公式_圆柱体积公式怎么算
  14. Android 百度地图定位显示当前位置
  15. input输入框提示语
  16. 机器学习 交叉验证与网格搜索调参
  17. Java中的七种设计原则
  18. 神经网络图用什么软件做,神经网络输入图片大小
  19. [iOS]阿里云人脸身份证校验
  20. 服务器基线加固脚本_一种基于WebLogic的安全基线加固方法与流程

热门文章

  1. Fiddler 抓包工具2 - 全网最全最细教程,没有之一
  2. Dev C++调试程序方法详解
  3. python简明教程电子书下载_python简明教程中文pdf下载-Python入门级电子书完整免费版-东坡下载...
  4. C语言程序设计:图书管理系统(附代码)
  5. mysql主从中断原因_mysql主从中断
  6. 罗技Lua脚本-CF神圣爆裂者自动开枪
  7. python必背100源代码-python 100例 (持续更新)
  8. c语言程序中所有语句都将被转换成二进制的机器指令,c语言练习试题
  9. vivo手机点击android,了解Vivo手机几个小技巧,让您的手机变得更好用
  10. matlab画图点形状,matlab画图点的形状