解析表示化学反应的字符串并验证该反应是否可能
Parsing a string that represents a chemical reaction and verify if the reaction is possible
我必须编写一个程序,将用户的化学方程式作为输入,例如 12 CO2 + 6 H2O -> 2 C6H12O6 + 12 O2,然后观察两个站点上的原子量是否相同。有什么方法可以轻松计算和解析吗?
例如:
12 CO2 + 6 H2O -> 2 C6H12O6 + 12 O2
12*2+6*2 -> 2*6+2*12+2*6+12*2
在这种情况下,应该有输出 "false"。
这是我的代码,但它实际上只是为了尝试一些东西:
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
List<String> list = new ArrayList<String>();
String input = "";
while (!(input.equals("end"))) {
input = s.nextLine();
list.add(input);
}
list.remove(list.size() - 1);
for (int i = 0; i < list.size(); i++) {
int before = 0;
int after = 0;
String string = list.get(i);
string = besserUmwandeln(string);
System.out.println(string);
}
}
public static String besserUmwandeln(String string) {
string = string.replace("-", "");
string = string.trim().replaceAll(("\s+"), " ");
string = string.replace(' ', '*');
StringBuilder builder = new StringBuilder(string);
System.out.println(string);
for (int k = 0; k < builder.length(); k++) {
if (Character.isUpperCase(builder.charAt(k))) {
builder.setCharAt(k, ':');
}
if (Character.isLowerCase(builder.charAt(k))) {
builder.setCharAt(k, '.');
}
if (Character.isDigit(builder.charAt(k))) {
} else {
}
}
for (int j = 0; j < builder.length(); j++) {
if (j < builder.length() && builder.charAt(j) == ':' && builder.charAt(j + 1) == '.') {
builder.deleteCharAt(j + 1);
}
}
for (int i = 0; i < builder.length(); i++) {
if (i < builder.length() - 1 && builder.charAt(i) == ':' && builder.charAt(i + 1) == ':') {
builder.deleteCharAt(i);
}
}
for (int i = 0; i < builder.length(); i++) {
if (i < builder.length() - 1 && builder.charAt(i) == '+' && builder.charAt(i + 1) == '*') {
builder.deleteCharAt(i + 1);
}
}
for (int i = 0; i < builder.length(); i++) {
if (i < builder.length() - 1 && builder.charAt(i) == '*' && builder.charAt(i + 1) == '+') {
builder.deleteCharAt(i);
}
}
for (int i = 0; i < builder.length(); i++) {
if (i < builder.length() - 1 && builder.charAt(i) == '*' && builder.charAt(i + 1) == '>') {
builder.deleteCharAt(i);
}
}
for (int i = 0; i < builder.length(); i++) {
if (i < builder.length() - 1 && builder.charAt(i) == '>' && builder.charAt(i + 1) == '*') {
builder.deleteCharAt(i + 1);
}
}
for (int i = 0; i < builder.length(); i++) {
if (i < builder.length() - 1 && builder.charAt(i) == '*' && builder.charAt(i + 1) == ':') {
builder.deleteCharAt(i + 1);
}
}
return builder.toString();
}
所以,每次我需要用 Java
解析一些文本时,我大多最终只使用 Regex
。所以我建议你也这样做。
您可以在 regex101.com.
测试正则表达式
并且也可以在 Java
中轻松使用它:
final inputText = ...
final Pattern pattern = Patern.compile("Some regex code");
final Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println(matcher.group(0));
}
在Regex
里面你可以用(
和)
定义捕获组然后用matcher.group(int)
.
抓取结果
例如,您可以先使用 (.*) -> (.*)
.
分隔方程
然后使用 find
循环左右组:(\d+) (\w+)(?: \+| -|$)
.
之后,您可以使用 group(1)
作为金额,使用 group(2)
作为元素。
如果需要,还可以使用 (\w)(\d?)
迭代第二组(元素)以获得精确的元素分布。然后第一组是元素,例如对于文本 CO2
它产生两次匹配,第一次匹配有 group(1) -> C
而没有第二组。第二个命中有 group(1) -> O
和 group(2) -> 2
.
在这里测试你的正则表达式:regex101#Q6KMJo
这个问题要求一个简单的解析器来解析一种简单的方程式。我假设你不需要支持各种带有括号和奇怪符号的不规则方程。
为了安全起见,我会使用很多 String.split()
而不是正则表达式。
一个(相对)简单的解决方案将执行以下操作:
- 分裂日期
->
- 确保有两块
- 总结每一块:
- 分裂日期
+
- 解析每个分子并总结原子:
- 解析可选乘数
- 找到分子正则表达式的所有匹配项
- 转换数字并按元素相加
- 比较结果
每个级别的解析都可以在单独的方法中轻松完成。使用正则表达式可能是解析单个分子的最佳方式,所以我从这里借用了表达式:https://codereview.stackexchange.com/questions/2345/simplify-splitting-a-string-into-alpha-and-numeric-parts。正则表达式非常简单,所以请多多包涵:
import java.util.Map;
import java.util.HashMap;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class SimpleChemicalEquationParser
{
// Counts of elements on each side
private Map<String, Integer> left;
private Map<String, Integer> right;
public SimpleChemicalEquationParser(String eqn)
{
this.left = new HashMap<>();
this.right = new HashMap<>();
parse(eqn);
}
public boolean isBalanced()
{
return left.equals(right);
}
public boolean isSimpleBalanced()
{
return leftCount() == rightCount();
}
public int leftCount()
{
return left.values().stream().mapToInt(Integer::intValue).sum();
}
public int rightCount()
{
return right.values().stream().mapToInt(Integer::intValue).sum();
}
private void parse(String eqn)
{
String[] sides = eqn.split("->");
if(sides.length != 2) {
throw new RuntimeException("Check your equation. There should be exactly one -> symbol somewhere");
}
parseSide(sides[0], this.left);
parseSide(sides[1], this.right);
}
private void parseSide(String side, Map<String, Integer> counter)
{
String[] molecules = side.split("\+");
for(String molecule : molecules) {
parseMolecule(molecule, counter);
}
}
private void parseMolecule(String molecule, Map<String, Integer> counter)
{
molecule = molecule.trim();
Matcher matcher = Pattern.compile("([a-zA-Z]+)\s*([0-9]*)").matcher(molecule);
int multiplier = 1;
int endIndex = 0;
while(matcher.find()) {
String separator = molecule.substring(endIndex, matcher.start()).trim();
if(!separator.isEmpty()) {
// Check if there is a premultiplier before the first element
if(endIndex == 0) {
String multiplierString = molecule.substring(0, matcher.start()).trim();
try {
multiplier = Integer.parseInt(multiplierString);
} catch(NumberFormatException nfe) {
throw new RuntimeException("Invalid prefix \"" + multiplierString +
"\" to molecule \"" + molecule.substring(matcher.start()) + "\"");
}
} else {
throw new RuntimeException("Nonsensical characters \"" + separator +
"\" in molecule \"" + molecule + "\"");
}
}
parseElement(multiplier, matcher.group(1), matcher.group(2), counter);
endIndex = matcher.end();
}
if(endIndex != molecule.length()) {
throw new RuntimeException("Invalid end to side: \"" + molecule.substring(endIndex) + "\"");
}
}
private void parseElement(int multiplier, String element, String atoms, Map<String, Integer> counter)
{
if(!atoms.isEmpty())
multiplier *= Integer.parseInt(atoms);
if(counter.containsKey(element))
multiplier += counter.get(element);
counter.put(element, multiplier);
}
public static void main(String[] args)
{
// Collect all command line arguments into one equation
StringBuilder sb = new StringBuilder();
for(String arg : args)
sb.append(arg).append(' ');
String eqn = sb.toString();
SimpleChemicalEquationParser parser = new SimpleChemicalEquationParser(eqn);
boolean simpleBalanced = parser.isSimpleBalanced();
boolean balanced = parser.isBalanced();
System.out.println("Left: " + parser.leftCount());
for(Map.Entry<String, Integer> entry : parser.left.entrySet()) {
System.out.println(" " + entry.getKey() + ": " + entry.getValue());
}
System.out.println();
System.out.println("Right: " + parser.rightCount());
for(Map.Entry<String, Integer> entry : parser.right.entrySet()) {
System.out.println(" " + entry.getKey() + ": " + entry.getValue());
}
System.out.println();
System.out.println("Atom counts match: " + simpleBalanced);
System.out.println("Elements match: " + balanced);
}
}
所有工作都是由 parse
方法及其下属完成的,它们构成了一种虚拟调用树。由于这种方法可以特别容易地确保每个元素的原子实际上是平衡的,所以我已经在这里完成了。 class 打印等式两边的原子数,无论原始计数是否平衡,以及它们是否与我的元素类型匹配。以下是几个运行示例:
OP 的原始示例:
$ java -cp . SimpleChemicalEquationParser '12 C O2 + 6 H2O -> 2 C6H12O6 + 12 O2'
Left: 54
C: 12
H: 12
O: 30
Right: 72
C: 12
H: 24
O: 36
Atom counts match: false
Elements match: false
添加了臭氧以使原子数匹配
$ java -cp . SimpleChemicalEquationParser '12 C O2 + 6 H2O + 6 O3 -> 2 C6H12O6 + 12 O2'
Left: 72
C: 12
H: 12
O: 48
Right: 72
C: 12
H: 24
O: 36
Atom counts match: true
Elements match: false
加水使一切相配
$ java -cp . SimpleChemicalEquationParser '12 C O2 + 12 H2O -> 2 C6H12O6 + 12 O2'
Left: 72
C: 12
H: 24
O: 36
Right: 72
C: 12
H: 24
O: 36
Atom counts match: true
Elements match: true
请注意,我在 CO2
中的 C
和 O
之间添加了一个 space。这是因为我当前的分子正则表达式 ([a-zA-Z]+)\s*([0-9]*)
允许任何字母组合来表示一个元素。如果您的元素总是简单的单字母元素,请将其更改为 ([a-zA-Z])\s*([0-9]*)
(删除 +
量词)。如果要正确命名它们,两个字母组合和第二个字母始终小写,请改为:([A-Z][a-z]?)\s*([0-9]*)
。我推荐后一种选择。对于两个修改版本,C O2
中的 space 将不再是必需的。
诸如 ANTLR 之类的正确解析器的工作方式是 1) 将文本转换为词法标记流,然后 2) 将具有前瞻性的标记解析为解析树。
前瞻有助于了解何时"end"特定的解析结构级别。
根据您的要求,您可以跳过词法分析和解析之间的区别,直接从文本中解析——但是,欣赏和使用前瞻性可能会有用。
特别是一个缓冲区来保存即将到来的(剩余的)文本、测试匹配(例如正则表达式)和从前面消耗匹配可能很有用。这可以通过修改 remaining
字符串或在其中推进索引来实现。
给定这样的缓冲区,您的伪代码可能如下所示:
class EquationParser {
protected ParseBuffer buffer;
// parse Equation;
// -- of form "Sum -> Sum".
// -- eg. "12 CO2 + 6 H2O -> 2 C6H12O6 + 12 O2"
public Equation parseEquation() {
Sum left = parseSum();
matchAndConsume("->");
Sum right = parseSum();
return new Equation( left, right);
}
// parse Sum;
// -- eg. "12 CO2 + 6 H2O"
public Sum parseSum() {
// parse 1 or more Product terms;
Sum result = new Sum();
result.add( parseProduct());
while (buffer.lookaheadMatch("\+")) {
buffer.consumeMatch("\+");
result.add( parseProduct());
}
return result;
}
// parse Product term;
// -- of form "N formula", or just "formula".
// -- eg. "12 CO2" or "CO2"
public Product parseProduct() {
int quantity = 1;
if (buffer.lookaheadMatch("\d+")) {
quantity = Integer.parseInt( buffer.consumeMatch("\d+"));
}
Formula formula = parseFormula();
return new Product( quantity, formula);
}
// parse Formula;
// -- eg. "C6H12O6" or "CO2"
public Formula parseFormula() {
Formula result = new Formula();
result.add( parseTerm());
while (buffer.lookaheadMatch("[A-Z][a-z]?\d*")) {
result.add( parseTerm());
}
return result;
}
// parse Term;
// -- eg. "C6", "C", "Co6", or "Co6"
public Term parseTerm() {
// ... reader exercise to implement...
}
protected void matchAndConsume (String patt) {
if (! buffer.lookaheadMatch( patt))
throw ParseFailed("parse failed: expected "+patt);
buffer.consumeMatch( patt);
}
}
这是概念性的示例代码,未经测试且不包括缓冲区或完整的解析器 -- reader 的工作是将这些充实为完整的解决方案。
我必须编写一个程序,将用户的化学方程式作为输入,例如 12 CO2 + 6 H2O -> 2 C6H12O6 + 12 O2,然后观察两个站点上的原子量是否相同。有什么方法可以轻松计算和解析吗?
例如:
12 CO2 + 6 H2O -> 2 C6H12O6 + 12 O2
12*2+6*2 -> 2*6+2*12+2*6+12*2
在这种情况下,应该有输出 "false"。
这是我的代码,但它实际上只是为了尝试一些东西:
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
List<String> list = new ArrayList<String>();
String input = "";
while (!(input.equals("end"))) {
input = s.nextLine();
list.add(input);
}
list.remove(list.size() - 1);
for (int i = 0; i < list.size(); i++) {
int before = 0;
int after = 0;
String string = list.get(i);
string = besserUmwandeln(string);
System.out.println(string);
}
}
public static String besserUmwandeln(String string) {
string = string.replace("-", "");
string = string.trim().replaceAll(("\s+"), " ");
string = string.replace(' ', '*');
StringBuilder builder = new StringBuilder(string);
System.out.println(string);
for (int k = 0; k < builder.length(); k++) {
if (Character.isUpperCase(builder.charAt(k))) {
builder.setCharAt(k, ':');
}
if (Character.isLowerCase(builder.charAt(k))) {
builder.setCharAt(k, '.');
}
if (Character.isDigit(builder.charAt(k))) {
} else {
}
}
for (int j = 0; j < builder.length(); j++) {
if (j < builder.length() && builder.charAt(j) == ':' && builder.charAt(j + 1) == '.') {
builder.deleteCharAt(j + 1);
}
}
for (int i = 0; i < builder.length(); i++) {
if (i < builder.length() - 1 && builder.charAt(i) == ':' && builder.charAt(i + 1) == ':') {
builder.deleteCharAt(i);
}
}
for (int i = 0; i < builder.length(); i++) {
if (i < builder.length() - 1 && builder.charAt(i) == '+' && builder.charAt(i + 1) == '*') {
builder.deleteCharAt(i + 1);
}
}
for (int i = 0; i < builder.length(); i++) {
if (i < builder.length() - 1 && builder.charAt(i) == '*' && builder.charAt(i + 1) == '+') {
builder.deleteCharAt(i);
}
}
for (int i = 0; i < builder.length(); i++) {
if (i < builder.length() - 1 && builder.charAt(i) == '*' && builder.charAt(i + 1) == '>') {
builder.deleteCharAt(i);
}
}
for (int i = 0; i < builder.length(); i++) {
if (i < builder.length() - 1 && builder.charAt(i) == '>' && builder.charAt(i + 1) == '*') {
builder.deleteCharAt(i + 1);
}
}
for (int i = 0; i < builder.length(); i++) {
if (i < builder.length() - 1 && builder.charAt(i) == '*' && builder.charAt(i + 1) == ':') {
builder.deleteCharAt(i + 1);
}
}
return builder.toString();
}
所以,每次我需要用 Java
解析一些文本时,我大多最终只使用 Regex
。所以我建议你也这样做。
您可以在 regex101.com.
测试正则表达式并且也可以在 Java
中轻松使用它:
final inputText = ...
final Pattern pattern = Patern.compile("Some regex code");
final Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println(matcher.group(0));
}
在Regex
里面你可以用(
和)
定义捕获组然后用matcher.group(int)
.
例如,您可以先使用 (.*) -> (.*)
.
然后使用 find
循环左右组:(\d+) (\w+)(?: \+| -|$)
.
之后,您可以使用 group(1)
作为金额,使用 group(2)
作为元素。
如果需要,还可以使用 (\w)(\d?)
迭代第二组(元素)以获得精确的元素分布。然后第一组是元素,例如对于文本 CO2
它产生两次匹配,第一次匹配有 group(1) -> C
而没有第二组。第二个命中有 group(1) -> O
和 group(2) -> 2
.
在这里测试你的正则表达式:regex101#Q6KMJo
这个问题要求一个简单的解析器来解析一种简单的方程式。我假设你不需要支持各种带有括号和奇怪符号的不规则方程。
为了安全起见,我会使用很多 String.split()
而不是正则表达式。
一个(相对)简单的解决方案将执行以下操作:
- 分裂日期
->
- 确保有两块
- 总结每一块:
- 分裂日期
+
- 解析每个分子并总结原子:
- 解析可选乘数
- 找到分子正则表达式的所有匹配项
- 转换数字并按元素相加
- 分裂日期
- 比较结果
每个级别的解析都可以在单独的方法中轻松完成。使用正则表达式可能是解析单个分子的最佳方式,所以我从这里借用了表达式:https://codereview.stackexchange.com/questions/2345/simplify-splitting-a-string-into-alpha-and-numeric-parts。正则表达式非常简单,所以请多多包涵:
import java.util.Map;
import java.util.HashMap;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class SimpleChemicalEquationParser
{
// Counts of elements on each side
private Map<String, Integer> left;
private Map<String, Integer> right;
public SimpleChemicalEquationParser(String eqn)
{
this.left = new HashMap<>();
this.right = new HashMap<>();
parse(eqn);
}
public boolean isBalanced()
{
return left.equals(right);
}
public boolean isSimpleBalanced()
{
return leftCount() == rightCount();
}
public int leftCount()
{
return left.values().stream().mapToInt(Integer::intValue).sum();
}
public int rightCount()
{
return right.values().stream().mapToInt(Integer::intValue).sum();
}
private void parse(String eqn)
{
String[] sides = eqn.split("->");
if(sides.length != 2) {
throw new RuntimeException("Check your equation. There should be exactly one -> symbol somewhere");
}
parseSide(sides[0], this.left);
parseSide(sides[1], this.right);
}
private void parseSide(String side, Map<String, Integer> counter)
{
String[] molecules = side.split("\+");
for(String molecule : molecules) {
parseMolecule(molecule, counter);
}
}
private void parseMolecule(String molecule, Map<String, Integer> counter)
{
molecule = molecule.trim();
Matcher matcher = Pattern.compile("([a-zA-Z]+)\s*([0-9]*)").matcher(molecule);
int multiplier = 1;
int endIndex = 0;
while(matcher.find()) {
String separator = molecule.substring(endIndex, matcher.start()).trim();
if(!separator.isEmpty()) {
// Check if there is a premultiplier before the first element
if(endIndex == 0) {
String multiplierString = molecule.substring(0, matcher.start()).trim();
try {
multiplier = Integer.parseInt(multiplierString);
} catch(NumberFormatException nfe) {
throw new RuntimeException("Invalid prefix \"" + multiplierString +
"\" to molecule \"" + molecule.substring(matcher.start()) + "\"");
}
} else {
throw new RuntimeException("Nonsensical characters \"" + separator +
"\" in molecule \"" + molecule + "\"");
}
}
parseElement(multiplier, matcher.group(1), matcher.group(2), counter);
endIndex = matcher.end();
}
if(endIndex != molecule.length()) {
throw new RuntimeException("Invalid end to side: \"" + molecule.substring(endIndex) + "\"");
}
}
private void parseElement(int multiplier, String element, String atoms, Map<String, Integer> counter)
{
if(!atoms.isEmpty())
multiplier *= Integer.parseInt(atoms);
if(counter.containsKey(element))
multiplier += counter.get(element);
counter.put(element, multiplier);
}
public static void main(String[] args)
{
// Collect all command line arguments into one equation
StringBuilder sb = new StringBuilder();
for(String arg : args)
sb.append(arg).append(' ');
String eqn = sb.toString();
SimpleChemicalEquationParser parser = new SimpleChemicalEquationParser(eqn);
boolean simpleBalanced = parser.isSimpleBalanced();
boolean balanced = parser.isBalanced();
System.out.println("Left: " + parser.leftCount());
for(Map.Entry<String, Integer> entry : parser.left.entrySet()) {
System.out.println(" " + entry.getKey() + ": " + entry.getValue());
}
System.out.println();
System.out.println("Right: " + parser.rightCount());
for(Map.Entry<String, Integer> entry : parser.right.entrySet()) {
System.out.println(" " + entry.getKey() + ": " + entry.getValue());
}
System.out.println();
System.out.println("Atom counts match: " + simpleBalanced);
System.out.println("Elements match: " + balanced);
}
}
所有工作都是由 parse
方法及其下属完成的,它们构成了一种虚拟调用树。由于这种方法可以特别容易地确保每个元素的原子实际上是平衡的,所以我已经在这里完成了。 class 打印等式两边的原子数,无论原始计数是否平衡,以及它们是否与我的元素类型匹配。以下是几个运行示例:
OP 的原始示例:
$ java -cp . SimpleChemicalEquationParser '12 C O2 + 6 H2O -> 2 C6H12O6 + 12 O2'
Left: 54
C: 12
H: 12
O: 30
Right: 72
C: 12
H: 24
O: 36
Atom counts match: false
Elements match: false
添加了臭氧以使原子数匹配
$ java -cp . SimpleChemicalEquationParser '12 C O2 + 6 H2O + 6 O3 -> 2 C6H12O6 + 12 O2'
Left: 72
C: 12
H: 12
O: 48
Right: 72
C: 12
H: 24
O: 36
Atom counts match: true
Elements match: false
加水使一切相配
$ java -cp . SimpleChemicalEquationParser '12 C O2 + 12 H2O -> 2 C6H12O6 + 12 O2'
Left: 72
C: 12
H: 24
O: 36
Right: 72
C: 12
H: 24
O: 36
Atom counts match: true
Elements match: true
请注意,我在 CO2
中的 C
和 O
之间添加了一个 space。这是因为我当前的分子正则表达式 ([a-zA-Z]+)\s*([0-9]*)
允许任何字母组合来表示一个元素。如果您的元素总是简单的单字母元素,请将其更改为 ([a-zA-Z])\s*([0-9]*)
(删除 +
量词)。如果要正确命名它们,两个字母组合和第二个字母始终小写,请改为:([A-Z][a-z]?)\s*([0-9]*)
。我推荐后一种选择。对于两个修改版本,C O2
中的 space 将不再是必需的。
诸如 ANTLR 之类的正确解析器的工作方式是 1) 将文本转换为词法标记流,然后 2) 将具有前瞻性的标记解析为解析树。
前瞻有助于了解何时"end"特定的解析结构级别。
根据您的要求,您可以跳过词法分析和解析之间的区别,直接从文本中解析——但是,欣赏和使用前瞻性可能会有用。
特别是一个缓冲区来保存即将到来的(剩余的)文本、测试匹配(例如正则表达式)和从前面消耗匹配可能很有用。这可以通过修改 remaining
字符串或在其中推进索引来实现。
给定这样的缓冲区,您的伪代码可能如下所示:
class EquationParser {
protected ParseBuffer buffer;
// parse Equation;
// -- of form "Sum -> Sum".
// -- eg. "12 CO2 + 6 H2O -> 2 C6H12O6 + 12 O2"
public Equation parseEquation() {
Sum left = parseSum();
matchAndConsume("->");
Sum right = parseSum();
return new Equation( left, right);
}
// parse Sum;
// -- eg. "12 CO2 + 6 H2O"
public Sum parseSum() {
// parse 1 or more Product terms;
Sum result = new Sum();
result.add( parseProduct());
while (buffer.lookaheadMatch("\+")) {
buffer.consumeMatch("\+");
result.add( parseProduct());
}
return result;
}
// parse Product term;
// -- of form "N formula", or just "formula".
// -- eg. "12 CO2" or "CO2"
public Product parseProduct() {
int quantity = 1;
if (buffer.lookaheadMatch("\d+")) {
quantity = Integer.parseInt( buffer.consumeMatch("\d+"));
}
Formula formula = parseFormula();
return new Product( quantity, formula);
}
// parse Formula;
// -- eg. "C6H12O6" or "CO2"
public Formula parseFormula() {
Formula result = new Formula();
result.add( parseTerm());
while (buffer.lookaheadMatch("[A-Z][a-z]?\d*")) {
result.add( parseTerm());
}
return result;
}
// parse Term;
// -- eg. "C6", "C", "Co6", or "Co6"
public Term parseTerm() {
// ... reader exercise to implement...
}
protected void matchAndConsume (String patt) {
if (! buffer.lookaheadMatch( patt))
throw ParseFailed("parse failed: expected "+patt);
buffer.consumeMatch( patt);
}
}
这是概念性的示例代码,未经测试且不包括缓冲区或完整的解析器 -- reader 的工作是将这些充实为完整的解决方案。