要解决的问题会被用非常简单的“迷你语言”表述出来,用Java语言编写一个负责“翻译”的程序。这样,当需要解决的问题发生变化时,不需要修改Java语言程序,只需要修改迷你语言程序即可应对。
迷你语言
迷你语言的用途是控制无线玩具车。
- 前进1米(go)
- 右转(right)
- 左转(left)
- 重复(repeat)
示例
program repeat 4 repeat 3 go right go left end right end end
语法
1 | <program> ::= program <command list> |
示例
一个迷你程序的语法解析器。例如有如下迷你程序。
program repeat 4 go right end end
将这段迷你程序推导成为如下那样的语法树。
类图
Node类
1 | public abstract class Node { |
ProgramNode类
1 | // <program> ::= program <command list> |
CommandListNode类
1 | import java.util.ArrayList; |
CommandNode类
1 | // <command> ::= <repeat command> | <primitive command> |
RepeatCommandNode类
1 | // <repeat command> ::= repeat <number> <command list> |
PrimitiveCommandNode类
1 | // <primitive command> ::= go | left | right |
Context类
1 | import java.util.StringTokenizer; |
ParseException类
1 | public class ParseException extends Exception { |
Main类
1 | import java.io.BufferedReader; |
运行结果
1 | text = "program end" |
登场角色
AbstractExpression(抽象表达式)
AbstractExpression角色定义了语法树节点的共同接口(API)。在示例程序中,由Node类扮演此角色。
TerminalExpression(终结符表达式)
TerminalExpression角色对应BNF中的终结符表达式。在示例程序中,由PrimitiveCommandNode类扮演此角色。
NonterminalExpression(非终结符表达式)
NonterminalExpression角色对应BNF中的非终结符表达式。在示例程序中,由ProgramNode类、CommandNode类、RepeatCommandNode类和CommandListNode类扮演此角色。
Context(文脉、上下文)
Context角色为解释器进行语法解析提供了必要的信息。在示例程序中,由Context类扮演此角色。
Client(请求者)
为了推导语法树,Client角色会调用TerminalExpression角色和NonterminalExpression角色。在示例程序中,由Main类扮演此角色。