本例源码: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. canvas图片编辑操作:缩放、移动、保存(PC端+移动端)

    最近在写canvas关于图片的操作,看了网上的代码基本都是不行的,于是就自己写了一个. html代码 <canvas id="myCanvas" width="37 ...

  2. Vue Elementui 表单必填项和非必填项label文字对齐的简单方式

    1. 不好的方式 很长时间以来都是用改写form-item样式来使得必填项和非必填项保证label对齐,这样需要改写系统样式,还要在相应的item上引用,代码量增多,示例如下(不推荐) <tem ...

  3. Mac开发工具

    便捷管理你的Mac App Homebrew:https://brew.sh/index_zh-cn 强大的文本编辑器 Sublime Text:http://www.sublimetext.com ...

  4. PAT 2-09. 装箱问题模拟(20)

    题目链接 :http://www.patest.cn/contests/ds/2-09 解题思路:直接模拟, 记录已经使用的箱子的剩余容量, 如果已经使用的箱子中没有可以放下物品的箱子, 在增加另一个 ...

  5. python 10 else EasyGui(转载)

    else语句 if else 要么怎么样,要么不怎么样 while else 干完了能怎样,干不完就不怎样 (异常处理) else 没有问题,就干吧 try: int('a') except Valu ...

  6. 基于python tkinter的点名小程序

    import datetimeimport jsonimport osimport randomimport tkinter as tkimport openpyxl # 花名册文件名excel_fi ...

  7. SpringBoot整合Actuator进行健康监控

    一.Actuator介绍 SpringBoot自带监控功能Actuator,通过 restful api 请求来监管.审计.收集应用的运行情况,可以帮助实现对程序内部运行情况监控,比如监控状况.Bea ...

  8. 操作系统-文件系统(5)Linux文件系统管理

    主流分区机制有MBR和GPT两种 MBR分区:第一个扇区最重要,里面有:引导代码(Bootstrap code area)及分区表(partition table), 其中Bootstrap code ...

  9. 第4篇 Scrum 冲刺博客

    1.站立会议 照骗 进度 成员 昨日完成任务 今日计划任务 遇到的困难 钟智锋 重新设计项目执行流程 实现技能 庄诗楷 游戏窗口的制作 制作了开始游戏的界面,感觉还不错 无 易德康 完成所有棋子的移动 ...

  10. JavaFX桌面应用-SpringBoot + JavaFX

    SpringBoot对于Java程序员来说可以是一个福音,它让程序员在开发的时候,大大简化了各种spring的xml配置. 那么在JavaFX项目使用SpringBoot会是怎么样的体验呢? 这次使用 ...