解析常量和标识符

时间:2015-05-30 22:05:50

标签: peg pegjs

我想匹配一个常量,它基本上是一个全大写的字符串。

另外,我想匹配一个标识符,它可以包含小写和大写字母的混合。

Start 
  = Constant
  / Identifier

Identifier
  = h:[A-Za-z_] t:[a-zA-Z0-9_]* { return { type: 'IDENTIFIER', value: h + t.join('') } }

Constant
  = h:[A-Z] t:[A-Z_0-9]* { return { type: 'CONSTANT', value: h + t.join('') } }

问题是,当我尝试匹配Asd时,它说:Line 1, column 2: Expected [A-Z_0-9] or end of input but "s" found.

它似乎与常量规则匹配,但即使失败也不会交换到标识符......

问题似乎是一个常量也是一个有效的标识符,但我无法弄清楚打破歧义的规则,我认为如果常量匹配失败,它应该只尝试标识符规则......

1 个答案:

答案 0 :(得分:1)

这里出现的问题是因为解析表达式语法不像上下文无关语法。他们获得了第一场比赛而不是回溯。 Constant规则在Identifier之前定义。 Asd匹配常量规则的起始字符,但是下一个char不匹配,因此它会引发错误,因为它是确定性的。希望很容易解决:

Start 
  = Constant
  / Identifier

Identifier
  = h:[A-Za-z_] t:[a-zA-Z0-9_]* { return { type: 'IDENTIFIER', value: h + t.join('') } }

Constant
  = h:[A-Z] ![a-z] t:[A-Z_0-9]* { return { type: 'CONSTANT', value: h + t.join('') } }  

输出:

{
   "type": "IDENTIFIER",
   "value": "Asd"
}

默认情况下,PEG是确定性的,可以避免歧义,正如您的规则所定义的那样。