kamadorueda / santiago

Santiago is a lexing and parsing toolkit for Rust
91 stars 7 forks source link

Precedence rules don't work #2

Closed idgrasp closed 2 years ago

idgrasp commented 2 years ago

Hi Kevin!

I tried to use Santiago in a project and found a problem with precedence rules: https://github.com/kamadorueda/santiago/blob/264bf39a29318ee9686aae4d9d805853123cbcc0/src/lib.rs#L447 The result of evaluated expression (1 + 2 * 3 / 6 - 7) must be -5. I've set the same Associativity rules in my grammar, and it doesn't work properly. String 1 + 2 * 3 is parsed into BinaryOp([BinaryOp([Int(1), Plus, Int(2)]), Multiply, Int(3)]), which is (1 + 2) * 3

kamadorueda commented 2 years ago

Very good catch! I can confirm the problem

I'm gonna give it a look

kamadorueda commented 2 years ago

This solves the problem:

--- a/tests/calculator_with_ast/grammar.rs
+++ b/tests/calculator_with_ast/grammar.rs
@@ -13,16 +13,15 @@ pub enum AST {

 pub fn grammar() -> Grammar<AST> {
     santiago::grammar!(
-        "expr" => rules "bin_op";
         "expr" => rules "int";

-        "bin_op" => rules "expr" "add" "expr" =>
+        "expr" => rules "expr" "add" "expr" =>
             AST::BinaryOperation;
-        "bin_op" => rules "expr" "subtract" "expr" =>
+        "expr" => rules "expr" "subtract" "expr" =>
             AST::BinaryOperation;
-        "bin_op" => rules "expr" "multiply" "expr" =>
+        "expr" => rules "expr" "multiply" "expr" =>
             AST::BinaryOperation;
-        "bin_op" => rules "expr" "divide" "expr" =>
+        "expr" => rules "expr" "divide" "expr" =>
BinaryOperation(
    [
        BinaryOperation(
            [
                Int(
                    1,
                ),
                OperatorAdd,
                BinaryOperation(
                    [
                        BinaryOperation(
                            [
                                Int(
                                    2,
                                ),
                                OperatorMultiply,
                                Int(
                                    3,
                                ),
                            ],
                        ),
                        OperatorDivide,
                        Int(
                            6,
                        ),
                    ],
                ),
            ],
        ),
        OperatorSubtract,
        Int(
            7,
        ),
    ],
)

I'm pending to investigate it further

kamadorueda commented 2 years ago

I just reviewed more thoroughly and:

idgrasp commented 2 years ago

Thank you a lot! That worked! Was debugging satisfies_disambiguation to try to find an answer :)

P.S. I'm practicing rust (switched from C++) and working on a pet project. I went through a lot of generators (including PEG generators without left recursion...) and I think Santiago is the best project for my purposes. After Flex+Lemon in C++ projects, it looks really handy and comfortable!

Thank you for your work!

I think this issue can be closed :)

kamadorueda commented 2 years ago

That's awesome, thank you!