本例源码:https://files.cnblogs.com/files/heyang78/JsonAnalyzer2-20200525-01.rar

自从按BNF重新书写了算术表达式解析(https://www.cnblogs.com/heyang78/p/12951492.html)后,深感这种方式精简,于是又用它重写了Json解析器.

此解析器通过的测试用例在:https://www.cnblogs.com/heyang78/p/12955028.html

新Json解析器核心类:

package com.heyang;

import java.util.List;

public class TreeBuilder {
private Node root;
private List<Token> tokens;
private int tokenIdx; public TreeBuilder(List<Token> tokens) throws Exception{
this.tokens=tokens;
this.tokenIdx=0; root=new Node(null,Node.Type_List);
parse_object(root);
} private void parse_object(Node parent) throws Exception{
Token token; token=fetchToken();
if(token.getType()!=Token.TYPE_OPEN_BRACE) {
throw new Exception("Missing '{'");
} for(;;) {
token=fetchToken();
if(token.getType()!=Token.TYPE_TEXT) {
break;
}
String key=token.getText(); token=fetchToken();
if(token.getType()!=Token.TYPE_COLON) {
throw new Exception("Should be ':' after key:"+key);
} token=fetchToken();
if(token.getType()==Token.TYPE_TEXT) {
String value=token.getText(); parent.addChild(new Node(key,value));
}else if(token.getType()==Token.TYPE_OPEN_BRACE){
Node node=new Node(key,Node.Type_List);
parent.addChild(node); returnToken();
parse_object(node); }else if(token.getType()==Token.TYPE_OPEN_BRACKET) {
Node node=new Node(key,Node.Type_Array);
parse_array(node);
parent.addChild(node);
}else {
throw new Exception("value should be string/object/array but not.");
} token=fetchToken();
if(token.getType()==Token.TYPE_COMMA) {
continue;
}else {
returnToken();
break;
}
} token=fetchToken();
if(token.getType()!=Token.TYPE_CLOSE_BRACE) {
throw new Exception("Missing '}'");
}
} private void parse_array(Node parent) throws Exception {
Token token; for(;;) {
token=fetchToken();
if(token.getType()==Token.TYPE_TEXT) {
String value=token.getText();
Node node=new Node(null,value);
parent.addChild(node);
}else if(token.getType()==Token.TYPE_OPEN_BRACE) {
Node node=new Node(null,Node.Type_List);
parent.addChild(node); returnToken();
parse_object(node);
}else {
returnToken();
} token=fetchToken();
if(token.getType()==Token.TYPE_COMMA) {
continue;
}else {
returnToken();
break;
}
} token=fetchToken();
if(token.getType()!=Token.TYPE_CLOSE_BRACKET) {
throw new Exception("Missing ']'");
}
} private Token fetchToken() {
if(tokenIdx>=tokens.size()) {
return null;
}else {
Token t=tokens.get(tokenIdx);
tokenIdx++;
return t;
}
} private void returnToken() {
if(tokenIdx>0) {
tokenIdx--;
}
} public Node getRoot() {
return root;
}
}

该解析器目前有bug,即;,{}[]出现在值的字符串中时,会导致解析异常.这个需要调整Lexer,此事留待日后完成.

--2020年5月25日--

按照BNF语法重新写就的JsonAnalyzer2的更多相关文章

  1. url语法

    URL的主要部分 URL通常被写成如下形式: <方案>:<方案描述部分> 一个URL包含了它使用的方案名称(<方案>), 其后紧跟一个冒号,然后是一个字符串 (&l ...

  2. ANTLR4权威指南 - 第6章 尝试一些实际中的语法

    第6章 尝试一些实际中的语法 在前一章,我们学习了通用词法结构和语法结构,并学习了如何用ANTLR的语法来表述这些结构.现在,是时候把我们学到的这些用来构建一些现实世界中的语法了.我们的主要目标是,怎 ...

  3. 【转】BNF和EBNF的含义与用法

    [转]BNF和EBNF的含义与用法   BNF 和EBNF的含义与用法 1简介       关于本文       什么是BNF?工作原理       基本原理       一个实例 EBNF及其用途  ...

  4. CSDN-markdown语法之怎样插入图片

    文件夹 图片上传方式 插入在线图片 插入本地图片 图片链接方式 行内式图片链接 參考式图片链接 几个问题探讨 问题1:图片上传和图片链接两种方式的差别 问题2:Markdown中怎样指定图片的高和宽? ...

  5. LR(1)语法分析器生成器(生成Action表和Goto表)java实现(一)

    序言 : 在看过<自己实现编译器链接器>源码之后,最近在看<编译器设计>,但感觉伪代码还是有点太浮空.没有掌握的感觉,也因为内网几乎没有LR(1)语法分析器生成器的内容,于是我 ...

  6. BSON 1.0版本规范(翻译)

    BSON 1.0版本规范 本文翻译自 http://bsonspec.org/spec.html BSON是用于存储零个或多个键/值对为一个单一的实体的一个二进制格式.我们称这个实体为文档(Docum ...

  7. android 讯飞语音识别(离线)注意事项

    讯飞语音识别:使用注意事项:mainfest.xml中一定要记得权限写进去21001:我的情况是没有写SpeechApp类,并且需要在application中注册:20005:无匹配结果23300:本 ...

  8. YACC基本用法

    YACC文件格式 yacc文件分为三部分: ... definitions ...(%{}%) %%... rules ...%% ... subroutines ...   定义部分 第一部分包括标 ...

  9. 一个Python小白5个小时爬虫经历

    前言 最近业余在做一个基于.NET Core的搜索项目,奈何基层代码写好了,没有看起来很华丽的数据供测试.很巧的也是博客搜索,于是乎想到了博客园.C#也能做做页面数据抓取的,不过在博客园看到的大部分都 ...

随机推荐

  1. PyTorch 学习

    PyTorch torch.autograd模块 深度学习的算法本质上是通过反向传播求导数, PyTorch的autograd模块实现了此功能, 在Tensor上的所有操作, autograd都会为它 ...

  2. Fixing the train-test resolution discrepancy

  3. 关于GPU你必须知道的基本知识

    图形处理单元(或简称GPU)会负责处理从PC内部传送到所连接显示器的所有内容,无论你在玩游戏.编辑视频或只是盯着桌面的壁纸,所有显示器中显示的图像都是由GPU进行渲染的. 对普通用户来说,实际上不需要 ...

  4. Java编译解释之cmd

    一.编译 1. javac 类名.java (在类当前目录下) 2. javac 类的全路径 二.解释 1. java 类名(在类当前目录下) 2. java -cp 类的当前目录路径 类名

  5. 2020-07-28:已知sqrt (2)约等于 1.414,要求不用数学库,求sqrt (2)精确到小数点后 10 位。

    福哥答案2020-07-28: 1.二分法.2.手算法.3.牛顿迭代法.基础是泰勒级数展开法.4.泰勒级数法.5.平方根倒数速算法,卡马克反转.基础是牛顿迭代法. golang代码如下: packag ...

  6. 2020-04-08:为什么TCP握手需要三次?

    假想一下,如果我们去掉了第三次呢?如果只是第二次建立的话,服务端和客户端就已经建立,但是如果客户端没有收到服务端的回应?这个时候,客户端认为没有建立,服务端却为认为建立成功,并保存了必要的资源,如果出 ...

  7. docker基础入门理解

    本文简单的介绍了一下docker的一些优点,以及使用方法 1. 理解docker 1.1 docker是什么? 1.2 为什么要使用Docker? 2. docker安装 3. docker-容器,镜 ...

  8. [netty4][netty-common]netty之ResourceLeakDetector的使用与实现

    netty之ResourceLeakDetector的使用与实现 通过WeakReference和ReferenceQueue做针对需要手动释放的资源的侦测 使用 设置日志级别: ServerBoot ...

  9. Markdown实验样例

    一级标题 二级标题 三级标题 重新开始一个段落 这是新的段落 斜体文本 粗体文本 粗斜体文本 下面是分隔线 删除线 下划线 脚注[1] 无序列表 第一项 嵌套元素1 嵌套元素2 第二项 嵌套元素1 嵌 ...

  10. 使用BurpSuite、Hydra和medusa爆破相关的服务

    一.基本定义 1.爆破=爆破工具(BP/hydra)+字典(用户字典/密码字典). 字典:就是一些用户名或者口令(弱口令/使用社工软件的生成)的集合. 2.BurpSuite 渗透测试神器,使用Jav ...