本例源码: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. 关于手机数码圈KOL的一两点感想

    复工以来,高峰时段9号线地铁上的人依旧不少,安全距离啥的肯定是不用想了,只是从原来的4G手机换成5G手机以后在某些站能接收到5G信号,我终于能在一些原来根本没信号的站里愉快的刷一刷微博和酷安了. 但是 ...

  2. 综合CSS3 transition、transform、animation写的一个动画导航

    打算好好写博客开始,就想把博客给装修下,近几个月一直处在准备找工作疯狂学习前端的状态.感觉博客装修要等到工作稳定下来才有时间和经历去想想要搞成什么样的了.也看过一些博主的博客导航有这种样式的,趁着回顾 ...

  3. C#LeetCode刷题之#434-字符串中的单词数​​​​​​​(Number of Segments in a String)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3941 访问. 统计字符串中的单词个数,这里的单词指的是连续的不是 ...

  4. Python基础入门知识点——Python中的异常

    前言 在先前的一些章节里你已经执行了一些代码,你一定遇到了程序“崩溃”或因未解决的错误而终止的情况.你会看到“跟踪记录(traceback)”消息以及随后解释器向你提供的信息,包括错误的名称.原因和发 ...

  5. Oracle元数据信息

    一.schema操作 1)查看当前schema select user, sys_context('userenv','current_schema') from dual; 2)切换schema a ...

  6. 为什么?为什么?Java处理排序后的数组比没有排序的快?想过没有?

    先看再点赞,给自己一点思考的时间,微信搜索[沉默王二]关注这个有颜值却假装靠才华苟且的程序员.本文 GitHub github.com/itwanger 已收录,里面还有我精心为你准备的一线大厂面试题 ...

  7. Vscode配置C++环境

    (终于申请博客了qaq) 之前用了那么久Dev-C++,总算换了一个编辑器,Visual Studio Code (Vscode). 界面可比以前的舒适多了. Vscode作为一款功能极其丰富的开发工 ...

  8. Mockito鸡尾酒第一杯 单测Mock

    鸡尾酒 Mockito是Java的单元测试Mock框架. 它的logo是一杯古巴最著名的鸡尾酒Mojito, Mojito鸡尾酒,源自古巴的哈瓦那,带有浓厚的加勒比海风情. 并不浓烈,但是喝一杯下去, ...

  9. 常见的mysql查询命令

    LIMIT基本语法:如果只给定一个参数,表示记录数.mysql> SELECT * FROM orange LIMIT 5; //检索前5条记录(1-5)相当于mysql> SELECT ...

  10. 「从零单排canal 07」 parser模块源码解析

    基于1.1.5-alpha版本,具体源码笔记可以参考我的github:https://github.com/saigu/JavaKnowledgeGraph/tree/master/code_read ...