summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-20 21:39:32 +0200
committerPaul Buetow <paul@buetow.org>2026-03-20 21:39:32 +0200
commit92c9b9c1cf5f6b1d71d9f0178ad262068b6d5684 (patch)
tree6cd199e1b696dfc2b40a5fed0fbcdb277d5ef018
parent8701f048229e0bbb2d97ba23a9ba38397eb70286 (diff)
internal/repl: add RPN support to REPL
- Import rpn package in repl.go - Add 'rpn' and 'calc' as built-in commands - Update executor to handle 'rpn <expr>' and 'calc <expr>' commands - Add rpn/calc descriptions to help text - All tests pass, go vet passes
-rw-r--r--internal/repl/commands.go19
-rw-r--r--internal/repl/repl.go23
2 files changed, 39 insertions, 3 deletions
diff --git a/internal/repl/commands.go b/internal/repl/commands.go
index 7800653..ad8a34d 100644
--- a/internal/repl/commands.go
+++ b/internal/repl/commands.go
@@ -6,7 +6,7 @@ import (
)
// builtinCommands defines the built-in REPL commands
-var builtinCommands = []string{"help", "clear", "quit", "exit"}
+var builtinCommands = []string{"help", "clear", "quit", "exit", "rpn", "calc"}
// Commands returns the list of built-in command names
func Commands() []string {
@@ -27,8 +27,11 @@ func ExecuteCommand(cmd string) (string, error) {
return "", cmdClear()
case "quit", "exit":
return "", cmdQuit()
+ case "rpn", "calc":
+ // rpn/calc commands are handled in executor(), not here
+ return "", nil
default:
- return "", fmt.Errorf("unknown command: %s. Available commands: help, clear, quit, exit", args[0])
+ return "", fmt.Errorf("unknown command: %s. Available commands: help, clear, quit, exit, rpn, calc", args[0])
}
}
@@ -40,6 +43,7 @@ Built-in Commands:
help <command> Show help for a specific topic
clear Clear the screen
quit / exit Exit the REPL
+ rpn / calc Evaluate an RPN (postfix notation) expression
Usage Examples:
20% of 150 Calculate 20% of 150
@@ -47,6 +51,15 @@ Usage Examples:
30 is what % of 150 Calculate what percentage 30 is of 150
30 is 20% of what Calculate what number 30 is 20% of
+RPN (Reverse Polish Notation) Examples:
+ rpn 3 4 + 3 + 4 = 7
+ rpn 3 4 + 4 4 - * (3 + 4) * (4 - 4) = 0
+ rpn x 5 = x x + Assign x=5, then x + x = 10
+ rpn 2 3 ^ 2^3 = 8
+ rpn 1 2 swap Swap top two stack values
+ rpn 1 2 3 dup Duplicate top value
+ rpn show Show current stack state
+
Keyboard Shortcuts (Vi Mode):
Normal Mode:
i Enter Insert mode
@@ -79,7 +92,7 @@ Press Ctrl+D or type 'quit'/'exit' to exit.
case "quit", "exit":
return "quit / exit - Exit the REPL\nUsage: quit or exit"
default:
- return fmt.Sprintf("No help available for: %s\nAvailable commands: help, clear, quit, exit", subCmd)
+ return fmt.Sprintf("No help available for: %s\nAvailable commands: help, clear, quit, exit, rpn, calc", subCmd)
}
}
diff --git a/internal/repl/repl.go b/internal/repl/repl.go
index 0f690e9..79a94f4 100644
--- a/internal/repl/repl.go
+++ b/internal/repl/repl.go
@@ -10,6 +10,7 @@ import (
"syscall"
"codeberg.org/snonux/perc/internal/calculator"
+ "codeberg.org/snonux/perc/internal/rpn"
"github.com/mattn/go-isatty"
"github.com/c-bata/go-prompt"
@@ -37,6 +38,19 @@ func executor(input string) {
return
}
+ // Check for rpn command prefix
+ if strings.HasPrefix(strings.ToLower(input), "rpn ") || strings.HasPrefix(strings.ToLower(input), "calc ") {
+ // Extract the expression after rpn/calc
+ rest := strings.TrimSpace(strings.TrimPrefix(input, strings.SplitN(input, " ", 2)[0]))
+ result, err := runRPN(rest)
+ if err != nil {
+ fmt.Printf("Error: %v\n", err)
+ return
+ }
+ fmt.Println(result)
+ return
+ }
+
// Run the calculation
result, err := calculator.Parse(input)
if err != nil {
@@ -46,6 +60,13 @@ func executor(input string) {
fmt.Println(result)
}
+// runRPN parses and evaluates an RPN expression
+func runRPN(input string) (string, error) {
+ vars := rpn.NewVariables().(*rpn.Variables)
+ rpnCalc := rpn.NewRPN(vars)
+ return rpnCalc.ParseAndEvaluate(input)
+}
+
// isBuiltinCommand checks if input starts with a built-in command
func isBuiltinCommand(input string) (string, bool) {
args := strings.Fields(input)
@@ -180,6 +201,8 @@ func getCommandDescription(cmd string) string {
"clear": "Clear the screen",
"quit": "Exit the REPL",
"exit": "Exit the REPL",
+ "rpn": "Evaluate an RPN (postfix notation) expression",
+ "calc": "Same as rpn - evaluate an RPN expression",
}
return descriptions[cmd]
}