* 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 implements the ParserSyntaxImpl.
*/
#include "ParserSyntaxImpl.h"
#include "cangjie/AST/Match.h"
#include "cangjie/Utils/Unicode.h"
using namespace Cangjie;
using namespace Cangjie::AST;
ParserSyntaxImpl::ParserSyntaxImpl(const std::string& input, DiagnosticEngine& diag, SourceManager& sm, const Position& pos,
bool attachComment)
: lexer{std::make_unique<Lexer>(input, diag, sm, pos, attachComment)}
{
}
ParserSyntaxImpl::ParserSyntaxImpl(const std::vector<Token>& inputTokens, DiagnosticEngine& diag, SourceManager& sm,
bool attachComment)
: lexer{std::make_unique<Lexer>(inputTokens, diag, sm, attachComment)}
{
}
ParserSyntaxImpl::~ParserSyntaxImpl()
{
}
const Token& ParserSyntaxImpl::Peek()
{
if (lookahead.kind != TokenKind::SENTINEL) {
return lookahead;
}
bool firstNLFlag = true;
do {
lookahead = lexer->Next();
if (calculateLineNum) {
allTokensInOneFile.emplace_back(lookahead.Begin().line, lookahead.End().line);
}
if (lookahead.kind == TokenKind::LCURL || lookahead.kind == TokenKind::LPAREN ||
lookahead.kind == TokenKind::LSQUARE) {
bracketsStack.push_back(lookahead.kind);
}
const std::unordered_map<TokenKind, TokenKind> MATCHING_OPENING_BRACKET_OF{{TokenKind::RCURL, TokenKind::LCURL},
{TokenKind::RSQUARE, TokenKind::LSQUARE}, {TokenKind::RPAREN, TokenKind::LPAREN}};
auto matchingBracket = MATCHING_OPENING_BRACKET_OF.find(lookahead.kind);
if (matchingBracket != MATCHING_OPENING_BRACKET_OF.end()) {
if (!bracketsStack.empty() && matchingBracket->second == bracketsStack.back()) {
bracketsStack.pop_back();
}
}
if (lookahead.kind == TokenKind::NL) {
newlineSkipped = true;
if (firstNLFlag) {
firstNLPosition = lookahead.Begin();
firstNLFlag = false;
}
}
} while (lookahead.kind == TokenKind::COMMENT || (lookahead.kind == TokenKind::NL && skipNL));
if (lookahead.kind == TokenKind::END && !lastToken.Begin().IsZero()) {
lookahead.SetValuePos(lookahead.Value(), lastToken.End(), lastToken.End());
}
return lookahead;
}
bool ParserSyntaxImpl::Seeing(const std::vector<TokenKind>& kinds, bool skipNewline)
{
if (lookahead.kind != TokenKind::SENTINEL) {
if (lookahead.kind == kinds[0]) {
return lexer->Seeing(kinds.begin() + 1, kinds.end(), skipNewline);
}
return false;
} else {
return lexer->Seeing(kinds, skipNewline);
}
}
bool ParserSyntaxImpl::SeeingModifier()
{
return (Peek().kind >= TokenKind::STATIC && Peek().kind <= TokenKind::OPERATOR) ||
(Peek().kind == TokenKind::CONST) || (Peek().kind == TokenKind::COMMON) || (Peek().kind == TokenKind::SPECIFIC);
}
bool ParserSyntaxImpl::SeeingMacroCall()
{
if (!Seeing(TokenKind::AT)) {
return false;
}
auto tokens = lexer->LookAheadSkipNL(1);
if (tokens.begin()->kind != TokenKind::IDENTIFIER && (tokens.begin()->kind < TokenKind::PUBLIC ||
tokens.begin()->kind > TokenKind::OPEN)) {
return false;
}
return !IsBuiltinAnnotation(moduleName, tokens.begin()->Value());
}
bool ParserSyntaxImpl::SeeingBuiltinAnnotation()
{
if (!Seeing(TokenKind::AT)) {
return false;
}
auto tokens = lexer->LookAheadSkipNL(1);
if (tokens.begin()->kind != TokenKind::IDENTIFIER) {
return false;
}
return IsBuiltinAnnotation(moduleName, tokens.begin()->Value());
}
bool ParserSyntaxImpl::SeeingExpr()
{
static const std::vector<TokenKind> exprFirstToken = {
TokenKind::SUB,
TokenKind::NOT,
TokenKind::IF,
TokenKind::MATCH,
TokenKind::QUOTE,
TokenKind::TRY,
TokenKind::THROW,
TokenKind::PERFORM,
TokenKind::RESUME,
TokenKind::RETURN,
TokenKind::CONTINUE,
TokenKind::BREAK,
TokenKind::FOR,
TokenKind::WHILE,
TokenKind::DO,
TokenKind::SPAWN,
TokenKind::SYNCHRONIZED,
TokenKind::LPAREN,
TokenKind::LCURL,
TokenKind::LSQUARE,
TokenKind::THIS,
TokenKind::SUPER,
TokenKind::IDENTIFIER,
TokenKind::UNSAFE,
TokenKind::WILDCARD,
TokenKind::VARRAY,
};
if (SeeingAny(exprFirstToken)) {
return true;
}
return SeeingLiteral() || SeeingPrimitiveTypeAndLParen() || SeeingPrimitiveTypeAndDot() || SeeingMacroCall() ||
SeeingBuiltinAnnotation();
}