形如:[a,b,c] [a,[b,cd],f] 为 嵌套列表

其ANTLR文法表示:

      list     :'[' elements ']';        // 匹配方括号
elements : elements (',' element)*; // 匹配list的逗号
element : NAME | list; // element是NAME或者嵌套的list
NAME : ('a'..'z' | 'A'..'Z')+; // NAME含有至少一个字母

具体实现:
```
public class Token {
public int type;
public String text;

public Token(int type, String text) {
this.type = type;
this.text = text;
}

@Override
public String toString() {
String tname = ListLexer.tokenNames[type];
return "";
}
}
```

```
public class ListLexer extends Lexer{
public static int NAME = 2;
public static int COMMA = 3;
public static int LBRACK = 4;
public static int RBRACK = 5;
public static String[] tokenNames = {"n/a","","NAME","COMMA","LBRACK","RBRACK"};
public String getTokenName(int x) {
return tokenNames[x];
}
boolean isLETTER() {
return c >= 'a' && c = 'A' && c ");
}

Token NAME() {
// NAME由一个或者多个字母组成
StringBuilder buf = new StringBuilder();
do {
buf.append(c);
consume();
} while(isLETTER());
return new Token(NAME, buf.toString());

}

void WS() {
// 忽略所有空白符
while (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
consume();
}
}
}

```

```
public abstract class Lexer {
public static final char EOF = (char)-1;
public static final int EOF_TYPE = 1; // 表示EOF的词法类型
String input; // 待解析的字符串
int p = 0; // 当前输入字符串的下标
char c; // 当前字符

public Lexer(String input) {
this.input = input;
c = input.charAt(p);
}

public void consume() {
// 向前移动一个字符,检验输入是否结束
p++;
if (p >= input.length()) {
c = EOF;
} else {
c = input.charAt(p);
}
}

public void match(char x) {
if (c == x) {
consume();
} else {
throw new Error("expecting "+ x + "; found"+c);
}
}

public abstract Token nextToken();
public abstract String getTokenName(int tokenType);
}
```

```
public class ListParser extends Parser{
public ListParser(Lexer input) {
super(input);
}
public void list() {
match(ListLexer.LBRACK);
elements();
match(ListLexer.RBRACK);
}

void elements() {
element();
while(lookahead.type == ListLexer.COMMA) {
match(ListLexer.COMMA);
element();
}
}
void element() {
if (lookahead.type == ListLexer.NAME) {
match(ListLexer.NAME);
} else if(lookahead.type == ListLexer.LBRACK) {
list();
} else {
throw new Error("expecting name or list; found"+lookahead);
}
}
}
```

```
public class Parser {
Lexer input;
Token lookahead;

public Parser(Lexer input) {
this.input = input;
consume();
}
public void match(int x) {
if (lookahead.type == x) {
consume();
} else {
throw new Error("expecting "+ input.getTokenName(x) + "; found"+ lookahead);
}
}

public void consume() {
lookahead = input.nextToken();
}
}

```

```
public class TestParser {
public static void main(String[] args) {
ListLexer lexer = new ListLexer("[a,[b,ccb],c]");
ListParser parser = new ListParser(lexer);
parser.list();
}
}
```

【读书笔记】-【编程语言的实现模式】-【LL(1)递归下降的语法解析器】的更多相关文章

  1. HeadFirst设计模式读书笔记(3)-装饰者模式(Decorator Pattern)

    装饰者模式:动态地将责任附件到对象上.若要扩展功能,装饰者提东了比继承更有弹性的替代方案. 装饰者和被装饰对象有相同的超类型 你可以用一个或者多个装饰者包装一个对象. 既然装饰者和被装饰对象有相同的超 ...

  2. 《JavaScript设计模式与开发实践》读书笔记之中介者模式

    1. 中介者模式 中介者模式的作用就是用来解除对象与对象之间的紧耦合关系,增加中介者后,所有相关对象都通过中介者来通信,而不再相互引用 1.1中介者模式的例子 以泡泡堂游戏为例,先定义一个玩家构造函数 ...

  3. 《JavaScript设计模式与开发实践》读书笔记之享元模式

    1. 享元模式 享元模式是一种用于性能优化的模式,享元模式的核心是运用共享技术来有效支持大量细粒度的对象 1.1 传统的文件上传方法 以文件上传为例,文件上传功能可以选择依照队列,一个一个的排队上传, ...

  4. ARM体系结构与编程读书笔记——处理器的运行模式

    ARM处理器共有7种运行模式,如下表: 处理器模式 描述 用户模式(User, usr) 正常程序执行的模式 快速中断模式(FIQ, fiq) 用于高速数据传输和通道处理 外部中断模式(IRQ, ir ...

  5. 《图解设计模式》读书笔记2-2 Factory Method模式

    目录 类图 代码 角色介绍 思想 类图 代码 //产品类,任意可"use"的产品都可继承该类 public abstract class Product { public abst ...

  6. 《图解设计模式》读书笔记2-1 Template Method模式

    目录 模板方法模式 类图 思想: 模板方法模式 在父类中定义流程,在子类中实现具体的方法. 类图 代码 //抽象类 public abstract class AbstractDisplay { pu ...

  7. 【读书笔记】iOS-设计模式

    一个可复用的解决方案,用于处理特定场景下的常见问题.一种设计模式并不是一个可以直接转化为代码的已完工设计.它是对于如何解决问题的一种描述或者模板,可以用在许多不同的场合. 参考资料:<iOS W ...

  8. Android(java)学习笔记187:Android中操作XML数据(使用Pull解析器)

    1. Pull解析器的运行方式与 SAX 解析器相似.它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件.跟SAX不同的是, Pull解析器 ...

  9. Android(java)学习笔记130:Android中操作XML数据(使用Pull解析器)

    1. Pull解析器的运行方式与 SAX 解析器相似.它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件.跟SAX不同的是, Pull解析器 ...

随机推荐

  1. 加快Bitmap的访问速度

    引言 在对Bitmap图片操作的时候,有时需要用到获取或设置像素颜色方法:GetPixel 和 SetPixel, 如果直接对这两个方法进行操作的话速度很慢,这里我们可以通过把数据提取出来操作,然后操 ...

  2. Ant自动编译打包&发布 android项目

    Eclipse用起来虽然方便,但是编译打包android项目还是比较慢,尤其将应用打包发布到各个渠道时,用Eclipse手动打包各种渠道包就有点不切实际了,这时候我们用到Ant帮我们自动编译打包了. ...

  3. Win10下E3-1231 V3开启Intel虚拟化技术(vt-x)安装HAXM

    硬件配置: 技嘉G1 Sniper B6主板,Intel Xeon E3-1231 V3 CPU.主板和U都支持Intel的虚拟化技术,也在主板的设置界面打开了虚拟化支持,如下图: 使用CPU-V检测 ...

  4. 自定义 scrapy 爬虫的 requests

    之前使用 scrapy 抓取数据的时候 ,默认是在逻辑中判断是否执行下一次请求 def parse(self): # 获取所有的url,例如获取到urls中 for url in urls: yiel ...

  5. DRY原则和Shy原则

    保障可维护性的主要诀窍是遵循DRY原则和Shy原则. 在一个系统的整个生命周期里,理解和改动这类维护工作的比例一般非常之高.为了维护的方便,要尽量将系统划分为可以独立理解与改动的模块.这就要在设计的时 ...

  6. iOS开发 - AVPlayer实现流音频边播边存

    边播边下有三套左右实现思路,本文使用AVPlayer + AVURLAsset实现. 概述 1. AVPlayer简介 AVPlayer存在于AVFoundation中,可以播放视频和音频,可以理解为 ...

  7. Web GIS 离线地图

    Web GIS 离线地图 1,基于瓦片的离线地图下载 博客园 阿凡卢 提供了离线地图的下载工具,下载地址:http://pan.baidu.com/s/1hqvQr7e 具体使用见 参考资料2 阿凡卢 ...

  8. Android Weak Handler:可以避免内存泄漏的Handler库

    这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识.前端.后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过! android使用java作 ...

  9. Schema Workbench 开发mdx和模式文件

    一.前言 安装了saiku之后,每次修改schema文件,非常耗时,每次都要经历若干步骤:修改xml.上传.重启才能生效,并且非常不利于学习和理解MDX和模式文件,踌躇之际,发现了这个工具,十分小巧方 ...

  10. cmd窗口编码方式的修改

    cmd默认的编码是采用GBK   regedit HKEY_CURRENT_USER\Console\%SystemRoot%_system32_cmd.exe\CodePage 十进制:936 GB ...