简体   繁体   中英

Working on Parser with Binary and unary node?

I now this is bit weird title but I hope you will understand what I am asking about. Few months back I worked on Interpreter program in python and that was kind of great but now I want to implement same in C++ but doing so is offering great problems to me as C++ is type strict.

Lets start of from what I did in my python program. First I created a Lexer that would separate everything into tokens (key-value pair) and I wrote a Parser which will convert a arithmetic grammar into Operation Nodes as BinaryOpNode, UnaryOpNode, and NumberNode. ex- (-2+7)^3 will be converted into AST as a Binary Node having left node as another Binary Node, operator as POW(power) and right node as Number node of 3. Left Node of this node is Binary Node whose Left Node is Unary Node (MINUS and a Number Node 2), opeartor as PLUS and Right Node as Number Node 7.

I did this by identifying expression, term and factor. I have wrote a Lexer in C++ but having problem in Parser. Please help me to do same in C++.

What I have done so Far??

I tried something weird but kind of working. I created a class BinaryOpNode with two void* members for Right and left Node, A Enum member for operation between Rt and Lt node. Now two another boolean members for both nodes which would help to now what type of void* Lt and Rt are? Are they UnaryOpNode or BinaryOpNode(default). This will help me to typecast the Node into respective types.

However I am not satisfied with my results as they look like less optimized and also I can't keep track of NumberNode this way.

Please Help me. THANKS IN ADVANCE

What you are looking for is polymorphism. That is, code that a programmer writes, and does different things depending on the types of the things it operates on.

C++ supports a bewildering array of ways to do polymorphism.

The most supported kind is inheritance based virtual polymorphism. In this, you create a base class:

struct INode {
  virtual ~INode() {}
};

and add in common operations to it, making those common operations pure-virtual:

struct INode {
  virtual ~INode() {}
  virtual std::vector<INode*> GetChildren() const = 0;
};

This requires that you work with pointers instead of object instances.

In this system, if you know the type of an object, you can use dynamic_cast<RealType*>(iNodePointer) to get a pointer to the object as an instance of that type. It returns nullptr if the types don't match. This lets you access the methods you have in the descended type that aren't in the base interface.


A second kind of polymorphism is std::variant based. This is a closed set of types, which parsers often have.

using AnyNode = std::variant<Node::BinaryOp, Node::UnaryOp, Node::Number>;

here you use std::visit to operate on the concrete type instead of dynamic_cast , and your parse tree is value-based instead of pointer-based.

There is some pain when you want a node to have inside itself a vector of AnyNode .


A third way is std::function type-erasure style. Here you write your own polymorphic system that takes objects of arbitrary type and wraps their operations up in a value-semantics wrapper.


A forth option is CRTP static polymorphism. This isn't suitable to build a dynamic parse tree, but it can be used to help implement some of the above.


A fifth option is aspect oriented std::function operation bundles.


A sixth option is manual function table tweaking, basically reimplementing the C++ vtable solution manually as if you are in C, but in C++. This can permit you to have features similar to other OO-languages.


A seventh option is to write up a signals-slots system and send messages to your objects.


There are almost certainly more.

The easiest solution is probably to first learn about inheritance and virtual functions in C++ (the first option above). I personally would probably write a parse tree using std::variant at this point, but if you probably don't know enough C++ at this point to practically do that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM