繁体   English   中英

java.util.Scanner如何工作?

[英]How does java.util.Scanner work?

我有一种简单的语言,其中包含类似

size(50*50)
start(10, 20, -x)
forward(15)
stop

这是乌龟绘画语言的一个例子。 我需要正确地标记它。 上面是一个源代码实例。 语句和表达式用换行符分隔。 我将扫描程序设置为使用换行符之类的定界符。 我希望next("start")吃掉字符串“ start”,然后发出next("(")吃掉第一个括号。但是,看起来它做的事情超出了我的预期。扫描仪已经坏了上面的代码基于定界符和/或我需要以不同的方式处理吗?对我来说,第一行上的“开始”,“(”,“ 50”,“ *”,“ 50”和“)”将构成单独的令牌,这似乎是一个无法实现的期望。如何用尽可能少的代码对上面的令牌进行令牌处理?我目前不需要编写令牌处理程序,而是在编写解释器,因此令牌化是我不需要的想在我的身上花费时间,我就像Scanner在这里一起工作。

我的useDelimiter调用如下:

Scanner s ///...
s.useDelimiter(Pattern.compile("[\\s]&&[^\\r\\n]"));

发出第next电话将给我完整的文件内容。 没有上面的电话,它给了我整个第一行。

要编写适当的解析器,您需要以正式语法定义语言。 相信我,您想正确执行此操作,否则下游将遇到问题。

您可能可以在最低级别将标记表示为正则表达式,但是首先需要清楚语法,这是词法结构中标记的组合。 您可以将其表示为称为Productions的递归函数(方法)。 每个生产功能都可以使用扫描仪来测试是否正在查看所需的令牌。 但是扫描仪会消耗输入,并且您无法撤消输入。

如果您使用扫描仪,则会发现以下不合适的内容:

  1. 它将始终根据正则表达式解析令牌,

    1.1因此,即使您确实获得了可以使用的令牌,也将不得不编写更多代码来确定它到底是什么令牌

    1.2,您可能无法将您的语言语法表示为一种表达方式

  2. 您无法重绕。 先行解析器(像您这样的大量语法所必需的)需要能够向前看输入流,然后决定是否要不使用输入,并让另一个令牌解析器功能使用它。

我建议您自己编写字符lexer,并遍历一个字符的字符串/数组而不是一个流。 然后,您可以重新上弦。

否则,请使用现成的lexer / parser框架,例如yaccCoco / R。

java.io.StreamTokenizer可能更合适。 递归下降解析器的示例中使用它。

附录: StreamTokenizer Scanner 之间的主要区别是什么

可以执行解析器所需的词法分析 StreamTokenizer的重量较轻,但仅限于四个预定义的元令牌。 Scanner更加灵活,但使用起来却比较麻烦。 这是两者的比较以及后者的变体

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM