p2sr / SourceAutoRecord

Speedrun plugin for Source engine games.
https://sar.portal2.sr/
MIT License
93 stars 29 forks source link

Rewrite `cond` parsing #140

Open mlugg opened 1 year ago

mlugg commented 1 year ago

The code for parsing cond conditions was written in a quite messy way, and it's gained a lot of functionality over time, leading to unintuitive and messy code. I'd like to rewrite it, with readability and simplicity in mind.

I also want the new parser to have near-symmetric handling of the LHS and RHS of comparisons. var:, ?, cvar:, and % will all work on both sides of an equation, meaning they can be dealt with at the tokenizer level; the only thing which will be handled differently is literals (e.g. map), which on the LHS are special names and on the RHS are equivalent to strings (i.e. foo is the same as %foo). This can be handled at the parser level with no problem, since the tokenizer doesn't need to identify the specific LHS options (map etc). The Condition struct should look like this:

struct CondTerm {
  enum {
    MAP,
    PREV_MAP,
    GAME,
    SVAR,
    CVAR,
    STRING,
    IDENT,
  } type;

  std::string child; // for SVAR, CVAR, STRING, IDENT

  std::string eval() {
    switch (this->type) {
    case MAP:
      return engine->GetCurrentMapName();
    case PREV_MAP:
      ...
    }
  }
};

struct Condition {
  enum {
    ORANGE,
    COOP,
    CM,
    SAME_MAP,
    WORKSHOP,
    MENU,
    EQUALS,
    NOT,
    AND,
    OR,
  } type;
  union {
    struct { CondTerm lhs; CondTerm rhs; } eq;
    struct { Condition *lhs; Condition *rhs; } binop;
    Condition unop_child;
  };
  bool eval() {
    switch (this->type) {
    case ORANGE:
      return engine->IsOrange();
    ...
    case EQUALS:
      return this->eq.lhs.eval() == this->eq.rhs.eval();
    ...
    }
  }
};
ThisAMJ commented 1 year ago

Don't forget # shorthand for cvar: in that list!