* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* This source file is part of the Cangjie project, licensed under Apache-2.0
* with Runtime Library Exception.
*
* See https://cangjie-lang.cn/pages/LICENSE for license information.
*/
* @file
*
* This file declares class ParserSyntaxImpl.
*/
#ifndef CANGJIE_PARSER_SYNTAX_IMPL_H
#define CANGJIE_PARSER_SYNTAX_IMPL_H
#include "cangjie/Parse/Parser.h"
using namespace Cangjie;
using namespace Cangjie::AST;
class ParserSyntaxImpl final {
public:
ParserSyntaxImpl(const std::string& input, DiagnosticEngine& diag, SourceManager& sm, const Position& pos,
bool attachComment);
ParserSyntaxImpl(const std::vector<Token>& inputTokens, DiagnosticEngine& diag, SourceManager& sm, bool attachComment);
~ParserSyntaxImpl();
Token lookahead{TokenKind::SENTINEL, "", Position(0, 1, 1), Position(0, 1, 1)};
Token lastToken{TokenKind::SENTINEL, "", Position(0, 1, 1), Position(0, 1, 1)};
const Token& Peek();
bool Seeing(TokenKind kind)
{
return Peek().kind == kind;
}
inline bool Seeing(TokenKind rangeLeft, TokenKind rangeRight)
{
return Peek().kind >= rangeLeft && Peek().kind <= rangeRight;
}
inline bool SeeingAny(const std::vector<TokenKind>& kinds)
{
return Utils::In(Peek().kind, kinds);
}
bool Seeing(const std::vector<TokenKind>& kinds, bool skipNewline = true);
bool SeeingMacroCall();
bool SeeingBuiltinAnnotation();
inline bool SeeingAnnotationLambdaExpr()
{
return Seeing({TokenKind::AT, TokenKind::IDENTIFIER, TokenKind::LCURL}) && SeeingBuiltinAnnotation();
}
bool SeeingModifier();
bool SeeingDecl()
{
if (SeeingIfAvailable()) {
return false;
}
return (SeeingModifier() && !Seeing({TokenKind::UNSAFE, TokenKind::LCURL})) ||
SeeingAny({TokenKind::FUNC, TokenKind::LET, TokenKind::VAR, TokenKind::ENUM, TokenKind::TYPE,
TokenKind::STRUCT, TokenKind::CLASS, TokenKind::INTERFACE, TokenKind::MAIN, TokenKind::EXTEND, TokenKind::PROP}) ||
(SeeingBuiltinAnnotation() && !SeeingAnnotationLambdaExpr());
}
bool SeeingIfAvailable()
{
if (!Seeing(TokenKind::AT)) {
return false;
}
auto tokens = lexer->LookAheadSkipNL(1);
return !tokens.empty() && tokens.begin()->kind == TokenKind::IDENTIFIER &&
tokens.begin()->Value() == IF_AVAILABLE;
}
bool SeeingExpr();
bool SeeingLiteral()
{
return SeeingAny({TokenKind::INTEGER_LITERAL, TokenKind::RUNE_BYTE_LITERAL, TokenKind::BOOL_LITERAL,
TokenKind::STRING_LITERAL, TokenKind::JSTRING_LITERAL, TokenKind::MULTILINE_STRING,
TokenKind::MULTILINE_RAW_STRING, TokenKind::RUNE_LITERAL, TokenKind::FLOAT_LITERAL,
TokenKind::UNIT_LITERAL});
}
bool SeeingPrimitiveTypeAndLParen()
{
return Seeing({TokenKind::INT8, TokenKind::LPAREN}) || Seeing({TokenKind::INT16, TokenKind::LPAREN}) ||
Seeing({TokenKind::INT32, TokenKind::LPAREN}) || Seeing({TokenKind::INT64, TokenKind::LPAREN}) ||
Seeing({TokenKind::INTNATIVE, TokenKind::LPAREN}) || Seeing({TokenKind::UINT8, TokenKind::LPAREN}) ||
Seeing({TokenKind::UINT16, TokenKind::LPAREN}) || Seeing({TokenKind::UINT32, TokenKind::LPAREN}) ||
Seeing({TokenKind::UINT64, TokenKind::LPAREN}) || Seeing({TokenKind::UINTNATIVE, TokenKind::LPAREN}) ||
Seeing({TokenKind::FLOAT16, TokenKind::LPAREN}) || Seeing({TokenKind::FLOAT32, TokenKind::LPAREN}) ||
Seeing({TokenKind::FLOAT64, TokenKind::LPAREN}) || Seeing({TokenKind::RUNE, TokenKind::LPAREN});
}
bool SeeingPrimitiveTypeAndDot()
{
return Seeing({TokenKind::INT8, TokenKind::DOT}) || Seeing({TokenKind::INT16, TokenKind::DOT}) ||
Seeing({TokenKind::INT32, TokenKind::DOT}) || Seeing({TokenKind::INT64, TokenKind::DOT}) ||
Seeing({TokenKind::INTNATIVE, TokenKind::DOT}) || Seeing({TokenKind::UINT8, TokenKind::DOT}) ||
Seeing({TokenKind::UINT16, TokenKind::DOT}) || Seeing({TokenKind::UINT32, TokenKind::DOT}) ||
Seeing({TokenKind::UINT64, TokenKind::DOT}) || Seeing({TokenKind::UINTNATIVE, TokenKind::DOT}) ||
Seeing({TokenKind::FLOAT16, TokenKind::DOT}) || Seeing({TokenKind::FLOAT32, TokenKind::DOT}) ||
Seeing({TokenKind::FLOAT64, TokenKind::DOT}) || Seeing({TokenKind::RUNE, TokenKind::DOT}) ||
Seeing({TokenKind::BOOLEAN, TokenKind::DOT}) || Seeing({TokenKind::UNIT, TokenKind::DOT}) ||
Seeing({TokenKind::NOTHING, TokenKind::DOT});
}
OwnedPtr<AST::Node> ParseExprOrDecl(ScopeKind sk);
private:
std::unique_ptr<Lexer> lexer;
std::string moduleName;
bool calculateLineNum{false};
std::list<std::pair<unsigned, unsigned>> allTokensInOneFile;
std::vector<TokenKind> bracketsStack;
bool newlineSkipped{true};
bool skipNL{true};
Position firstNLPosition{DEFAULT_POSITION};
};
#endif