所以,我试图在pegjs中编写一个非常基本的Lisp解析器,只要Lisp代码在语法上有效且适合一行,我就可以吐出相同的代码。
我希望扩展解析器,以便能够接受任何地方插入的任何换行符以及代码中的额外空格。
所以,只要所有内容都在一行,的工作代码:
Start
= List
Character
= [^\n" ""("")"]
LeftParenthesis
= "("
RightParenthesis
= ")"
WhiteSpace
= " "
NewLine
= "\n"
Token
= token:Character+{return token.join("");}
Tuple
= left:Token WhiteSpace+ right:List?{
return left.concat([" "]).concat(right);
}
/ Token
List
= left:LeftParenthesis tuple:Tuple right:RightParenthesis{
return left.concat(tuple).concat(right);
}
/ Tuple
然后,在我尝试允许换行和空格时,我尝试更改" Tuple"到
Tuple
= left:Token WhiteSpace+ (NewLine* WhiteSpace*)* right:List?{
return left.concat([" "]).concat(right);
}
/ Token
但是这种变化导致pegjs进入无限循环,尽管规则的添加似乎是非递归的。
注意:如果我不清楚我要做什么,我会编写一个语法,以便pegjs吐出解析器
(f x
(g y
(h z t)))
并吐出与字符串相同的代码或只是
"(f x (g y (h z t)))"
要么适合我。
我目前的工作语法是做什么
(f x (g y (h z t)))
和输出
"(f x (g y (h z t)))"
虽然在每个" Token"之后只允许一个换行符是微不足道的。或者" Tuple",我希望接受以下法律代码:
(f x
(g y (
h z t) ) )
答案 0 :(得分:0)
原来这个问题与Ignore whitespace with PEG.js
非常相似一切都是关于忽略空格和换行符。我实际上不知道为什么上面的代码会失败,但在玩完之后,我设法让pegjs做我想做的事情
Start
= List
Character
= [^ \t\r\n"("")"]
LeftParenthesis
= "("
RightParenthesis
= ")"
Separator
= [ \t\r\n]
Token
= List
/ token:Character+{return token.join("");}
Tuple
= first:Token second:Separator+ rest:Tuple*{
return rest.length > 0 ? first.concat([" "]).concat(rest) : first;
}
/ Token
List
= left:LeftParenthesis Separator* token:Tuple Separator* right:RightParenthesis{
return [left].concat(token).concat([right]).join("");
}
因此,当您提供以下字符串进行解析时:
(f x
(g y (
h z t) ) )
解析器输出
"(f x (g y (h z t)))"
这正是我想要的