【问题标题】:Is there a simple way I can tokenize a string without a full-blown lexer?有没有一种简单的方法可以在没有成熟的词法分析器的情况下对字符串进行标记?
【发布时间】:2010-12-08 02:31:59
【问题描述】:

我正在寻找实现Shunting-yard Algorithm,但我需要一些帮助来确定将字符串拆分为其标记的最佳方法是什么。

如果您注意到,算法的第一步是“读取令牌”。这并不是一件不重要的事情。令牌可以由数字、运算符和括号组成。

如果你正在做类似的事情:

(5+1)

一个简单的 string.split() 会给我一个标记数组 { "(", "5", "+", "1", ")" }。

但是,如果您有多个数字,例如:

((2048*124) + 42)

现在,一个简单的 string.split() 将无法解决问题。多位数是个问题。

我知道我可以编写一个词法分析器,但是有没有办法在不编写成熟的词法分析器的情况下做到这一点?

我在 JavaScript 中实现了这个,如果可能的话,我想避免走下 lexer-path。 我将使用“*”、“+”、“-”和“/”运算符以及整数。

【问题讨论】:

  • 任何能正确地将字符流转换为令牌流的东西都是词法分析器。

标签: javascript computer-science tokenize lexer shunting-yard


【解决方案1】:

您可以使用http://mikesamuel.blogspot.com/2009/05/efficient-parsing-in-javascript.html 中所述的全局匹配

基本上,您创建一个描述令牌的正则表达式

/[0-9]+|false|true|\(|\)/g

并将“g”放在末尾,以便全局匹配,然后调用它的匹配方法

var tokens = myRegex.match(inputString);

并取回一个数组。

【讨论】:

  • 我认为这是最好的方法。我使用 result = subject.match(/(-?[0-9]+|[*+-\/()])/g);你得到你需要的令牌,你想要的令牌:)。
【解决方案2】:

正则表达式呢?您可以轻松编写正则表达式以按照您想要的方式对其进行拆分,JS string.split 方法也接受正则表达式作为参数。

例如...(修改以包含您需要的所有字符等)

/([0-9]+|[*+-\/()])/

【讨论】:

  • +1 对于像'((42 + 7) * 4)' 这样的嵌套括号会中断,但可以通过在表达式的后半部分添加括号来修复:/([0-9]+|[*+-\/()])/
  • 他仍在使用维基页面上指定的算法。伪代码显示“读取令牌”。
  • @Simucal, @KingNestor 我现在很困惑,这不是正确答案吗?
  • 有些人在遇到问题时会想“我知道,我会使用正则表达式”。现在他们有两个问题。 codinghorror.com/blog/archives/001016.html
  • @brianpeiris,哦,我不是说这不是答案。我只是在评论 Jani 答案的第一行,“如果您不想编写 wiki 上指定的算法。”该算法没有指定如何读取令牌,它只是说“读取令牌”。因此,以这种方式,KingNestor 正在使用此答案遵循算法。
猜你喜欢
  • 2015-02-04
  • 1970-01-01
  • 1970-01-01
  • 2011-09-20
  • 2015-08-27
  • 2011-09-30
  • 2014-01-03
  • 1970-01-01
  • 2012-07-24
相关资源
最近更新 更多