我试图在rust中使用pomelo来解析一种脚本语言,但在该语言的backus-naur表示中遇到了障碍,它无法像我定义的那样解析if-else语句。例如,如果它要解析语句
if (1) {
return;
}解析器将会成功,但是如果我向代码中添加一个else语句,比如
if (1) {
return;
} else {
return;
}它将在else标记处抛出一个语法错误,具体地说,我得到的输出是
gettin If
gettin LParen
gettin Num(1)
gettin RParen
gettin LBrace
gettin Return
gettin Semicolon
gettin RBrace
gettin Else
should not execute this
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: "syntax Some(Else)"', src/main.rs:122:24
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace在查看bnf表单时,我似乎不太清楚为什么这会失败。我很抱歉这个最小的可重现示例的大量代码,但我不知道bnf表单中错误的确切原因,因此我不知道如何压缩它以产生相同的错误。
extern crate pomelo;
use pomelo::pomelo;
pomelo!{
%error String;
%syntax_error{
Err(format!("syntax {:?}",token))
}
%parse_fail {
"Giving up. Parser is hopelessly lost...".to_string()
}
%token #[derive(Debug)] pub enum Token {};
//define types to make the compiler happy
%type Ident String;
%type Type String;
%type Num i64;
%type String String;
%type expr Vec<String>;
%type expr_list Vec<Vec<String>>;
%type stmt Vec<String>;
%type input Option<Vec<Vec<String>>>;
%type block Vec<Vec<String>>;
%type decl_list Vec<Vec<String>>;
%type stmt_list Vec<Vec<String>>;
%type func_list Vec<Vec<String>>;
%type arg_list Vec<String>;
%type type_list Vec<String>;
%type package String;
%type imports Vec<String>;
%type f_decl Vec<String>;
%type type_t Vec<Vec<String>>;
%type type_s Vec<Vec<String>>;
%type decl Vec<Vec<String>>;
%type assignment String;
%type CheckMark String;
%type Todo String;
%left Else;
%right Eq;
%left Or;
%left And;
%nonassoc Equal Neq;
%nonassoc Less LessEq Greater GreaterEq;
%left Add Sub;
%left Mul Div;
%nonassoc Not;
input ::= type_s?(v) {v /*assigning worthless values to make the compiler happy*/};
type_t ::= stmt(a) {vec![a]}
type_s ::= type_t(t) {t}
type_s ::= type_s(mut a) type_t(b) {a.extend(b);a}
stmt ::= KeyFunction Ident(name) LParen arg_list?(args) RParen block(code) {vec![name]}
assignment ::= Ident(a) Eq expr(b) {a}
arg_list ::= Ident(n) [Semicolon] { vec![n] }
arg_list ::= assignment(n) {vec![n]}
arg_list ::= arg_list(mut args) Comma Ident(n) { args.push(n); args }
block ::= LBrace stmt_list?(ss) RBrace { ss.unwrap_or(Vec::new()) }
stmt_list ::= stmt(s) { vec![s] }
stmt_list ::= stmt_list(mut ss) stmt(s) { ss.push(s); ss }
stmt ::= block(ss) { ss.get(0).unwrap_or(&Vec::new()).clone() }
stmt ::= expr(e) Semicolon {e}
stmt ::= Ident(a) Eq expr(b) Semicolon { vec![a] }
stmt ::= Var Ident(a) Eq expr(b) Semicolon { vec![a]}
stmt ::= If LParen expr(e) RParen stmt(s1) Else stmt(s2) {println!("should execute this"); s1 }
stmt ::= If LParen expr(e) RParen stmt(s1) [Else] {println!("should not execute this"); s1 }
stmt ::= While LParen expr(e) RParen stmt(s) { s }
stmt ::= Return expr(e) Semicolon { e }
stmt ::= Return Semicolon { vec!["".to_string()] }
stmt ::= Break Semicolon { vec!["".to_string()] }
stmt ::= Continue Semicolon {vec!["".to_string()] }
stmt ::= Todo(a) expr(b) Semicolon {vec![a]}
stmt ::= CheckMark(a) {vec![a]}
expr ::= Num(n) { vec!["".to_string()] }
expr ::= String(n) {vec!["".to_string()]}
expr ::= Ident(n) {vec!["".to_string()] }
expr ::= Ident(n) LParen expr_list?(es) RParen {vec![n]}
expr ::= LParen expr(e) RParen { e }
expr ::= expr(a) Add expr(b) { a}
expr ::= expr(a) Sub expr(b) { a }
expr ::= expr(a) Mul expr(b) {a}
expr ::= expr(a) Div expr(b) {a}
expr ::= Sub expr(a) [Not] { a }
expr ::= expr(a) Equal expr(b) { a }
expr ::= expr(a) Neq expr(b) { a }
expr ::= expr(a) And expr(b) { a }
expr ::= expr(a) Or expr(b) {a }
expr ::= Not expr(a) { a }
expr ::= expr(a) Less expr(b) { a }
expr ::= expr(a) Greater expr(b) { a }
expr ::= expr(a) LessEq expr(b) { a }
expr ::= expr(a) GreaterEq expr(b) { a }
expr_list ::= expr(e) { vec![e] }
expr_list ::= expr_list(mut es) Comma expr(e) { es.push(e); es }
}
fn main() {
let mut parse = parser::Parser::new();
let code = vec![
parser::Token::If,
parser::Token::LParen,
parser::Token::Num(1),
parser::Token::RParen,
parser::Token::LBrace,
parser::Token::Return,
parser::Token::Semicolon,
parser::Token::RBrace,
parser::Token::Else,
parser::Token::LBrace,
parser::Token::Return,
parser::Token::Semicolon,
parser::Token::RBrace
];
for i in code {
println!("gettin {:?}",i);
parse.parse(i).unwrap();
}
parse.end_of_input().unwrap();
}发布于 2021-07-08 05:54:06
对于遇到类似问题的任何人来说,问题在于else标记的关联性,将else标记从左关联更改为右关联起到了作用
https://stackoverflow.com/questions/68292939
复制相似问题