如何解决PEG:我的if语句语法有什么错?
我正在使用rust-peg实现类似于OCaml的语言,并且我的解析器有一个错误。 我定义了if语句语法,但是它不起作用。
我猜测测试用例的输入被解析为Apply(Apply(Apply(Apply(f,then),2) else),4)
。我的意思是"then"
被解析为Ident,而不是关键字。
我不知道要修复此apply-expression语法。你有什么主意吗?
#[derive(Clone,PartialEq,Eq,Debug)]
pub enum Expression {
Number(i64),If {
cond: Box<Expression>,conseq: Box<Expression>,alt: Box<Expression>,},Ident(String),Apply(Box<Expression>,Box<Expression>),}
use peg::parser;
use toplevel::expression;
use Expression::*;
parser! {
pub grammar toplevel() for str {
rule _() = [' ' | '\n']*
pub rule expression() -> Expression
= expr()
rule expr() -> Expression
= if_expr()
/ apply_expr()
rule if_expr() -> Expression
= "if" _ cond:expr() _ "then" _ conseq:expr() _ "else" _ alt:expr() {
Expression::If {
cond: Box::new(cond),conseq: Box::new(conseq),alt: Box::new(alt)
}
}
rule apply_expr() -> Expression
= e1:atom() _ e2:atom() { Apply(Box::new(e1),Box::new(e2)) }
/ atom()
rule atom() -> Expression
= number()
/ id:ident() { Ident(id) }
rule number() -> Expression
= n:$(['0'..='9']+) { Expression::Number(n.parse().unwrap()) }
rule ident() -> String
= id:$(['a'..='z' | 'A'..='Z']['a'..='z' | 'A'..='Z' | '0'..='9']*) { id.to_string() }
}}
fn main() {
assert_eq!(expression("1"),Ok(Number(1)));
assert_eq!(
expression("myFunc 10"),Ok(Apply(
Box::new(Ident("myFunc".to_string())),Box::new(Number(10))
))
);
// failed
assert_eq!(
expression("if f then 2 else 3"),Ok(If {
cond: Box::new(Ident("f".to_string())),conseq: Box::new(Number(2)),alt: Box::new(Number(3))
})
);
}
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `Err(ParseError { location: LineCol { line: 1,column: 11,offset: 10 },expected: ExpectedSet { expected: {"\"then\"","\' \' | \'\\n\'"} } })`,right: `Ok(If { cond: Ident("f"),conseq: Number(2),alt: Number(3) })`',src/main.rs:64:5
解决方法
PEG使用有序选择。这意味着当您为某个规则R = A / B
编写R
时,如果位置A
成功解析,它将从不尝试B
,甚至如果选择A
会在以后导致问题。这是无上下文语法的核心区别,并且经常被忽略。
特别是,当您编写apply = atom atom / atom
时,如果有可能连续解析两个原子,则绝不会尝试仅解析一个原子,即使这意味着剩下的原子以后没有任何意义。
结合使用then
和else
是语法中的完美标识符这一事实,就可以看到问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。