mirror of
https://github.com/louisrubet/rpn
synced 2025-02-07 08:45:48 +01:00
Remove c++20 warnings
Remove pragmas, modify RpnInprog
This commit is contained in:
parent
db3420fa95
commit
b5c23d33ae
7 changed files with 175 additions and 185 deletions
11
src/lexer.cc
11
src/lexer.cc
|
@ -2,9 +2,6 @@
|
|||
|
||||
#include "lexer.h"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic" // allow designated initializers
|
||||
|
||||
bool Lexer::Analyse(const string& entry, map<string, ReservedWord>& keywords, vector<SynElement>& elements,
|
||||
vector<SynError>& errors) {
|
||||
size_t jump;
|
||||
|
@ -186,7 +183,7 @@ bool Lexer::ParseNumber(const string& entry, size_t idx, size_t& next_idx, vecto
|
|||
vector<SynElement>& elements) {
|
||||
mpreal* r = nullptr;
|
||||
int base = 10;
|
||||
if (GetNUmberAt(entry, idx, next_idx, base, &r)) {
|
||||
if (GetNumberAt(entry, idx, next_idx, base, &r)) {
|
||||
elements.push_back({.type = kNumber, .re = r, .re_base = base});
|
||||
return true;
|
||||
} else {
|
||||
|
@ -205,7 +202,7 @@ bool Lexer::ParseComplex(const string& entry, size_t idx, size_t& next_idx, vect
|
|||
next_idx = entry.size();
|
||||
return true; // complex format error, return a symbol
|
||||
}
|
||||
if (!GetNUmberAt(entry, idx + 1, next_idx, re_base, &re, ',')) {
|
||||
if (!GetNumberAt(entry, idx + 1, next_idx, re_base, &re, ',')) {
|
||||
elements.push_back({.type = kSymbol, .value = entry.substr(idx, entry.size() - idx)});
|
||||
next_idx = entry.size();
|
||||
return true; // complex format error, return a symbol
|
||||
|
@ -220,7 +217,7 @@ bool Lexer::ParseComplex(const string& entry, size_t idx, size_t& next_idx, vect
|
|||
return true; // complex format error, return a symbol
|
||||
}
|
||||
|
||||
if (!GetNUmberAt(entry, i, next_idx, im_base, &im, ')')) {
|
||||
if (!GetNumberAt(entry, i, next_idx, im_base, &im, ')')) {
|
||||
elements.push_back({.type = kSymbol, .value = entry.substr(idx, entry.size() - idx)});
|
||||
next_idx = entry.size();
|
||||
if (re != nullptr) delete re;
|
||||
|
@ -255,5 +252,3 @@ bool Lexer::ParseUnknown(const string& entry, size_t idx, size_t& next_idx, vect
|
|||
next_idx = token.size() + idx;
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
|
|
@ -23,7 +23,7 @@ class Lexer {
|
|||
mpreal* im;
|
||||
int re_base;
|
||||
int im_base;
|
||||
program_fn_t fn;
|
||||
object_cb_t fn;
|
||||
bool auto_eval;
|
||||
};
|
||||
|
||||
|
@ -34,7 +34,7 @@ class Lexer {
|
|||
|
||||
struct ReservedWord {
|
||||
ObjectType type;
|
||||
program_fn_t fn;
|
||||
object_cb_t fn;
|
||||
};
|
||||
|
||||
Lexer() {}
|
||||
|
|
|
@ -49,7 +49,8 @@ static void CtrlHandler(int sig __attribute__((unused)), siginfo_t* siginfo __at
|
|||
}
|
||||
|
||||
static void CatchCtrlC() {
|
||||
struct sigaction act = {0};
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
act.sa_sigaction = &CtrlHandler;
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
if (sigaction(SIGINT, &act, nullptr) < 0)
|
||||
|
|
|
@ -69,9 +69,13 @@ struct Object {
|
|||
};
|
||||
|
||||
class Program;
|
||||
class Branch;
|
||||
struct Branch;
|
||||
typedef void (Program::*program_fn_t)(void);
|
||||
typedef size_t (Program::*branch_fn_t)(Branch&);
|
||||
union object_cb_t {
|
||||
program_fn_t prog;
|
||||
branch_fn_t branch;
|
||||
};
|
||||
|
||||
/// @brief stack objects derived from Object
|
||||
///
|
||||
|
|
314
src/program.cc
314
src/program.cc
|
@ -3,206 +3,199 @@
|
|||
#include "program.h"
|
||||
|
||||
//< language reserved keywords (allowed types are kKeyword, kBranch or kUndef)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type" // allow casting kBranch callbacks
|
||||
#pragma GCC diagnostic ignored "-Wpedantic" // allow designated initializers for keywords_
|
||||
vector<Program::keyword_t> Program::keywords_{
|
||||
// clang-format off
|
||||
vector<Program::keyword_t> Program::keywords_ = {
|
||||
// GENERAL
|
||||
{kUndef, "", nullptr, "\nGENERAL"},
|
||||
{kKeyword, "help", &Program::RpnHelp, "this help message"},
|
||||
{kKeyword, "h", &Program::RpnHelp, ""},
|
||||
{kKeyword, "?", &Program::RpnHelp, ""},
|
||||
{kKeyword, "quit", &Program::RpnQuit, "quit software"},
|
||||
{kKeyword, "q", &Program::RpnQuit, ""},
|
||||
{kKeyword, "exit", &Program::RpnQuit, ""},
|
||||
{kKeyword, "test", &Program::RpnTest, ""}, // not seen by user
|
||||
{kKeyword, "version", &Program::RpnVersion, "show rpn version"},
|
||||
{kKeyword, "uname", &Program::RpnUname, "show rpn complete identification string"},
|
||||
{kKeyword, "history", &Program::RpnHistory, "see commands history"},
|
||||
{kKeyword, "help", {.prog = &Program::RpnHelp}, "this help message"},
|
||||
{kKeyword, "h", {.prog = &Program::RpnHelp}, ""},
|
||||
{kKeyword, "?", {.prog = &Program::RpnHelp}, ""},
|
||||
{kKeyword, "quit", {.prog = &Program::RpnQuit}, "quit software"},
|
||||
{kKeyword, "q", {.prog = &Program::RpnQuit}, ""},
|
||||
{kKeyword, "exit", {.prog = &Program::RpnQuit}, ""},
|
||||
{kKeyword, "test", {.prog = &Program::RpnTest}, ""},
|
||||
{kKeyword, "version", {.prog = &Program::RpnVersion}, "show rpn version"},
|
||||
{kKeyword, "uname", {.prog = &Program::RpnUname}, "show rpn complete identification string"},
|
||||
{kKeyword, "history", {.prog = &Program::RpnHistory}, "see commands history"},
|
||||
|
||||
// USUAL OPERATIONS ON REALS AND COMPLEXES
|
||||
{kUndef, "", nullptr, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"},
|
||||
{kKeyword, "+", &Program::RpnPlus, "addition"},
|
||||
{kKeyword, "-", &Program::RpnMinus, "substraction"},
|
||||
{kKeyword, "*", &Program::RpnMul, "multiplication"},
|
||||
{kKeyword, "/", &Program::RpnDiv, "division"},
|
||||
{kKeyword, "inv", &Program::RpnInv, "inverse"},
|
||||
{kKeyword, "chs", &Program::RpnNeg, "negation"},
|
||||
{kKeyword, "neg", &Program::RpnNeg, ""},
|
||||
{kKeyword, "^", &Program::RpnPower, "power"},
|
||||
{kKeyword, "pow", &Program::RpnPower, ""},
|
||||
{kKeyword, "sqrt", &Program::RpnSquareroot, "RpnSquare root"},
|
||||
{kKeyword, "sq", &Program::RpnSquare, "RpnSquare"},
|
||||
{kKeyword, "abs", &Program::RpnAbs, "absolute value (norm for a complex)"},
|
||||
{kKeyword, "sign", &Program::RpnSign, "sign of a number or z/|z| for a complex"},
|
||||
{kKeyword, "+", {.prog = &Program::RpnPlus}, "addition"},
|
||||
{kKeyword, "-", {.prog = &Program::RpnMinus}, "substraction"},
|
||||
{kKeyword, "*", {.prog = &Program::RpnMul}, "multiplication"},
|
||||
{kKeyword, "/", {.prog = &Program::RpnDiv}, "division"},
|
||||
{kKeyword, "inv", {.prog = &Program::RpnInv}, "inverse"},
|
||||
{kKeyword, "chs", {.prog = &Program::RpnNeg}, "negation"},
|
||||
{kKeyword, "neg", {.prog = &Program::RpnNeg}, ""},
|
||||
{kKeyword, "^", {.prog = &Program::RpnPower}, "power"},
|
||||
{kKeyword, "pow", {.prog = &Program::RpnPower}, ""},
|
||||
{kKeyword, "sqrt", {.prog = &Program::RpnSquareroot}, "RpnSquare root"},
|
||||
{kKeyword, "sq", {.prog = &Program::RpnSquare}, "RpnSquare"},
|
||||
{kKeyword, "abs", {.prog = &Program::RpnAbs}, "absolute value (norm for a complex)"},
|
||||
{kKeyword, "sign", {.prog = &Program::RpnSign}, "sign of a number or z/|z| for a complex"},
|
||||
|
||||
// OPERATIONS ON REALS
|
||||
{kUndef, "", nullptr, "\nOPERATIONS ON REALS"},
|
||||
{kKeyword, "%", &Program::RpnPurcent, "purcent"},
|
||||
{kKeyword, "%CH", &Program::RpnPurcentCH, "inverse purcent"},
|
||||
{kKeyword, "mod", &Program::RpnModulo, "modulo"},
|
||||
{kKeyword, "fact", &Program::RpnFact, "n! for integer n or Gamma(x+1) for fractional x"},
|
||||
{kKeyword, "mant", &Program::RpnMant, "mantissa of a real number"},
|
||||
{kKeyword, "xpon", &Program::RpnXpon, "exponant of a real number"},
|
||||
{kKeyword, "floor", &Program::RpnFloor, "largest number <="},
|
||||
{kKeyword, "ceil", &Program::RpnCeil, "smallest number >="},
|
||||
{kKeyword, "ip", &Program::RpnIp, "integer part"},
|
||||
{kKeyword, "fp", &Program::RpnFp, "fractional part"},
|
||||
{kKeyword, "min", &Program::RpnMin, "min of 2 real numbers"},
|
||||
{kKeyword, "max", &Program::RpnMax, "max of 2 real numbers"},
|
||||
{kKeyword, "%", {.prog = &Program::RpnPurcent}, "purcent"},
|
||||
{kKeyword, "%CH", {.prog = &Program::RpnPurcentCH}, "inverse purcent"},
|
||||
{kKeyword, "mod", {.prog = &Program::RpnModulo}, "modulo"},
|
||||
{kKeyword, "fact", {.prog = &Program::RpnFact}, "n! for integer n or Gamma(x+1) for fractional x"},
|
||||
{kKeyword, "mant", {.prog = &Program::RpnMant}, "mantissa of a real number"},
|
||||
{kKeyword, "xpon", {.prog = &Program::RpnXpon}, "exponant of a real number"},
|
||||
{kKeyword, "floor", {.prog = &Program::RpnFloor}, "largest number <="},
|
||||
{kKeyword, "ceil", {.prog = &Program::RpnCeil}, "smallest number >="},
|
||||
{kKeyword, "ip", {.prog = &Program::RpnIp}, "integer part"},
|
||||
{kKeyword, "fp", {.prog = &Program::RpnFp}, "fractional part"},
|
||||
{kKeyword, "min", {.prog = &Program::RpnMin}, "min of 2 real numbers"},
|
||||
{kKeyword, "max", {.prog = &Program::RpnMax}, "max of 2 real numbers"},
|
||||
|
||||
// OPERATIONS ON COMPLEXES
|
||||
{kUndef, "", nullptr, "\nOPERATIONS ON COMPLEXES"},
|
||||
{kKeyword, "re", &Program::RpnReal, "complex real part"},
|
||||
{kKeyword, "im", &Program::RpnImag, "complex imaginary part"},
|
||||
{kKeyword, "conj", &Program::RpnConj, "complex conjugate"},
|
||||
{kKeyword, "arg", &Program::RpnArg, "complex argument in radians"},
|
||||
{kKeyword, "c->r", &Program::RpnC2r, "transform a complex in 2 reals"},
|
||||
{kKeyword, "r->c", &Program::RpnR2c, "transform 2 reals in a complex"},
|
||||
{kKeyword, "p->r", &Program::RpnP2r, "cartesian to polar"},
|
||||
{kKeyword, "r->p", &Program::RpnR2p, "polar to cartesian"},
|
||||
{kKeyword, "re", {.prog = &Program::RpnReal}, "complex real part"},
|
||||
{kKeyword, "im", {.prog = &Program::RpnImag}, "complex imaginary part"},
|
||||
{kKeyword, "conj", {.prog = &Program::RpnConj}, "complex conjugate"},
|
||||
{kKeyword, "arg", {.prog = &Program::RpnArg}, "complex argument in radians"},
|
||||
{kKeyword, "c->r", {.prog = &Program::RpnC2r}, "transform a complex in 2 reals"},
|
||||
{kKeyword, "r->c", {.prog = &Program::RpnR2c}, "transform 2 reals in a complex"},
|
||||
{kKeyword, "p->r", {.prog = &Program::RpnP2r}, "cartesian to polar"},
|
||||
{kKeyword, "r->p", {.prog = &Program::RpnR2p}, "polar to cartesian"},
|
||||
|
||||
// MODE
|
||||
{kUndef, "", nullptr, "\nMODE"},
|
||||
{kKeyword, "std", &Program::RpnStd, "standard floating numbers representation. ex: std"},
|
||||
{kKeyword, "fix", &Program::RpnFix, "fixed point representation. ex: 6 fix"},
|
||||
{kKeyword, "sci", &Program::RpnSci, "scientific floating point representation. ex: 20 sci"},
|
||||
{kKeyword, "prec", &Program::RpnPrecision, "set float precision in bits. ex: 256 prec"},
|
||||
{kKeyword, "round", &Program::RpnRound,
|
||||
{kKeyword, "std", {.prog = &Program::RpnStd}, "standard floating numbers representation. ex: std"},
|
||||
{kKeyword, "fix", {.prog = &Program::RpnFix}, "fixed point representation. ex: 6 fix"},
|
||||
{kKeyword, "sci", {.prog = &Program::RpnSci}, "scientific floating point representation. ex: 20 sci"},
|
||||
{kKeyword, "prec", {.prog = &Program::RpnPrecision}, "set float precision in bits. ex: 256 prec"},
|
||||
{kKeyword, "round", {.prog = &Program::RpnRound},
|
||||
"set float rounding mode in \n\t\"nearest (even)\", \"toward zero\", \"toward "
|
||||
"+inf\", \"toward -inf\", \"away from zero\", \"faithful rounding\", \"nearest (away from zero)\""
|
||||
"\n\tex: \"nearest (even)\" round"},
|
||||
{kKeyword, "default", &Program::RpnDefault, "set float representation and precision to default"},
|
||||
{kKeyword, "type", &Program::RpnType, "show type of stack first entry"},
|
||||
{kKeyword, "hex", &Program::RpnHex, "hexadecimal representation, applies on stack level 0 only"},
|
||||
{kKeyword, "dec", &Program::RpnDec, "decimal representation, applies on stack level 0 only"},
|
||||
{kKeyword, "bin", &Program::RpnBin, "binary representation, applies on stack level 0 only"},
|
||||
{kKeyword, "base", &Program::RpnBase, "arbitrary base representation, applies on stack level 0 only"},
|
||||
{kKeyword, "default", {.prog = &Program::RpnDefault}, "set float representation and precision to default"},
|
||||
{kKeyword, "type", {.prog = &Program::RpnType}, "show type of stack first entry"},
|
||||
{kKeyword, "hex", {.prog = &Program::RpnHex}, "hexadecimal representation, applies on stack level 0 only"},
|
||||
{kKeyword, "dec", {.prog = &Program::RpnDec}, "decimal representation, applies on stack level 0 only"},
|
||||
{kKeyword, "bin", {.prog = &Program::RpnBin}, "binary representation, applies on stack level 0 only"},
|
||||
{kKeyword, "base", {.prog = &Program::RpnBase}, "arbitrary base representation, applies on stack level 0 only"},
|
||||
|
||||
// TESTS
|
||||
{kUndef, "", nullptr, "\nTEST"},
|
||||
{kKeyword, ">", &Program::RpnSup, "binary operator >"},
|
||||
{kKeyword, ">=", &Program::RpnSupEq, "binary operator >="},
|
||||
{kKeyword, "<", &Program::RpnInf, "binary operator <"},
|
||||
{kKeyword, "<=", &Program::RpnInfEq, "binary operator <="},
|
||||
{kKeyword, "!=", &Program::RpnDiff, "binary operator != (different)"},
|
||||
{kKeyword, "==", &Program::RpnEq, "binary operator == (equal)"},
|
||||
{kKeyword, "and", &Program::RpnTestAnd, "boolean operator and"},
|
||||
{kKeyword, "or", &Program::RpnTestOr, "boolean operator or"},
|
||||
{kKeyword, "xor", &Program::RpnTestXor, "boolean operator xor"},
|
||||
{kKeyword, "not", &Program::RpnTestNot, "boolean operator not"},
|
||||
{kKeyword, "same", &Program::RpnSame, "boolean operator same (equal)"},
|
||||
{kKeyword, ">", {.prog = &Program::RpnSup}, "binary operator >"},
|
||||
{kKeyword, ">=", {.prog = &Program::RpnSupEq}, "binary operator >="},
|
||||
{kKeyword, "<", {.prog = &Program::RpnInf}, "binary operator <"},
|
||||
{kKeyword, "<=", {.prog = &Program::RpnInfEq}, "binary operator <="},
|
||||
{kKeyword, "!=", {.prog = &Program::RpnDiff}, "binary operator != (different)"},
|
||||
{kKeyword, "==", {.prog = &Program::RpnEq}, "binary operator == (equal)"},
|
||||
{kKeyword, "and", {.prog = &Program::RpnTestAnd}, "boolean operator and"},
|
||||
{kKeyword, "or", {.prog = &Program::RpnTestOr}, "boolean operator or"},
|
||||
{kKeyword, "xor", {.prog = &Program::RpnTestXor}, "boolean operator xor"},
|
||||
{kKeyword, "not", {.prog = &Program::RpnTestNot}, "boolean operator not"},
|
||||
{kKeyword, "same", {.prog = &Program::RpnSame}, "boolean operator same (equal)"},
|
||||
|
||||
// STACK
|
||||
{kUndef, "", nullptr, "\nSTACK"},
|
||||
{kKeyword, "swap", &Program::RpnSwap, "swap 2 first stack entries"},
|
||||
{kKeyword, "drop", &Program::RpnDrop, "drop first stack entry"},
|
||||
{kKeyword, "drop2", &Program::RpnDrop2, "drop 2 first stack entries"},
|
||||
{kKeyword, "dropn", &Program::RpnDropn, "drop n first stack entries"},
|
||||
{kKeyword, "del", &Program::RpnErase, "drop all stack entries"},
|
||||
{kKeyword, "erase", &Program::RpnErase, ""},
|
||||
{kKeyword, "rot", &Program::RpnRot, "rotate 3 first stack entries"},
|
||||
{kKeyword, "dup", &Program::RpnDup, "duplicate first stack entry"},
|
||||
{kKeyword, "dup2", &Program::RpnDup2, "duplicate 2 first stack entries"},
|
||||
{kKeyword, "dupn", &Program::RpnDupn, "duplicate n first stack entries"},
|
||||
{kKeyword, "pick", &Program::RpnPick, "push a copy of the given stack level onto the stack"},
|
||||
{kKeyword, "depth", &Program::RpnDepth, "give stack depth"},
|
||||
{kKeyword, "roll", &Program::RpnRoll, "move a stack entry to the top of the stack"},
|
||||
{kKeyword, "rolld", &Program::RpnRolld, "move the element on top of the stack to a higher stack position"},
|
||||
{kKeyword, "over", &Program::RpnOver, "push a copy of the element in stack level 2 onto the stack"},
|
||||
{kKeyword, "swap", {.prog = &Program::RpnSwap}, "swap 2 first stack entries"},
|
||||
{kKeyword, "drop", {.prog = &Program::RpnDrop}, "drop first stack entry"},
|
||||
{kKeyword, "drop2", {.prog = &Program::RpnDrop2}, "drop 2 first stack entries"},
|
||||
{kKeyword, "dropn", {.prog = &Program::RpnDropn}, "drop n first stack entries"},
|
||||
{kKeyword, "del", {.prog = &Program::RpnErase}, "drop all stack entries"},
|
||||
{kKeyword, "erase", {.prog = &Program::RpnErase}, ""},
|
||||
{kKeyword, "rot", {.prog = &Program::RpnRot}, "rotate 3 first stack entries"},
|
||||
{kKeyword, "dup", {.prog = &Program::RpnDup}, "duplicate first stack entry"},
|
||||
{kKeyword, "dup2", {.prog = &Program::RpnDup2}, "duplicate 2 first stack entries"},
|
||||
{kKeyword, "dupn", {.prog = &Program::RpnDupn}, "duplicate n first stack entries"},
|
||||
{kKeyword, "pick", {.prog = &Program::RpnPick}, "push a copy of the given stack level onto the stack"},
|
||||
{kKeyword, "depth", {.prog = &Program::RpnDepth}, "give stack depth"},
|
||||
{kKeyword, "roll", {.prog = &Program::RpnRoll}, "move a stack entry to the top of the stack"},
|
||||
{kKeyword, "rolld", {.prog = &Program::RpnRolld}, "move the element on top of the stack to a higher stack position"},
|
||||
{kKeyword, "over", {.prog = &Program::RpnOver}, "push a copy of the element in stack level 2 onto the stack"},
|
||||
|
||||
// STRING
|
||||
{kUndef, "", nullptr, "\nSTRING"},
|
||||
{kKeyword, "->str", &Program::RpnInstr, "convert an object into a string"},
|
||||
{kKeyword, "str->", &Program::RpnStrout, "convert a string into an object"},
|
||||
{kKeyword, "chr", &Program::RpnChr, "convert ASCII character code in stack level 1 into a string"},
|
||||
{kKeyword, "num", &Program::RpnNum,
|
||||
"return ASCII code of the first character of the string in stack level 1 as a real number"},
|
||||
{kKeyword, "size", &Program::RpnStrsize, "return the length of the string"},
|
||||
{kKeyword, "pos", &Program::RpnStrpos, "seach for the string in level 1 within the string in level 2"},
|
||||
{kKeyword, "sub", &Program::RpnStrsub, "return a substring of the string in level 3"},
|
||||
{kKeyword, "->str", {.prog = &Program::RpnInstr}, "convert an object into a string"},
|
||||
{kKeyword, "str->", {.prog = &Program::RpnStrout}, "convert a string into an object"},
|
||||
{kKeyword, "chr", {.prog = &Program::RpnChr}, "convert ASCII character code in stack level 1 into a string"},
|
||||
{kKeyword, "num", {.prog = &Program::RpnNum}, "return ASCII code of the first character of the string in stack level 1 as a real number"},
|
||||
{kKeyword, "size", {.prog = &Program::RpnStrsize}, "return the length of the string"},
|
||||
{kKeyword, "pos", {.prog = &Program::RpnStrpos}, "seach for the string in level 1 within the string in level 2"},
|
||||
{kKeyword, "sub", {.prog = &Program::RpnStrsub}, "return a substring of the string in level 3"},
|
||||
|
||||
// BRANCH
|
||||
{kUndef, "", nullptr, "\nBRANCH"},
|
||||
{kBranch, "if", (program_fn_t)&Program::RpnIf,
|
||||
"if <test-instruction> then <true-instructions> else <false-instructions> "
|
||||
"end"},
|
||||
{kBranch, "then", (program_fn_t)&Program::RpnThen, "used with if"},
|
||||
{kBranch, "else", (program_fn_t)&Program::RpnElse, "used with if"},
|
||||
{kBranch, "end", (program_fn_t)&Program::RpnEnd, "used with various branch instructions"},
|
||||
{kBranch, "start", (program_fn_t)&Program::RpnStart, "<start> <end> start <instructions> next|<step> step"},
|
||||
{kBranch, "for", (program_fn_t)&Program::RpnFor, "<start> <end> for <variable> <instructions> next|<step> step"},
|
||||
{kBranch, "next", (program_fn_t)&Program::RpnNext, "used with start and for"},
|
||||
{kBranch, "step", (program_fn_t)&Program::RpnStep, "used with start and for"},
|
||||
{kKeyword, "ift", &Program::RpnIft, "similar to if-then-end, <test-instruction> <true-instruction> ift"},
|
||||
{kKeyword, "ifte", &Program::RpnIfte,
|
||||
"similar to if-then-else-end, <test-instruction> <true-instruction> "
|
||||
"<false-instruction> ifte"},
|
||||
{kBranch, "do", (program_fn_t)&Program::RpnDo, "do <instructions> until <condition> end"},
|
||||
{kBranch, "until", (program_fn_t)&Program::RpnUntil, "used with do"},
|
||||
{kBranch, "while", (program_fn_t)&Program::RpnWhile, "while <test-instruction> repeat <loop-instructions> end"},
|
||||
{kBranch, "repeat", (program_fn_t)&Program::RpnRepeat, "used with while"},
|
||||
{kBranch, "if", {.branch = &Program::RpnIf}, "if <test-instruction> then <true-instructions> else <false-instructions> end"},
|
||||
{kBranch, "then", {.branch = &Program::RpnThen}, "used with if"},
|
||||
{kBranch, "else", {.branch = &Program::RpnElse}, "used with if"},
|
||||
{kBranch, "end", {.branch = &Program::RpnEnd}, "used with various branch instructions"},
|
||||
{kBranch, "start", {.branch = &Program::RpnStart}, "<start> <end> start <instructions> next|<step> step"},
|
||||
{kBranch, "for", {.branch = &Program::RpnFor}, "<start> <end> for <variable> <instructions> next|<step> step"},
|
||||
{kBranch, "next", {.branch = &Program::RpnNext}, "used with start and for"},
|
||||
{kBranch, "step", {.branch = &Program::RpnStep}, "used with start and for"},
|
||||
{kKeyword, "ift", {.prog = &Program::RpnIft}, "similar to if-then-end, <test-instruction> <true-instruction> ift"},
|
||||
{kKeyword, "ifte", {.prog = &Program::RpnIfte}, "similar to if-then-else-end, <test-instruction> <true-instruction> <false-instruction> ifte"},
|
||||
{kBranch, "do", {.branch = &Program::RpnDo}, "do <instructions> until <condition> end"},
|
||||
{kBranch, "until", {.branch = &Program::RpnUntil}, "used with do"},
|
||||
{kBranch, "while", {.branch = &Program::RpnWhile}, "while <test-instruction> repeat <loop-instructions> end"},
|
||||
{kBranch, "repeat", {.branch = &Program::RpnRepeat}, "used with while"},
|
||||
|
||||
// STORE
|
||||
{kUndef, "", nullptr, "\nSTORE"},
|
||||
{kKeyword, "sto", &Program::RpnSto, "store a variable. ex: 1 'name' sto"},
|
||||
{kKeyword, "rcl", &Program::RpnRcl, "recall a variable. ex: 'name' rcl"},
|
||||
{kKeyword, "purge", &Program::RpnPurge, "delete a variable. ex: 'name' purge"},
|
||||
{kKeyword, "vars", &Program::RpnVars, "list all variables"},
|
||||
{kKeyword, "clusr", &Program::RpnClusr, "erase all variables"},
|
||||
{kKeyword, "edit", &Program::RpnEdit, "edit a variable content"},
|
||||
{kKeyword, "sto+", &Program::RpnStoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"},
|
||||
{kKeyword, "sto-", &Program::RpnStosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"},
|
||||
{kKeyword, "sto*", &Program::RpnStomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"},
|
||||
{kKeyword, "sto/", &Program::RpnStodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"},
|
||||
{kKeyword, "sneg", &Program::RpnStoneg, "negate a variable. ex: 'name' sneg"},
|
||||
{kKeyword, "sinv", &Program::RpnStoinv, "inverse a variable. ex: 1 'name' sinv"},
|
||||
{kKeyword, "sto", {.prog = &Program::RpnSto}, "store a variable. ex: 1 'name' sto"},
|
||||
{kKeyword, "rcl", {.prog = &Program::RpnRcl}, "recall a variable. ex: 'name' rcl"},
|
||||
{kKeyword, "purge", {.prog = &Program::RpnPurge}, "delete a variable. ex: 'name' purge"},
|
||||
{kKeyword, "vars", {.prog = &Program::RpnVars}, "list all variables"},
|
||||
{kKeyword, "clusr", {.prog = &Program::RpnClusr}, "erase all variables"},
|
||||
{kKeyword, "edit", {.prog = &Program::RpnEdit}, "edit a variable content"},
|
||||
{kKeyword, "sto+", {.prog = &Program::RpnStoadd}, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"},
|
||||
{kKeyword, "sto-", {.prog = &Program::RpnStosub}, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"},
|
||||
{kKeyword, "sto*", {.prog = &Program::RpnStomul}, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"},
|
||||
{kKeyword, "sto/", {.prog = &Program::RpnStodiv}, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"},
|
||||
{kKeyword, "sneg", {.prog = &Program::RpnStoneg}, "negate a variable. ex: 'name' sneg"},
|
||||
{kKeyword, "sinv", {.prog = &Program::RpnStoinv}, "inverse a variable. ex: 1 'name' sinv"},
|
||||
|
||||
// PROGRAM
|
||||
{kUndef, "", nullptr, "\nPROGRAM"},
|
||||
{kKeyword, "eval", &Program::RpnEval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"},
|
||||
{kBranch, "->", (program_fn_t)&Program::RpnInprog,
|
||||
"load program local variables. ex: << -> n m << 0 n m for i i + next >> "
|
||||
">>"},
|
||||
{kKeyword, "eval", {.prog = &Program::RpnEval}, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"},
|
||||
{kBranch, "->", {.branch = &Program::RpnInprog}, "load program local variables. ex: << -> n m << 0 n m for i i + next >> >>"},
|
||||
|
||||
// TRIG ON REALS AND COMPLEXES
|
||||
{kUndef, "", nullptr, "\nTRIG ON REALS AND COMPLEXES"},
|
||||
{kKeyword, "pi", &Program::RpnPi, "pi constant"},
|
||||
{kKeyword, "sin", &Program::RpnSin, "sinus"},
|
||||
{kKeyword, "asin", &Program::RpnAsin, "arg sinus"},
|
||||
{kKeyword, "cos", &Program::RpnCos, "cosinus"},
|
||||
{kKeyword, "acos", &Program::RpnAcos, "arg cosinus"},
|
||||
{kKeyword, "tan", &Program::RpnTan, "tangent"},
|
||||
{kKeyword, "atan", &Program::RpnAtan, "arg tangent"},
|
||||
{kKeyword, "d->r", &Program::RpnD2r, "convert degrees to radians"},
|
||||
{kKeyword, "r->d", &Program::RpnR2d, "convert radians to degrees"},
|
||||
{kKeyword, "pi", {.prog = &Program::RpnPi}, "pi constant"},
|
||||
{kKeyword, "sin", {.prog = &Program::RpnSin}, "sinus"},
|
||||
{kKeyword, "asin", {.prog = &Program::RpnAsin}, "arg sinus"},
|
||||
{kKeyword, "cos", {.prog = &Program::RpnCos}, "cosinus"},
|
||||
{kKeyword, "acos", {.prog = &Program::RpnAcos}, "arg cosinus"},
|
||||
{kKeyword, "tan", {.prog = &Program::RpnTan}, "tangent"},
|
||||
{kKeyword, "atan", {.prog = &Program::RpnAtan}, "arg tangent"},
|
||||
{kKeyword, "d->r", {.prog = &Program::RpnD2r}, "convert degrees to radians"},
|
||||
{kKeyword, "r->d", {.prog = &Program::RpnR2d}, "convert radians to degrees"},
|
||||
|
||||
// LOGS ON REALS AND COMPLEXES
|
||||
{kUndef, "", nullptr, "\nLOGS ON REALS AND COMPLEXES"},
|
||||
{kKeyword, "e", &Program::RpnE, "Euler constant"},
|
||||
{kKeyword, "ln", &Program::RpnLn, "logarithm base e"},
|
||||
{kKeyword, "log", &Program::RpnLn, ""},
|
||||
{kKeyword, "lnp1", &Program::RpnLnp1, "ln(1+x) which is useful when x is close to 0"},
|
||||
{kKeyword, "exp", &Program::RpnExp, "exponential"},
|
||||
{kKeyword, "expm", &Program::RpnExpm, "exp(x)-1 which is useful when x is close to 0"},
|
||||
{kKeyword, "log10", &Program::RpnLog10, "logarithm base 10"},
|
||||
{kKeyword, "alog10", &Program::RpnAlog10, "exponential base 10"},
|
||||
{kKeyword, "exp10", &Program::RpnAlog10, ""},
|
||||
{kKeyword, "log2", &Program::RpnLog2, "logarithm base 2"},
|
||||
{kKeyword, "alog2", &Program::RpnAlog2, "exponential base 2"},
|
||||
{kKeyword, "exp2", &Program::RpnAlog2, ""},
|
||||
{kKeyword, "sinh", &Program::RpnSinh, "hyperbolic sine"},
|
||||
{kKeyword, "asinh", &Program::RpnAsinh, "inverse hyperbolic sine"},
|
||||
{kKeyword, "cosh", &Program::RpnCosh, "hyperbolic cosine"},
|
||||
{kKeyword, "acosh", &Program::RpnAcosh, "inverse hyperbolic cosine"},
|
||||
{kKeyword, "tanh", &Program::RpnTanh, "hyperbolic tangent"},
|
||||
{kKeyword, "atanh", &Program::RpnAtanh, "inverse hyperbolic tangent"},
|
||||
{kKeyword, "e", {.prog = &Program::RpnE}, "Euler constant"},
|
||||
{kKeyword, "ln", {.prog = &Program::RpnLn}, "logarithm base e"},
|
||||
{kKeyword, "log", {.prog = &Program::RpnLn}, ""},
|
||||
{kKeyword, "lnp1", {.prog = &Program::RpnLnp1}, "ln(1+x) which is useful when x is close to 0"},
|
||||
{kKeyword, "exp", {.prog = &Program::RpnExp}, "exponential"},
|
||||
{kKeyword, "expm", {.prog = &Program::RpnExpm}, "exp(x)-1 which is useful when x is close to 0"},
|
||||
{kKeyword, "log10", {.prog = &Program::RpnLog10}, "logarithm base 10"},
|
||||
{kKeyword, "alog10", {.prog = &Program::RpnAlog10}, "exponential base 10"},
|
||||
{kKeyword, "exp10", {.prog = &Program::RpnAlog10}, ""},
|
||||
{kKeyword, "log2", {.prog = &Program::RpnLog2}, "logarithm base 2"},
|
||||
{kKeyword, "alog2", {.prog = &Program::RpnAlog2}, "exponential base 2"},
|
||||
{kKeyword, "exp2", {.prog = &Program::RpnAlog2}, ""},
|
||||
{kKeyword, "sinh", {.prog = &Program::RpnSinh}, "hyperbolic sine"},
|
||||
{kKeyword, "asinh", {.prog = &Program::RpnAsinh}, "inverse hyperbolic sine"},
|
||||
{kKeyword, "cosh", {.prog = &Program::RpnCosh}, "hyperbolic cosine"},
|
||||
{kKeyword, "acosh", {.prog = &Program::RpnAcosh}, "inverse hyperbolic cosine"},
|
||||
{kKeyword, "tanh", {.prog = &Program::RpnTanh}, "hyperbolic tangent"},
|
||||
{kKeyword, "atanh", {.prog = &Program::RpnAtanh}, "inverse hyperbolic tangent"},
|
||||
|
||||
// TIME AND DATE
|
||||
{kUndef, "", nullptr, "\nTIME AND DATE"},
|
||||
{kKeyword, "time", &Program::RpnTime, "local time in ISO 8601 format"},
|
||||
{kKeyword, "date", &Program::RpnDate, "local date in ISO 8601 format"},
|
||||
{kKeyword, "ticks", &Program::RpnTicks, "local date and time in µs"}};
|
||||
#pragma GCC diagnostic pop
|
||||
{kKeyword, "time", {.prog = &Program::RpnTime}, "local time in ISO 8601 format"},
|
||||
{kKeyword, "date", {.prog = &Program::RpnDate}, "local date in ISO 8601 format"},
|
||||
{kKeyword, "ticks", {.prog = &Program::RpnTicks}, "local date and time in µs"}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
/// autocompletion vector for linenoise autocompletion
|
||||
vector<string>& Program::GetAutocompletionWords() {
|
||||
|
@ -589,13 +582,10 @@ RetValue Program::Parse(const string& entry) {
|
|||
}
|
||||
} break;
|
||||
case kKeyword:
|
||||
push_back(new Keyword(element.fn, element.value));
|
||||
push_back(new Keyword(element.fn.prog, element.value));
|
||||
break;
|
||||
case kBranch:
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type" // allow casting kBranch callbacks
|
||||
push_back(new Branch((branch_fn_t)element.fn, element.value));
|
||||
#pragma GCC diagnostic pop
|
||||
push_back(new Branch(element.fn.branch, element.value));
|
||||
break;
|
||||
default:
|
||||
ShowError(kUnknownError, "error creating program from entry");
|
||||
|
|
|
@ -84,7 +84,7 @@ class Program : public deque<Object*>, public Lexer, public Object {
|
|||
struct keyword_t {
|
||||
ObjectType type;
|
||||
string name;
|
||||
program_fn_t fn;
|
||||
object_cb_t fn;
|
||||
string comment;
|
||||
};
|
||||
static vector<keyword_t> keywords_;
|
||||
|
@ -153,7 +153,7 @@ class Program : public deque<Object*>, public Lexer, public Object {
|
|||
// program
|
||||
bool FindVariable(string& variable, Object*& obj);
|
||||
void RpnEval(void);
|
||||
int RpnInprog(Branch& inprog_obj);
|
||||
size_t RpnInprog(Branch& inprog_obj);
|
||||
|
||||
// real
|
||||
void RpnPlus();
|
||||
|
|
|
@ -75,14 +75,14 @@ void Program::RpnEval(void) {
|
|||
|
||||
/// @brief -> keyword (Branch) implementation
|
||||
///
|
||||
int Program::RpnInprog(Branch& inprog_obj) {
|
||||
size_t Program::RpnInprog(Branch& inprog_obj) {
|
||||
string context("->"); // for showing errors
|
||||
size_t count_symbols = 0;
|
||||
bool prog_found = false;
|
||||
|
||||
if (inprog_obj.arg1 == kStepOut) {
|
||||
ERROR_CONTEXT(kUnknownError);
|
||||
return -1;
|
||||
return kStepOut;
|
||||
}
|
||||
|
||||
// syntax must be
|
||||
|
@ -101,7 +101,7 @@ int Program::RpnInprog(Branch& inprog_obj) {
|
|||
// found something other than symbol
|
||||
ERROR_CONTEXT(kBadOperandType);
|
||||
ShowError(err_, context);
|
||||
return -1;
|
||||
return kStepOut;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,21 +109,21 @@ int Program::RpnInprog(Branch& inprog_obj) {
|
|||
if (count_symbols == 0) {
|
||||
ERROR_CONTEXT(kSyntaxError);
|
||||
ShowError(err_, context);
|
||||
return -1;
|
||||
return kStepOut;
|
||||
}
|
||||
|
||||
// <program> is missing
|
||||
if (!prog_found) {
|
||||
ERROR_CONTEXT(kSyntaxError);
|
||||
ShowError(err_, context);
|
||||
return -1;
|
||||
return kStepOut;
|
||||
}
|
||||
|
||||
// check symbols Number vs stack_ size
|
||||
if (stack_.size() < count_symbols) {
|
||||
ERROR_CONTEXT(kMissingOperand);
|
||||
ShowError(err_, context);
|
||||
return -1;
|
||||
return kStepOut;
|
||||
}
|
||||
|
||||
// load variables
|
||||
|
|
Loading…
Add table
Reference in a new issue