0

Hello I am trying to implement a parser for mathematical expression using antlr4, using c++ as the target.

I used the example calculator grammar as a starting poing, and I am currently parsing and eventually evaluating correctly simple expressions. Now I started addressing using math functions such as sqrt, log, sin, etc... Grammar is mine, but I would like to avoid a sequence of if/elseif in the visitor implementation.

the generated code for the context is:

class  OneArgFunctionNameContext : public antlr4::ParserRuleContext {
  public:
    OneArgFunctionNameContext(antlr4::ParserRuleContext *parent, size_t invokingState);
    virtual size_t getRuleIndex() const override;
    antlr4::tree::TerminalNode *SQRT();
    antlr4::tree::TerminalNode *EXP();
    antlr4::tree::TerminalNode *LOG();
    antlr4::tree::TerminalNode *LN();
    antlr4::tree::TerminalNode *SIN();
    antlr4::tree::TerminalNode *COS();
    antlr4::tree::TerminalNode *TAN();
    antlr4::tree::TerminalNode *ACOS();
    antlr4::tree::TerminalNode *ASIN();
    antlr4::tree::TerminalNode *ATAN();
    antlr4::tree::TerminalNode *ABS();


    virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;

  };

then, given the examples I had the chance to see and understand, I could to the following:

{
    if (ctx->SQRT())
    {
        ... // perform sqrt
    }
    else if (ctx->EXP())
    {
        ... // perform exp
    }
    else if (...)
    {
        ...
    }
    ...

}

what I would like to have is a switch statement rather than a sequence of if/elseif, but I cant find how to identify which type is the child terminal node. Something like the following:

switch (ctx->{SOMETHING})
{
   case SQRT:
   ...
   break;
   case SQRT:
   ...
   break;
   ...
}

Can it be done this way? I have this feeling that the answer (wether positive or negative) should be pretty obvious, but I cant reach out to grasp it.

Thanks in Advance

BaroneAshura
  • 191
  • 1
  • 1
  • 14
  • Not possible that simply, it would need to translate a string into a piece of code, which is possible with dynamic language, not compiled ones. May be possible with template black magic. – gaFF Jun 11 '19 at 10:07
  • @gaFF I see your point. The subject of the question actually arose, because the generated code contains an unnamed `enum` listing all the available terminal nodes in the grammar. Unfortunately I cannot find any way to get a handle of the enum value from the rule context (being an unnamed `enum` eventually makes things even more non-accessible). – BaroneAshura Jun 12 '19 at 07:54
  • Name the `enum` ? It would be easy to `switch` on its value, but I guess the `enum` is in a third-party library. It's bad, but you could re-implement it ? I asked a [quite similar question](https://stackoverflow.com/questions/43211408/template-class-with-method-depending-on-template-parameter) some time ago, and @VittorioRomeo made a great answer using templates, but you could directly see [his blog](https://vittorioromeo.info/index/blog/checking_expression_validity_in_place.html). – gaFF Jun 12 '19 at 08:03
  • @gaFF the `enum` is generated as unnamed by the antlr4 code generator for cpp target. I would have to choose between reprocess generated code to name the `enum`, or modify the antlr4 code generator to make it a named `enum`, or live with it. Due to tight time schedule, as of now I am leaving it as it is. the goal of the question was also to try to get some insight on the rationale for using an unnamed `enum` there. – BaroneAshura Jun 12 '19 at 08:17

0 Answers0