当前位置: 首页 > news >正文

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语法编写

一、导读 我们学习一门语言&#xff0c;或外语或编程语言&#xff0c;是不是都是要先学语法&#xff0c;想想这些语言有哪些相同点 1、中文、英语、日语......是不是都有 主谓宾 的规则 2、c、java、python、js......是不是都有 数据类型 、循环 等语法或数据结构 虽然人们在…...

6.使用个人用户登录域控的成员服务器,如何防止个人用户账号的用户策略生效?

&#xff08;1&#xff09;需求&#xff1a; &#xff08;2&#xff09;实战配置步骤 第一步:创建新的策略-并编辑策略 第二步&#xff1a;将策略应用到服务器处在OU 第三步&#xff1a;测试 &#xff08;1&#xff09;需求&#xff1a; 比如域控&#xff0c;或者加入域的…...

模拟算法

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

【数据结构刷题专题】—— 二叉树

二叉树 二叉树刷题框架 二叉树的定义&#xff1a; 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接口

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一个人虽可以走的更快&#xff0c;但一群人可以走的更远。 我是一名后…...

数据结构与算法-排序算法

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 文件上传(三)

之前讲解了如何接收文件以及如何保存到服务端的本地磁盘中&#xff1a; SpringBoot 文件上传&#xff08;一)-CSDN博客 SpringBoot 文件上传&#xff08;二&#xff09;-CSDN博客 这节讲解如何利用阿里云提供的OSS&#xff08;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、扩容&#xff1a; 可以直接在ubuntu setting界面里直接扩容&#xff0c;也可通过vmware命令&#xff0c;如下&#xff1a; vmware提供一个命令行工具&#xff0c;vmware-vdiskmanager.exe&#xff0c;位于vmware的安装目录下&#xff0c;比如 C:/Program Files/VMware/VMwar…...

秋招打卡算法题第一天

一年多没有刷过算法题了&#xff0c;已经不打算找计算机类工作了&#xff0c;但是思来想去&#xff0c;还是继续找吧。 1. 字符串最后一个单词的长度 public static void main(String[] args) {Scanner in new Scanner(System.in);while(in.hasNextInt()){String itemin.nextL…...

BC98 序列中删除指定数字

题目 描述 有一个整数序列&#xff08;可能有重复的整数&#xff09;&#xff0c;现删除指定的某一个整数&#xff0c;输出删除指定数字之后的序列&#xff0c;序列中未被删除数字的前后位置没有发生改变。 数据范围&#xff1a;序列长度和序列中的值都满足 1≤&#xfffd;≤…...

基于Java的学生体质健康管理系统的设计与实现(论文+源码)_kaic

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

【Linux系统】冯诺依曼与操作系统

什么是冯诺依曼体系结构&#xff1f; 如图即为冯诺依曼大致的体系结构图&#xff0c; 我们知道这些都是由我们的计算机硬件组成 输入设备&#xff1a;键盘&#xff0c; 鼠标&#xff0c; 摄像头&#xff0c; 话筒&#xff0c; 磁盘&#xff0c; 网卡... 输出设备&#xff1a…...

前端理论总结(html5)——form表单的新增特性/h5的新特性

form表单的新增特性 range&#xff1a;范围 color&#xff1a;取色器 url&#xff1a;对url进行验证 tel&#xff1a;对手机号格式验证 email&#xff1a;对邮箱格式验证 novalidate &#xff1a;提交表单时不验证 form 或 input 域 numbe…...

基于TensorFlow的花卉识别(算能杯)%%%

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

Android实现一周时间早中晚排班表

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

【Java八股面试系列】中间件-Redis

目录 Redis 什么是Redis Redis解决了什么问题 Redis的实现原理 数据结构 String 常用命令 应用场景 List(列表) 常用命令 应用场景 Hash(哈希) 常用命令 应用场景 set(集合) 常见命令​编辑 应用场景 Sorted Set(有序集合) 常见命令​编辑 应用场景 数据持…...

TCP/IP协议精华总结pdf分享

hi &#xff0c;大家好&#xff0c;应小伙伴们的要求&#xff0c;上次分享了个人的一些学习和职场经验&#xff0c;其中网络协议PDF文档是我之前学习协议的时候总结一些精华知识&#xff0c;网络属于基本功&#xff0c;是互联网必备知识&#xff0c;我深信掌握好核心20%知识&am…...

Centos7.x内网环境Jenkins前端打包环境配置

Centos7.x内网环境Jenkins前端打包环境配置 参考地址&#xff1a; https://www.cnblogs.com/guangdelw/p/18763336 https://2048.csdn.net/682c1be8606a8318e857d687.html 前言&#xff1a;环境描述和目标 最近公司新接了一个项目&#xff0c;要求是&#xff1a;需要再桌面…...

QuickBASIC QB64 支持 64 位系统和跨平台Linux/MAC OS

QuickBASIC 的现代继任者 QB64 已发展成为一个功能强大的开源项目&#xff0c;支持 64 位系统和跨平台开发。以下是详细介绍&#xff1a; 项目首页 - QB64pe:The QB64 Phoenix Edition Repository - GitCode https://gitcode.com/gh_mirrors/qb/QB64pe 1. QB64 概述 官网&am…...

定时任务:springboot集成xxl-job-core(二)

定时任务实现方式&#xff1a; 存在的问题&#xff1a; xxl-job的原理&#xff1a; 可以根据服务器的个数进行动态分片&#xff0c;每台服务器分到的处理数据是不一样的。 1. 多台机器动态注册 多台机器同时配置了调度器xxl-job-admin之后&#xff0c;执行器那里会有多个注…...

从法律层面剖析危化品证书:两证一证背后的安全逻辑

《安全生产法》第 24 条明确规定&#xff0c;危化品单位主要负责人和安全管理人员 “必须考核合格方可上岗”。这并非仅仅是行政要求&#xff0c;而是通过法律来筑牢安全防线。在某危化品仓库爆炸事故中&#xff0c;由于负责人未持证&#xff0c;导致事故责任升级&#xff0c;企…...

智慧政务标准规范介绍:构建高效、协同的政务信息体系

在当今信息化快速发展的时代&#xff0c;智慧政务作为政府数字化转型的重要方向&#xff0c;正逐步改变着政府管理和服务的方式。为了确保智慧政务系统的建设能够有序、高效地进行&#xff0c;国家制定了一系列标准规范&#xff0c;其中GB∕T 21062系列标准《政务信息资源交换体…...

MyBatisPlus--条件构造器及自定义SQL详解

条件构造器 在前面学习快速入门的时候&#xff0c;练习的增删改查都是基于id去执行的&#xff0c;但是在实际开发业务中&#xff0c;增删改查的条件往往是比较复杂的&#xff0c;因此MyBatisPlus就提供了一个条件构造器来帮助构造复杂的条件。 MyBatisPlus支持各种复杂的wher…...

基于cornerstone3D的dicom影像浏览器 第二十五章 自定义VR调窗工具

文章目录 前言一、三维调窗原理二、自定义三维调窗工具三、调用流程1. 修改mprvr.js2. 修改DispalyerArea3D.vue3. view3d.vue4. Toolbar3D.vue 总结 前言 从cornerstoneTools BaseTool派生VolumeShiftColorTool&#xff0c;实现鼠标键按下并移动时&#xff0c;对3D窗口的pres…...

浅谈 Linux 文件覆盖机制

引言&#xff1a;文件覆盖的本质 文件覆盖是 Linux 文件系统中常见的操作&#xff0c;指将源文件内容写入目标路径&#xff0c;导致目标文件原有内容被替换或新文件被创建。覆盖操作通常通过命令行工具&#xff08;如 mv、cp&#xff09;或系统调用&#xff08;如 open() 以写…...

【JavaEE】-- 网络原理

文章目录 1. 网络发展史1.1 广域网1.2 局域网 2. 网络通信基础2.1 IP地址2.2 端口号2.3 认识协议2.4 五元组2.5 协议分层2.5.1 分层的作用2.5.2 OSI七层模型&#xff08;教科书&#xff09;2.5.3 TCP/IP五层&#xff08;或四层&#xff09;模型&#xff08;工业中常用&#xff…...