Parsing Peg解析器-支持转义字符

Parsing Peg解析器-支持转义字符,parsing,escaping,peg,pegjs,Parsing,Escaping,Peg,Pegjs,我正在做一个Peg解析器。在其他结构中,它需要解析标记指令。标记可以包含任何字符。如果希望标记包含大括号},可以使用反斜杠将其转义。如果你需要一个反斜杠,也应该转义。受JSON的Peg语法启发,我尝试实现这一点: 有两个问题: 转义反斜杠将导致两个反斜杠字符,而不是一个。输入示例: 解析器在转义的卷曲上中断\}。输入示例: 相关语法为: Tag = "{" _ tagContent:$(TagChar+) _ "}" { return {

我正在做一个Peg解析器。在其他结构中,它需要解析标记指令。标记可以包含任何字符。如果希望标记包含大括号
}
,可以使用反斜杠将其转义。如果你需要一个反斜杠,也应该转义。受JSON的Peg语法启发,我尝试实现这一点:

有两个问题:

  • 转义反斜杠将导致两个反斜杠字符,而不是一个。输入示例:
  • 解析器在转义的卷曲上中断
    \}
    。输入示例:
相关语法为:

Tag
  = "{" _ tagContent:$(TagChar+) _ "}" {
  return { type: "tag", content: tagContent }
}

TagChar
  = [^\}\r\n]
  / Escape
    sequence:(
        "\\" { return {type: "char", char: "\\"}; }
      / "}" { return {type: "char", char: "\x7d"}; }
    )
    { return sequence; }
    
_ "whitespace"
  = [ \t\n\r]*
  
Escape
  = "\\"
您可以使用在线PegJS沙盒轻松测试语法和输入:


我希望有人有办法解决这个问题。

这些错误基本上都是打字错误

第一个问题是正则表达式中用于标记字符的字符类。在字符类中,
\
仍然是转义字符,因此
[^\}\r\n]
匹配除
}
(使用不必要的反斜杠转义)、回车符或换行符以外的任何字符
\
就是这样一个字符,因此它由character类匹配,
Escape
从未尝试过

由于标记字符的模式无法成功地将
\
识别为
转义
,因此标记
{\\}
被解析为四个字符(空格、反斜杠、反斜杠、空格),标记
{\}
被解析为在第一个
}
终止,从而产生语法错误

因此,您应该将字符类修改为
[^}\\\\r\n]
(我将右括号放在第一位,以便更容易阅读掉落的木材。顺序与此无关。)

一旦您这样做了,您会发现解析器仍然返回带有反斜杠的字符串。这是因为
标记中的
$
模式:
“{”\tagContent:$(TagChar+)}”
。根据,
$
运算符的含义是:(强调添加)

$expression

尝试匹配表达式。如果匹配成功,返回匹配的文本而不是匹配结果。


为了便于参考,正确的语法如下:

Tag
  = "{" _ tagContent:TagChar+ _ "}" {
  return { type: "tag", content: tagContent.map(c => c.char || c).join('') }
}

TagChar
  = [^}\\\r\n]
  / Escape
    sequence:(
        "\\" { return {type: "char", char: "\\"}; }
      / "}" { return {type: "char", char: "\x7d"}; }
    )
    { return sequence; }
    
_ "whitespace"
  = [ \t\n\r]*
  
Escape
  = "\\"
使用以下输入时:

{ some characters but escape \} with a \\ }
它将返回:

{
   "type": "tag",
   "content": "some characters but escape } with a \ "
}
{ some characters but escape \} with a \\ }
{
   "type": "tag",
   "content": "some characters but escape } with a \ "
}