Evaluating Expressions

This commit is contained in:
Ashley Rose 2025-11-01 22:09:40 -05:00
parent bbd8a8ca66
commit 9d05747655
Signed by untrusted user who does not match committer: rosyowo
GPG key ID: 999CEF726392D8F9
5 changed files with 194 additions and 0 deletions

View file

@ -0,0 +1,2 @@
---
BasedOnStyle: GNU

View file

@ -0,0 +1,164 @@
package me.rose.lox;
class Interpreter implements Expr.Visitor<Object>
{
void
interpret (Expr expression)
{
try
{
Object value = evaluate (expression);
System.out.println (stringify (value));
}
catch (RuntimeError error)
{
Lox.runtimeError (error);
}
}
private Object
evaluate (Expr expr)
{
return expr.accept (this);
}
@Override
public Object
visitGroupingExpr (Expr.Grouping expr)
{
return evaluate (expr.expression);
}
@Override
public Object
visitBinaryExpr (Expr.Binary expr)
{
Object left = evaluate (expr.left);
Object right = evaluate (expr.right);
switch (expr.operator.type)
{
case GREATER:
checkNumberOperand (expr.operator, left, right);
return (double)left > (double)right;
case GREATER_EQUAL:
checkNumberOperand (expr.operator, left, right);
return (double)left >= (double)right;
case LESS:
checkNumberOperand (expr.operator, left, right);
return (double)left < (double)right;
case LESS_EQUAL:
checkNumberOperand (expr.operator, left, right);
return (double)left <= (double)right;
case BANG_EQUAL:
return !isEqual (left, right);
case EQUAL_EQUAL:
return isEqual (left, right);
case MINUS:
checkNumberOperand (expr.operator, left, right);
return (double)left - (double)right;
case PLUS:
if (left instanceof Double && right instanceof Double)
{
return (double)left + (double)right;
}
if (left instanceof String && right instanceof String)
{
return (String)left + (String)right;
}
throw new RuntimeError (
expr.operator, "Operands must be two numbers or two strings.");
case SLASH:
checkNumberOperand (expr.operator, left, right);
return (double)left / (double)right;
case STAR:
checkNumberOperand (expr.operator, left, right);
return (double)left * (double)right;
}
return null;
}
@Override
public Object
visitLiteralExpr (Expr.Literal expr)
{
return expr.value;
}
@Override
public Object
visitUnaryExpr (Expr.Unary expr)
{
Object right = evaluate (expr.right);
switch (expr.operator.type)
{
case BANG:
return !isTruthy (right);
case MINUS:
checkNumberOperand (expr.operator, right);
return -(double)right;
}
return null;
}
private void
checkNumberOperand (Token operator, Object operand)
{
if (operand instanceof Double)
return;
throw new RuntimeError (operator, "Operand must be a number.");
}
private void
checkNumberOperand (Token operator, Object left, Object right)
{
if (left instanceof Double && right instanceof Double)
return;
throw new RuntimeError (operator, "Operands must be numbers.");
}
private boolean
isTruthy (Object object)
{
if (object == null)
return false;
if (object instanceof Boolean)
return (boolean)object;
return true;
}
private boolean
isEqual (Object a, Object b)
{
if (a == null && b == null)
return true;
if (a == null)
return false;
return a.equals (b);
}
private String
stringify (Object object)
{
if (object == null)
return "nil";
if (object instanceof Double)
{
String text = object.toString ();
if (text.endsWith (".0"))
{
text = text.substring (0, text.length () - 2);
}
return text;
}
return object.toString ();
}
}

View file

@ -10,7 +10,9 @@ import java.util.List;
public class Lox
{
private static final Interpreter interpreter = new Interpreter ();
static boolean hadError = false;
static boolean hadRuntimeError = false;
public static void
main (String[] args) throws IOException
@ -38,6 +40,8 @@ public class Lox
if (hadError)
System.exit (65);
if (hadRuntimeError)
System.exit (70);
}
private static void
@ -67,6 +71,8 @@ public class Lox
if (hadError)
return;
interpreter.interpret (expression);
}
static void
@ -75,6 +81,14 @@ public class Lox
report (line, "", message);
}
static void
runtimeError (RuntimeError error)
{
System.err.println (error.getMessage () + "\n[line " + error.token.line
+ "]");
hadRuntimeError = true;
}
private static void
report (int line, String where, String message)
{

View file

@ -0,0 +1,12 @@
package me.rose.lox;
class RuntimeError extends RuntimeException
{
final Token token;
RuntimeError (Token token, String message)
{
super (message);
this.token = token;
}
}

View file

@ -0,0 +1,2 @@
---
BasedOnStyle: GNU