Parcourir la source

Parsing variables -- Logical Operators

runningwater il y a 2 ans
Parent
commit
84910e1624

+ 67 - 59
README.md

@@ -28,78 +28,86 @@
 
 - **Literals**. Numbers,strings,Booleans, and nil
 - **Unary expressions.** A prefix ! to perform a logical not, and - to negate a number.
-- **Binary expressions.** The infix arithmetic(+,-,*,/) and logic operators (==, !=, <, <=,>,>=)
-    - **Parentheses.** A pair of ( and ) wrapped around and expression.
+  - **Binary expressions.** The infix arithmetic(+,-,*,/) and logic operators (==, !=, <, <=,>,>=)
+      - **Parentheses.** A pair of ( and ) wrapped around and expression.
 
-        - Syntax tree - Expression
+          - Syntax tree - Expression
 
-              ```
-              expression     → literal
-              | unary
-              | binary
-              | grouping ;
+                ```
+                expression     → literal
+                | unary
+                | binary
+                | grouping ;
 
-              literal        → NUMBER | STRING | "true" | "false" | "nil" ;
-              grouping       → "(" expression ")" ;
-              unary          → ( "-" | "!" ) expression ;
-              binary         → expression operator expression ;
-              operator       → "==" | "!=" | "<" | "<=" | ">" | ">="
-              | "+"  | "-"  | "*" | "/" ;
+                literal        → NUMBER | STRING | "true" | "false" | "nil" ;
+                grouping       → "(" expression ")" ;
+                unary          → ( "-" | "!" ) expression ;
+                binary         → expression operator expression ;
+                operator       → "==" | "!=" | "<" | "<=" | ">" | ">="
+                | "+"  | "-"  | "*" | "/" ;
 
-              ```
+                ```
 
-          | Name       | Operators | Associates |
-                    |------------|-----------|------------|
-          | Equality	  | == !=     | Left       |
-          | Comparison | > >= < <= | Left       |
-          | Term       | - +	      | Left       |
-          | Factor     | / *       | Left       |
-          | Unary      | ! -       | Right      |
+            | Name       | Operators | Associates |
+                      |------------|-----------|------------|
+            | Equality	  | == !=     | Left       |
+            | Comparison | > >= < <= | Left       |
+            | Term       | - +	      | Left       |
+            | Factor     | / *       | Left       |
+            | Unary      | ! -       | Right      |
 
-            ```
-            expression     → equality ;
-            equality       → comparison ( ( "!=" | "==" ) comparison )* ;
-            comparison     → term ( ( ">" | ">=" | "<" | "<=" ) term )* ;
-            term           → factor ( ( "-" | "+" ) factor )* ;
-            factor         → unary ( ( "/" | "*" ) unary )* ;
-            unary          → ( "!" | "-" ) unary
-                           | primary ;
-            primary        → NUMBER | STRING | "true" | "false" | "nil"
-                           | "(" expression ")" | IDENTIFIER ;
-           ```
+              ```
+              expression     → equality ;
+              equality       → comparison ( ( "!=" | "==" ) comparison )* ;
+              comparison     → term ( ( ">" | ">=" | "<" | "<=" ) term )* ;
+              term           → factor ( ( "-" | "+" ) factor )* ;
+              factor         → unary ( ( "/" | "*" ) unary )* ;
+              unary          → ( "!" | "-" ) unary
+                             | primary ;
+              primary        → NUMBER | STRING | "true" | "false" | "nil"
+                             | "(" expression ")" | IDENTIFIER ;
+             ```
 
-          - Syntax tree - Statement
+            - Syntax tree - Statement
 
-              ```
-              program        → statement* EOF ;
+                ```
+                program        → statement* EOF ;
       
-              statement      → exprStmt
-                             | printStmt 
-                             | block;
+                statement      → exprStmt
+                               | printStmt 
+                               | block;
             
-              block         → "{" declaration* "}"
+                block         → "{" declaration* "}"
       
-              exprStmt       → expression ";" ;
-              printStmt      → "print" expression ";" ;
-              ```
+                exprStmt       → expression ";" ;
+                printStmt      → "print" expression ";" ;
+                ```
 
-            A program is a list of statements followed by the special "end of file" token.
-            The mandatory end token ensures the parse consumes the entire input and don't
-            silently ignore erroneous unconsumed tokens at the end of a script.
-        - Syntax tree - add Variable syntax
-          ```
-            program   → declaration* EOF ;
+              A program is a list of statements followed by the special "end of file" token.
+              The mandatory end token ensures the parse consumes the entire input and don't
+              silently ignore erroneous unconsumed tokens at the end of a script.
+          - Syntax tree - add Variable syntax
+            ```
+              program   → declaration* EOF ;
           
-            declaration  → varDecl
-                         | statement ;
+              declaration  → varDecl
+                           | statement ;
           
-             statement      → exprStmt
-                             | ifStmt
-                             | printStmt 
-                             | block;
+               statement      → exprStmt
+                               | ifStmt
+                               | printStmt 
+                               | block;
             
-             block         → "{" declaration* "}"
-             ifStmt        → "if" "(" expression ")" statement ( "else" statement)? ;
+               block         → "{" declaration* "}"
+               ifStmt        → "if" "(" expression ")" statement ( "else" statement)? ;
             
-            varDecl  → "var" IDENTIFIER ( "=" expression )? ";" ;
-          ```
+              varDecl  → "var" IDENTIFIER ( "=" expression )? ";" ;
+            ```
+          - Syntax tree -- Logical Operators
+            ```
+              expression     → assignment ;
+              assignment     → IDENTIFIER "=" assignment
+              | logic_or ;
+              logic_or       → logic_and ( "or" logic_and )* ;
+              logic_and      → equality ( "and" equality )* ;
+            ```

+ 10 - 35
src/main/java/com/craftinginterpreters/lox/AstPrinter.java

@@ -9,7 +9,7 @@ import java.util.List;
  * @date 2023-06-05 13:19
  * @desc
  */
-public class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
+public class AstPrinter implements Expr.Visitor<String> {
   String print(List<Stmt> statements) {
     StringBuilder builder = new StringBuilder();
     for (Stmt statement : statements) {
@@ -21,40 +21,6 @@ public class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
   }
 
   @Override
-  public String visitBlockStmt(Stmt.Block stmt) {
-    StringBuilder builder = new StringBuilder();
-    builder.append("    {").append("\n");
-    for (Stmt statement : stmt.statements) {
-      builder.append("      ").append(statement.accept(this)).append("\n");
-    }
-    builder.append("    }").append("\n");
-    return builder.toString();
-  }
-
-  @Override
-  public String visitExpressionStmt(Stmt.Expression stmt) {
-    return stmt.expression.accept(this);
-  }
-
-  @Override
-  public String visitIfStmt(Stmt.If stmt) {
-    String condition = "if (" + parenthesize(null, stmt.condition) + ")";
-    // TODO
-    return condition;
-  }
-
-  @Override
-  public String visitPrintStmt(Stmt.Print stmt) {
-    return parenthesize("print", stmt.expression);
-  }
-
-  @Override
-  public String visitVarStmt(Stmt.Var stmt) {
-    return parenthesize(
-        "var", stmt.initializer == null ? new Expr.Literal(null) : stmt.initializer);
-  }
-
-  @Override
   public String visitAssignExpr(Expr.Assign expr) {
     return parenthesize("assign", expr.value);
   }
@@ -76,6 +42,15 @@ public class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
   }
 
   @Override
+  public String visitLogicalExpr(Expr.Logical expr) {
+    return parenthesize(null, expr.left)
+        + " "
+        + expr.operator.lexeme.toUpperCase()
+        + " "
+        + parenthesize(null, expr.right);
+  }
+
+  @Override
   public String visitUnaryExpr(Expr.Unary expr) {
     return parenthesize(expr.operator.lexeme, expr.right);
   }

+ 90 - 73
src/main/java/com/craftinginterpreters/lox/Expr.java

@@ -2,110 +2,127 @@ package com.craftinginterpreters.lox;
 
 /**
  * @author GenerateAst
- * @date 2023-06-12 16:03
+ * @date 2023-06-14 12:08
  */
 abstract class Expr {
-    interface Visitor<R> {
-        R visitAssignExpr(Assign expr);
+  interface Visitor<R> {
+    R visitAssignExpr(Assign expr);
 
-        R visitBinaryExpr(Binary expr);
+    R visitBinaryExpr(Binary expr);
 
-        R visitGroupingExpr(Grouping expr);
+    R visitGroupingExpr(Grouping expr);
 
-        R visitLiteralExpr(Literal expr);
+    R visitLiteralExpr(Literal expr);
 
-        R visitUnaryExpr(Unary expr);
+    R visitLogicalExpr(Logical expr);
 
-        R visitVariableExpr(Variable expr);
+    R visitUnaryExpr(Unary expr);
 
+    R visitVariableExpr(Variable expr);
+  }
+
+  static class Assign extends Expr {
+    Assign(Token name, Expr value) {
+      this.name = name;
+      this.value = value;
     }
 
+    @Override
+    <R> R accept(Visitor<R> visitor) {
+      return visitor.visitAssignExpr(this);
+    }
 
-    static class Assign extends Expr {
-        Assign(Token name, Expr value) {
-            this.name = name;
-            this.value = value;
-        }
+    final Token name;
+    final Expr value;
+  }
 
-        @Override
-        <R> R accept(Visitor<R> visitor) {
-            return visitor.visitAssignExpr(this);
-        }
+  static class Binary extends Expr {
+    Binary(Expr left, Token operator, Expr right) {
+      this.left = left;
+      this.operator = operator;
+      this.right = right;
+    }
 
-        final Token name;
-        final  Expr value;
+    @Override
+    <R> R accept(Visitor<R> visitor) {
+      return visitor.visitBinaryExpr(this);
     }
 
-    static class Binary extends Expr {
-        Binary(Expr left, Token operator, Expr right) {
-            this.left = left;
-            this.operator = operator;
-            this.right = right;
-        }
-
-        @Override
-        <R> R accept(Visitor<R> visitor) {
-            return visitor.visitBinaryExpr(this);
-        }
-
-        final Expr left;
-        final  Token operator;
-        final  Expr right;
+    final Expr left;
+    final Token operator;
+    final Expr right;
+  }
+
+  static class Grouping extends Expr {
+    Grouping(Expr expression) {
+      this.expression = expression;
     }
 
-    static class Grouping extends Expr {
-        Grouping(Expr expression) {
-            this.expression = expression;
-        }
+    @Override
+    <R> R accept(Visitor<R> visitor) {
+      return visitor.visitGroupingExpr(this);
+    }
 
-        @Override
-        <R> R accept(Visitor<R> visitor) {
-            return visitor.visitGroupingExpr(this);
-        }
+    final Expr expression;
+  }
 
-        final Expr expression;
+  static class Literal extends Expr {
+    Literal(Object value) {
+      this.value = value;
     }
 
-    static class Literal extends Expr {
-        Literal(Object value) {
-            this.value = value;
-        }
+    @Override
+    <R> R accept(Visitor<R> visitor) {
+      return visitor.visitLiteralExpr(this);
+    }
 
-        @Override
-        <R> R accept(Visitor<R> visitor) {
-            return visitor.visitLiteralExpr(this);
-        }
+    final Object value;
+  }
 
-        final Object value;
+  static class Logical extends Expr {
+    Logical(Expr left, Token operator, Expr right) {
+      this.left = left;
+      this.operator = operator;
+      this.right = right;
     }
 
-    static class Unary extends Expr {
-        Unary(Token operator, Expr right) {
-            this.operator = operator;
-            this.right = right;
-        }
+    @Override
+    <R> R accept(Visitor<R> visitor) {
+      return visitor.visitLogicalExpr(this);
+    }
 
-        @Override
-        <R> R accept(Visitor<R> visitor) {
-            return visitor.visitUnaryExpr(this);
-        }
+    final Expr left;
+    final Token operator;
+    final Expr right;
+  }
 
-        final Token operator;
-        final  Expr right;
+  static class Unary extends Expr {
+    Unary(Token operator, Expr right) {
+      this.operator = operator;
+      this.right = right;
     }
 
-    static class Variable extends Expr {
-        Variable(Token name) {
-            this.name = name;
-        }
+    @Override
+    <R> R accept(Visitor<R> visitor) {
+      return visitor.visitUnaryExpr(this);
+    }
 
-        @Override
-        <R> R accept(Visitor<R> visitor) {
-            return visitor.visitVariableExpr(this);
-        }
+    final Token operator;
+    final Expr right;
+  }
 
-        final Token name;
+  static class Variable extends Expr {
+    Variable(Token name) {
+      this.name = name;
     }
 
-    abstract <R> R accept(Visitor<R> visitor);
+    @Override
+    <R> R accept(Visitor<R> visitor) {
+      return visitor.visitVariableExpr(this);
+    }
+
+    final Token name;
+  }
+
+  abstract <R> R accept(Visitor<R> visitor);
 }

+ 12 - 0
src/main/java/com/craftinginterpreters/lox/Interpreter.java

@@ -94,6 +94,18 @@ public class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
   }
 
   @Override
+  public Object visitLogicalExpr(Expr.Logical expr) {
+    Object left = evaluate(expr.left);
+
+    if (expr.operator.type == TokenType.OR) {
+      if (isTruthy(left)) return left;
+    } else {
+      if (!isTruthy(left)) return left;
+    }
+    return evaluate(expr.right);
+  }
+
+  @Override
   public Object visitUnaryExpr(Expr.Unary expr) {
     Object right = evaluate(expr.right);
 

+ 28 - 2
src/main/java/com/craftinginterpreters/lox/Parser.java

@@ -118,9 +118,9 @@ public class Parser {
     return assignment();
   }
 
-  // assignment → IDENTIFIER "=" assignment | equality
+  // assignment → IDENTIFIER "=" assignment | equality | logic_or
   private Expr assignment() {
-    Expr expr = equality();
+    Expr expr = or();
     if (match(EQUAL)) {
       Token equals = previous();
       Expr value = assignment();
@@ -135,6 +135,32 @@ public class Parser {
     return expr;
   }
 
+  // logic_or       → logic_and ( "or" logic_and )* ;
+  private Expr or() {
+    Expr expr = and();
+
+    while (match(OR)) {
+      Token operator = previous();
+      Expr right = and();
+      expr = new Expr.Logical(expr, operator, right);
+    }
+
+    return expr;
+  }
+
+  // logic_and      → equality ( "and" equality )* ;
+  private Expr and() {
+    Expr expr = equality();
+
+    while (match(AND)) {
+      Token operator = previous();
+      Expr right = equality();
+      expr = new Expr.Logical(expr, operator, right);
+    }
+
+    return expr;
+  }
+
   // equality  → comparison ( ( "!=" | "==" ) comparison )* ;
   private Expr equality() {
     Expr expr = comparison();

+ 8 - 7
src/main/java/com/craftinginterpreters/tool/GenerateAst.java

@@ -47,16 +47,17 @@ public class GenerateAst {
                 "Binary   : Expr left, Token operator, Expr right",
                 "Grouping : Expr expression",
                 "Literal  : Object value",
+                "Logical  : Expr left, Token operator, Expr right",
                 "Unary    : Token operator, Expr right",
                 "Variable : Token name"
         ));
-        defineAst(outputDir, "Stmt", Arrays.asList(
-                "Block       : List<Stmt> statements",
-                "Expression  : Expr expression",
-                "If          : Expr condition, Stmt thenBranch, Stmt elseBranch",
-                "Print       : Expr expression",
-                "Var         : Token name, Expr initializer"
-        ));
+//        defineAst(outputDir, "Stmt", Arrays.asList(
+//                "Block       : List<Stmt> statements",
+//                "Expression  : Expr expression",
+//                "If          : Expr condition, Stmt thenBranch, Stmt elseBranch",
+//                "Print       : Expr expression",
+//                "Var         : Token name, Expr initializer"
+//        ));
     }
 
     private static void defineAst(String outputDir, String baseName, List<String> types)