* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef HC_GEN_AST_H
#define HC_GEN_AST_H
#include <list>
#include <memory>
#include <string>
#include <vector>
#include "token.h"
#include "types.h"
namespace OHOS {
namespace Hardware {
enum ObjectType {
PARSEROP_UINT8 = 0x01,
PARSEROP_UINT16,
PARSEROP_UINT32,
PARSEROP_UINT64,
PARSEROP_STRING,
PARSEROP_CONFNODE,
PARSEROP_CONFTERM,
PARSEROP_ARRAY,
PARSEROP_NODEREF,
PARSEROP_DELETE,
};
enum NodeRefType {
NODE_NOREF = 0,
NODE_COPY,
NODE_REF,
NODE_DELETE,
NODE_TEMPLATE,
NODE_INHERIT,
};
class AstObject {
public:
friend class Ast;
AstObject(const std::string &name, uint32_t type, uint64_t integerValue, const std::string &strValue,
uint32_t lineno, const std::shared_ptr<std::string> &src);
AstObject(const std::string &name, uint32_t type, uint64_t integerValue);
AstObject(const std::string &name, uint32_t type, const std::string &strValue);
AstObject(const std::string &name, uint32_t type, uint64_t integerValue, const Token &bindToken);
AstObject(const std::string &name, uint32_t type, const std::string &strValue, const Token &bindToken);
AstObject(const AstObject &obj);
virtual ~AstObject();
AstObject &operator=(const AstObject &obj);
virtual bool AddChild(const std::shared_ptr<AstObject> &childObj);
virtual bool AddPeer(std::shared_ptr<AstObject> peerObject);
friend std::ostream &operator<<(std::ostream &stream, const AstObject &t);
virtual bool Merge(std::shared_ptr<AstObject> &srcObj);
virtual bool Copy(std::shared_ptr<AstObject> src, bool overwrite);
virtual bool Move(std::shared_ptr<AstObject> src);
void Remove();
void Separate();
std::shared_ptr<AstObject> Lookup(const std::string &name, uint32_t type = 0) const;
bool IsElders(const std::shared_ptr<AstObject> &child) const;
bool IsNumber() const;
bool IsNode() const;
bool IsTerm() const;
bool IsArray() const;
virtual std::string SourceInfo();
void SetParent(AstObject *parent);
void SetSize(uint32_t size);
void SetSubSize(uint32_t size);
void SetHash(uint32_t hash);
uint32_t GetSize() const;
uint32_t GetSubSize() const;
uint32_t GetHash() const;
std::shared_ptr<AstObject> Child();
std::shared_ptr<AstObject> Next();
virtual const std::string &Name();
const std::string &StringValue() const;
uint64_t IntegerValue() const;
virtual uint32_t Type();
uint8_t OpCode() const;
void SetOpCode(uint8_t opcode);
virtual bool HasDuplicateChild();
std::shared_ptr<AstObject> Parent() const;
protected:
uint32_t type_;
std::string name_;
AstObject *parent_;
std::shared_ptr<AstObject> next_;
std::shared_ptr<AstObject> child_;
uint32_t lineno_;
std::shared_ptr<std::string> src_;
uint8_t opCode_;
uint32_t size_;
uint32_t subSize_;
uint32_t hash_;
uint64_t integerValue_;
std::string stringValue_;
private:
static uint32_t FitIntegerValueType(uint64_t value);
};
class ConfigNode : public AstObject {
public:
ConfigNode(const ConfigNode &node);
ConfigNode(const std::string &name, uint32_t nodeType, const std::string &refName);
ConfigNode(Token &name, uint32_t nodeType, const std::string &refName);
~ConfigNode() override = default;
ConfigNode &operator=(const ConfigNode &node);
friend std::ostream &operator<<(std::ostream &stream, const ConfigNode &t);
bool Merge(std::shared_ptr<AstObject> &srcObj) override;
static ConfigNode *CastFrom(const std::shared_ptr<AstObject> &astObject);
uint32_t GetNodeType() const;
const std::string &GetRefPath() const;
void SetNodeType(uint32_t nodeType);
void SetRefPath(const std::string &ref);
static const std::string &NodeTypeToStr(uint32_t type);
bool HasDuplicateChild() override;
bool InheritExpand(const std::shared_ptr<AstObject> &refObj);
bool RefExpand(const std::shared_ptr<AstObject> &refObj);
bool Copy(std::shared_ptr<AstObject> src, bool overwrite) override;
bool Move(std::shared_ptr<AstObject> src) override;
bool Compare(ConfigNode &other) const;
bool IsBaseNode();
uint32_t InheritIndex() const;
uint32_t InheritCount() const;
uint32_t TemplateSignNum() const;
void SetTemplateSignNum(uint32_t sigNum);
const std::list<AstObject *> &SubClasses() const;
private:
bool NodeRefExpand(const std::shared_ptr<AstObject> &ref);
bool NodeCopyExpand(const std::shared_ptr<AstObject> &ref);
std::string refNodePath_;
uint32_t nodeType_;
uint32_t inheritIndex_;
uint32_t inheritCount_;
uint32_t templateSignNum_;
std::list<AstObject *> subClasses_;
};
class ConfigTerm : public AstObject {
public:
ConfigTerm(const ConfigTerm &term);
ConfigTerm(const std::string &name, const std::shared_ptr<AstObject> &value);
ConfigTerm(Token &name, const std::shared_ptr<AstObject> &value);
~ConfigTerm() override = default;
ConfigTerm &operator=(const ConfigTerm &term);
static ConfigTerm *CastFrom(const std::shared_ptr<AstObject> &astObject);
bool Merge(std::shared_ptr<AstObject> &srcObj) override;
friend std::ostream &operator<<(std::ostream &stream, const ConfigTerm &t);
bool RefExpand(const std::shared_ptr<AstObject> refObj);
bool Copy(std::shared_ptr<AstObject> src, bool overwrite) override;
bool Move(std::shared_ptr<AstObject> src) override;
std::weak_ptr<AstObject> RefNode();
uint32_t SigNum() const;
void SetSigNum(uint32_t sigNum);
private:
std::weak_ptr<AstObject> refNode_;
uint32_t signNum_;
};
class ConfigArray : public AstObject {
public:
ConfigArray();
ConfigArray(const ConfigArray &array);
explicit ConfigArray(const Token &bindToken);
~ConfigArray() override = default;
ConfigArray &operator=(const ConfigArray &array);
static ConfigArray *CastFrom(const std::shared_ptr<AstObject> &astObject);
bool AddChild(const std::shared_ptr<AstObject> &childObj) override;
bool Merge(std::shared_ptr<AstObject> &srcObj) override;
bool Copy(std::shared_ptr<AstObject> src, bool overwrite) override;
uint16_t ArraySize() const;
uint16_t ArrayType() const;
private:
uint32_t arrayType_;
uint32_t arraySize_;
};
class AstObjectFactory {
public:
static std::shared_ptr<AstObject> Build(std::shared_ptr<AstObject> object);
};
class Ast {
public:
explicit Ast(std::shared_ptr<AstObject> astRoot) : astRoot_(std::move(astRoot)), redefineChecked_(false) {}
~Ast() = default;
std::shared_ptr<AstObject> GetAstRoot();
bool Merge(const std::list<std::shared_ptr<Ast>> &astList);
bool Expand();
std::shared_ptr<AstObject> Lookup(const std::shared_ptr<AstObject> &startObj, const std::string &path);
template <typename T>
static bool WalkForward(const std::shared_ptr<AstObject> &startObject, T callback)
{
std::shared_ptr<AstObject> forwardWalkObj = startObject;
int32_t walkDepth = 0;
bool preVisited = false;
while (forwardWalkObj != nullptr) {
if (!preVisited) {
int32_t ret = static_cast<int32_t>(callback(forwardWalkObj, walkDepth));
if (ret && ret != EASTWALKBREAK) {
return false;
} else if (ret != EASTWALKBREAK && forwardWalkObj->child_ != nullptr) {
walkDepth++;
forwardWalkObj = forwardWalkObj->child_;
continue;
}
}
if (forwardWalkObj == startObject) {
break;
}
if (forwardWalkObj->next_ != nullptr) {
forwardWalkObj = forwardWalkObj->next_;
preVisited = false;
} else {
forwardWalkObj = forwardWalkObj->Parent();
preVisited = true;
walkDepth--;
}
}
return true;
}
template <typename T>
static bool WalkBackward(const std::shared_ptr<AstObject> &startObject, T callback)
{
std::shared_ptr<AstObject> backWalkObj = startObject;
std::shared_ptr<AstObject> next = nullptr;
std::shared_ptr<AstObject> parent = nullptr;
int32_t walkDepth = 0;
bool preVisited = false;
while (backWalkObj != nullptr) {
if (backWalkObj->child_ == nullptr || preVisited) {
next = backWalkObj->next_;
parent = backWalkObj->Parent();
if (callback(backWalkObj, walkDepth) != NOERR) {
return false;
}
} else {
if (backWalkObj->child_) {
walkDepth++;
backWalkObj = backWalkObj->child_;
continue;
}
}
if (backWalkObj == startObject) {
break;
}
if (next != nullptr) {
backWalkObj = next;
preVisited = false;
} else {
backWalkObj = parent;
preVisited = true;
walkDepth--;
}
}
return true;
}
template <typename T1, typename T2>
static bool WalkRound(const std::shared_ptr<AstObject> &startObject, T1 forwardCallback, T2 backwardCallback)
{
std::shared_ptr<AstObject> roundWalkObj = startObject;
int32_t walkDepth = 0;
bool preVisited = false;
while (roundWalkObj != nullptr) {
if (preVisited) {
if (backwardCallback(roundWalkObj, walkDepth) != NOERR) {
return false;
}
} else {
auto ret = forwardCallback(roundWalkObj, walkDepth);
if (ret && ret != EASTWALKBREAK) {
return false;
} else if (!ret && roundWalkObj->child_ != nullptr) {
walkDepth++;
roundWalkObj = roundWalkObj->child_;
continue;
}
}
if (roundWalkObj == startObject) {
break;
}
if (roundWalkObj->next_) {
roundWalkObj = roundWalkObj->next_;
preVisited = false;
} else {
roundWalkObj = roundWalkObj->Parent();
preVisited = true;
walkDepth--;
}
}
return true;
}
template <typename T>
bool WalkForward(T callback)
{
return WalkForward(astRoot_, callback);
}
template <typename T>
bool WalkBackward(T callback)
{
return WalkBackward(astRoot_, callback);
}
template <typename T1, typename T2>
bool WalkRound(T1 forwardCallback, T2 backwardCallback)
{
return WalkRound(astRoot_, forwardCallback, backwardCallback);
}
void Dump(const std::string &prefix = std::string());
private:
bool RedefineCheck();
bool NodeExpand();
bool NodeExpandRef();
bool NodeExpandDelete();
bool NodeExpandTermRef();
bool InheritExpand();
static std::list<std::string> SplitNodePath(const std::string &path, char separator);
std::shared_ptr<AstObject> astRoot_;
bool redefineChecked_;
};
std::ostream &operator<<(std::ostream &stream, const AstObject &t);
std::ostream &operator<<(std::ostream &stream, const ConfigNode &t);
std::ostream &operator<<(std::ostream &stream, const ConfigTerm &t);
}
}
#endif