首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用rust和pomelo在backus naur形式中表示if-else语句?

如何使用rust和pomelo在backus naur形式中表示if-else语句?
EN

Stack Overflow用户
提问于 2021-07-08 05:02:17
回答 1查看 45关注 0票数 0

我试图在rust中使用pomelo来解析一种脚本语言,但在该语言的backus-naur表示中遇到了障碍,它无法像我定义的那样解析if-else语句。例如,如果它要解析语句

代码语言:javascript
复制
if (1) {
  return;
}

解析器将会成功,但是如果我向代码中添加一个else语句,比如

代码语言:javascript
复制
if (1) {
 return;
} else {
 return;
}

它将在else标记处抛出一个语法错误,具体地说,我得到的输出是

代码语言:javascript
复制
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表单中错误的确切原因,因此我不知道如何压缩它以产生相同的错误。

代码语言:javascript
复制
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();
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-08 05:54:06

对于遇到类似问题的任何人来说,问题在于else标记的关联性,将else标记从左关联更改为右关联起到了作用

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68292939

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档