Hive-技术补充-ANTLR语法编写
一、导读
我们学习一门语言,或外语或编程语言,是不是都是要先学语法,想想这些语言有哪些相同点
1、中文、英语、日语......是不是都有 主谓宾 的规则
2、c、java、python、js......是不是都有 数据类型 、循环 等语法或数据结构
虽然人们在过去的几十年里发明了多种编程语言,但基本的语言模式并不多。因为他们在设计时都会情不自禁的与自己脑海中的自然语言关联,并用数学符号表达了出来。因此如果你掌握了一门语言后再去学其他语言就会变的容易。总结下来有四种抽象的计算机语言模式:
1、序列:即一列元素,例如一个数组初始化时给的一串值
2、选择:在多种可选方案中做出选择,例如编程语言中的if语句
3、词法符号依赖:一个词法符号往往成对出现,比如{} () []
4、嵌套结构:一种自相似的语言结构,例如编程语言中的if嵌套 for嵌套
为了表达以上模式,我们先了解下巴克斯-诺尔范式(Backus Normal Form简称BNF)
二、巴克斯-诺尔范式
是一种用于表示上下文无关文法的语言,它是由约翰·巴科斯(John Backus)和彼得·诺尔(Peter Naur)首先引入的用来描述计算机语言语法的符号集。
几乎所有程序设计语言都是通过上下文无关文法来定义的。巴克斯-诺尔范式是上下文无关语法的一个例子。
而且上下文无关文法足够简单可以构造有效的分析算法来检验一个给定字串是否是由某个上下文无关文法产生,例如 LR 分析器和 LL 分析器。
三、从编程语言中提取语法
可以形象的理解为就像从一堆字符串中抽取一系列正则表达式来把他们完全表达出来,只是语法比正则表达式更丰富。
讨论语法的整体结构以及如何建立初始的语法框架,是任何编程语言项目的基础步骤。
语法由一个为该语法命名的头部定义和一些列可以相互引用的语言规则组成,例如:
grammar MyG;
rule1 : 《stuff》;
rule2 : 《more stuff》;
......
tuff 和 more stuff 为语言规则
下面我们来表达下常用的四种语言模式
1、序列模式
可以直接使用 类似 'RETR'的常量字符串来表示任意简单字符序列,如关键字、标点符号等
我们使用语法规则来为编程语的特定结构命名,就像我们编程时为多次相同功能命名的函数
+ 字符串表示一个或多个元素的情况
* 字符串表示0个或多个元素的情况
file : (row '\n')* ; //以一个 '\n' 作为终止符的序列
row : field(',',field)* ; //以一个 ',' 作为分隔符的序列
field:INT ; //假设字段都是整数
file 规则使用带终止符的序列模式来匹配0或多个row\n 序列
row 规则使用带分隔符的序列来匹配一个field 后面跟着0个或多个','field 序列的情形
','隔开了所有field 。rwo规则匹配类似 1、1,2 以及 1,2,3 的序列
2、选择模式
使用 | 表达编程语言中的选择模式,可以分割多个可选的语法结构,例如:
filed : INT | STRING ;
type: 'float' | 'int' | 'void'
stmt : node_stmt
| edge_stmt
| attr_stmt
| id '=' id
| subgraph
;
3、词法符号依赖模式
举个例子,如果我们在某个语句中看到了 [ ,就必须在同一个语句中找到与它匹配的 ] ,
通常[] 会把其他元素包裹起来,比如数组的初始化声明。
可以这样表示 :
vector : '[' INT+ ']' ;
4、嵌套模式
如果一条规则的定义中需要用到它自身,我们就需要一条嵌套规则,比如递归规则。下面时一条while循环的嵌套规则
stat : 'while' '(' expr ')' stat //匹配while语句
| '{' stat* '}' //匹配 {} 中若干条语句组成的代码
...... //其他语句
;
四、优先级处理
我们先来写一个包含乘法和加法的语法:
expr : expr '*' expr //匹配由 '*' 运算符连接的子表达式
| expr '+' expr //匹配由 '+' 运算符连接的子表达式
| INT
;
当处理 1 + 1 和 2*2 时没有问题,但是当处理 1+1*2 时就会由问题,
ANTLR 通过优先选择位置靠前的备选分支来解决歧义问题,这隐式的运行我们指定运算符优先级
尽管如此,一些运算符(例如指数运算符)是从右向左结合的,所以我们需要在这样的运算符上使用assoc选项手工指定结合性,这样,输入的 2^3^4就能够被正确解释为 2^(3^4)
expr : <assoc=right> expr '^' expr //运算符是右结合的
| INT
;
此外还可以使用优先级上升来解决这个问题
五、常见的词法结构
在词法角度上,不同编程语言的外观十分相似。也就是我们只需要描述标识符和整数一次,稍加改动,就可以将它运用于大多数编程语言中。
词法分析器也是使用不同的规则来描述繁多的语言结构。和语法分析器不同的是它是通过输入的字符流来识别特定语言结构
ANTLR运行词法规则和语法规则写在同一个文件中。不过词法分析和语法分析是两个不同的阶段,ANTLR是通过这种方式区分的:词法规则以大写字母开头,语法规则以小写字母开头。
例如 ID 是要给词法规则 expr 是一个语法规则
下面让我们一起来构造些常见词法符号的词法规则:
1、匹配标识符
ID : ('a'..'z'|'A'..'Z')+ ; //匹配1个或多个大小写字母
ID : [a-zA-Z]+ ; //匹配1个或多个大小写字母
有时不同的规则会起到冲突,比如
grammar KeywordTest;
enumDef : 'enum' '{'...'}';
......
FOR : 'for';
ID : [a-zA-Z]+ ; //不会匹配'enum'和'for'
按照语法ID规则也可以匹配到'enum'和'for' ,ANTLR词法分析器解决歧义的方式优先使用靠前的词法规则。
2、匹配数字
INT : '0'..'9'+; //匹配1个或多个数字
INT : [0-9]+; //匹配1个或多个数字
不过浮点数要复杂的多:
FLOAT : DIGIT+'.' DIGIT* //匹配 1.39 3.1569 等...
| '.' DIGIT+ //匹配 .1 .3654 等...
;
fragment
DIGIT : [0-9]; //匹配单个数字
这里我们使用了一条辅助规则 DIGIT,这样就不用重复书写了。将一条规则声明为fragment可以告诉ANTLR该规则不是词法符号,它只会被其他词法规则使用。
3、匹配字符串常量
STRING : '"' .*? '"'; //匹配"..." 间的任意文本
其中 . 匹配任意的单个字符。*表示0或多个字符 ? 是通过正则表达式提供了对贪婪子规则的支持
但是还不够完善,因为字符串中不应该再出现双引号。如果要加双引号必须加上转义符 \
STRING : '"' (ESC|.)*? '"';
fragment
ESC : '\\"' | '\\\\' ; //双字符序列 \" 和 \\
4、匹配注释和空白字符
当词法分析器匹配到我们定义的规则后,会把这些词法符号放入词法符号流,输送给语法分析器。
语法分析器检查词法符号流的语法结构,但是如果其中有注释或空白字符时,会十分容易出错,因此我们需要在词法匹配时就将它去除
assign : ID (WS|COMMENT)? '=' (WS|COMMENT)? expr (WS|COMMENT) ? ;
我们再使用 skip 指令通知词法分析为i将它丢弃
LINE_COMMENT : '//' .*? '\r'? '\n' -> skip ; //匹配 "//" 任意字符序列 '\n'
COMMENT : '/*' .*? '*/' -> skip ; //匹配 "/*" 任意字符序列 '*/'
注意windows上的换行符是 '\r\n' 而 linux上的换行符是 '\n' (因此注意windows上的文本文件上传到linux后每行会多一个\r符号)
另外词法分析器可以接收多种位于 -> 之后的指令 ,skip 只是其中一种 ,例如 channel 指令代表一个隐藏通道
下面我们看下 空白字符的处理
大多数编程语言将空白字符看作词法符号间的分隔符,并将它们忽略 比如 int a = 1 ;
(python是个例外,它使用空白字符来表达某些语法的目的:换行符代表一行命令的终止,特定数量的缩进指明嵌套的层级)
下列规则告诉 ANTLR 丢弃空白字符
WS : (' '|'\t'|'\r'|'\n')+ -> skip ; //匹配一个或多个空白字符并将它们丢弃
WS : [ \t\r\n]+ -> skip ; //匹配一个或多个空白字符并将它们丢弃
六、词法分析器和语法分析器的界限
词法和语法规则在一份文件中,且词法规则可以包含递归,这使得词法分析器变的和语法分析器一样强大,甚至可以匹配一些语法结构。
划定词法分析器和语法分析器的界限不仅是语言的职责,更是语言编写的应用程序的职责。
词法分析器应该匹配并丢弃任何语法分析器无须知晓的东西。比如注释和空白字符。
由词法分析器来匹配类似标识符、关键字、字符串、数字的常见词法符号。语法分析器的层级更高,所以我们不应当让它处理将数字组合成整数这样的事情,
这会加重它的负担。
将语法分析器无需区分的词法结构归为同一个词法类型符号。
例如:如果我们的程序对待整数和浮点数的方式是一致的,那就可以把它们都归纳为 NUMBER 类型的词法符号。
同样的将可以以相同方式处理的实体归为一类,
例如:如果语法分析器不关心xml的内容,词法分析器就可以将<>中的所有内容归为一个名为 TAG 的词法符号类型
相反,如果语法分析器需要把一种类型的文本拆开处理,那么词法分析器就应该将它的各个组成部分作为独立的词法符号输送个语法分析器
语法分析器和词法分析器是灵活的,受我们支配的,我们可以根据需求的不同来规定他们的功能和界限
比如我们有这样一个需求:
我们在代理服务器上有一份日志文件(ip 请求方法 状态码),日志内容如下
192.168.56.239 "GET /download/foo.html HTTP/1.0" 200
......
当我们大脑看到这些信息后很自认的就可以想出很多统计逻辑,不过我们的需求只是统计行数,
那我们就可以忽略到里面每行的的内容,只关注换行符即可
语法文件部分内容如下:
file : NL+ ; //匹配换行符序列的语法分析器
STUFF: ~'\n'+ -> skip ; //除 '\n' 之外的字符全部丢掉
NL : '\n' ; //将设定的换行符返回给语法分析器或者其他的调用者
接下来我们增加一个需求:
从日志文件中提取ip地址列表,这意味着我们需要一条匹配ip地址的词法规则,最好还有一些词法规则来匹配一行记录中的其他元素
语法文件部分内容如下:
file : row ; //匹配日志文件中全部行的语法规则
row : ip STRING INT NL ; //匹配日志文件中的一行记录IP : INT '.' INT '.' INT '.' INT ; //匹配ip 例如 192.168.56.239
INT : [0-9]+ ; //匹配ip地址中的一个字节或者http的状态码
STRING : '"' .*? '"' ; //匹配http请求方法
NL : '\n'; //匹配一行记录的终止符
WS : ' ' -> skip ; //忽略空格
我们也可以把IP词法规则转换成ip语法规则,只需要转换成小写即可
file : row ; //匹配日志文件中全部行的语法规则
row : ip STRING INT NL ; //匹配日志文件中的一行记录
ip : INT '.' INT '.' INT '.' INT ; //匹配ip 例如 192.168.56.239
INT : [0-9]+ ; //匹配ip地址中的一个字节或者http的状态码
STRING : '"' .*? '"' ; //匹配http请求方法
NL : '\n'; //匹配一行记录的终止符
WS : ' ' -> skip ; //忽略空格
相关文章:
Hive-技术补充-ANTLR语法编写
一、导读 我们学习一门语言,或外语或编程语言,是不是都是要先学语法,想想这些语言有哪些相同点 1、中文、英语、日语......是不是都有 主谓宾 的规则 2、c、java、python、js......是不是都有 数据类型 、循环 等语法或数据结构 虽然人们在…...

6.使用个人用户登录域控的成员服务器,如何防止个人用户账号的用户策略生效?
(1)需求: (2)实战配置步骤 第一步:创建新的策略-并编辑策略 第二步:将策略应用到服务器处在OU 第三步:测试 (1)需求: 比如域控,或者加入域的…...

模拟算法
例题一 算法思路: 纯模拟。从前往后遍历整个字符串,找到问号之后,就⽤ a ~ z 的每⼀个字符去尝试替换即 可。 例题二 解法(模拟 分情况讨论): 算法思路: 模拟 分情况讨论。 计算相邻两个…...

【数据结构刷题专题】—— 二叉树
二叉树 二叉树刷题框架 二叉树的定义: struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(NULL), right(NULL); };1 二叉树的遍历方式 【1】前序遍历 class Solution { public:void traversal(TreeNode* node, vector&…...
基于AWS云服务构建智能家居系统的最佳实践
在当今智能家居时代,构建一个安全、高性能、可扩展和灵活的智能家居系统已经成为许多公司的目标。亚马逊网络服务(AWS)提供了一系列云服务,可以帮助企业轻松构建和管理智能家居系统。本文将探讨如何利用AWS云服务构建一个智能家居系统,并分享相关的最佳实践。 系统架构概述 该…...
Java零基础-集合:Set接口
哈喽,各位小伙伴们,你们好呀,我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。 我是一名后…...
数据结构与算法-排序算法
1.顺序查找 def linear_search(iters, val):for i, v in enumerate(iters):if v val:return ireturn 2.二分查找 # 升序的二分查找 def binary_search(iters, val):left 0right len(iters)-1while left < right:mid (left right) // 2if iters[mid] val:return mid…...

SpringBoot 文件上传(三)
之前讲解了如何接收文件以及如何保存到服务端的本地磁盘中: SpringBoot 文件上传(一)-CSDN博客 SpringBoot 文件上传(二)-CSDN博客 这节讲解如何利用阿里云提供的OSS(Object Storage Service)对象存储服务保存文件。…...
web渗透测试漏洞流程:红队目标信息收集之资产搜索引擎收集
web渗透测试漏洞流程 渗透测试信息收集---域名信息收集1.域名信息的科普1.1 域名的概念1.2 后缀分类1.3 多重域名的关系1.4 域名收集的作用1.5 DNS解析原理1.6 域名解析记录2. 域名信息的收集的方法2.1 基础方法-搜索引擎语法2.1.1 Google搜索引擎2.1.1.1 Google语法的基本使用…...

UI自动化_id 元素定位
## 导包selenium from selenium import webdriver import time1、创建浏览器驱动对象 driver webdriver.Chrome() 2、打开测试网站 driver.get("你公司的平台地址") 3、使浏览器窗口最大化 driver.maximize_window() 4、在用户名输入框中输入admin driver.find_ele…...
华为OD技术面算法题整理
LeetCode原题 简单 题目编号频次409. 最长回文串 - 力扣(LeetCode)3...
vmware虚拟机下ubuntu扩大磁盘容量
1、扩容: 可以直接在ubuntu setting界面里直接扩容,也可通过vmware命令,如下: vmware提供一个命令行工具,vmware-vdiskmanager.exe,位于vmware的安装目录下,比如 C:/Program Files/VMware/VMwar…...

秋招打卡算法题第一天
一年多没有刷过算法题了,已经不打算找计算机类工作了,但是思来想去,还是继续找吧。 1. 字符串最后一个单词的长度 public static void main(String[] args) {Scanner in new Scanner(System.in);while(in.hasNextInt()){String itemin.nextL…...
BC98 序列中删除指定数字
题目 描述 有一个整数序列(可能有重复的整数),现删除指定的某一个整数,输出删除指定数字之后的序列,序列中未被删除数字的前后位置没有发生改变。 数据范围:序列长度和序列中的值都满足 1≤�≤…...

基于Java的学生体质健康管理系统的设计与实现(论文+源码)_kaic
摘 要 随着时代的进步,信息化也在逐渐深入融进我们生活的方方面面。其中也给健康管理带来了新的发展方向。通过对学生体质健康管理的研究与分析发现当下的管理系统还不够全面,系统的性能达不到使用者的要求。因此,本文结合Java的优势和流行性…...

【Linux系统】冯诺依曼与操作系统
什么是冯诺依曼体系结构? 如图即为冯诺依曼大致的体系结构图, 我们知道这些都是由我们的计算机硬件组成 输入设备:键盘, 鼠标, 摄像头, 话筒, 磁盘, 网卡... 输出设备:…...
前端理论总结(html5)——form表单的新增特性/h5的新特性
form表单的新增特性 range:范围 color:取色器 url:对url进行验证 tel:对手机号格式验证 email:对邮箱格式验证 novalidate :提交表单时不验证 form 或 input 域 numbe…...

基于TensorFlow的花卉识别(算能杯)%%%
Anaconda Prompt 激活 TensorFlow CPU版本 conda activate tensorflow_cpu //配合PyCharm环境 直接使用TensorFlow1.数据分析 此次设计的主题为花卉识别,数据为TensorFlow的官方数据集flower_photos,包括5种花卉(雏菊、蒲公英、玫瑰、向日葵…...

Android实现一周时间早中晚排班表
我们要做一个可以动态添加,修改一周早中晚时间排班表,需求图如下: one two 过程具体在这里不描述了,具体查看,https://github.com/yangxiansheng123/WorkingSchedule 上传数据格式: {"friday_plan":"…...

【Java八股面试系列】中间件-Redis
目录 Redis 什么是Redis Redis解决了什么问题 Redis的实现原理 数据结构 String 常用命令 应用场景 List(列表) 常用命令 应用场景 Hash(哈希) 常用命令 应用场景 set(集合) 常见命令编辑 应用场景 Sorted Set(有序集合) 常见命令编辑 应用场景 数据持…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...