[VER] 0.3.7-alpha

[Fix] 修复科学表达式数字解析的问题(Lexer引起) 由 Satklomi发现,感谢
[Feat] 增加Compiler相关定义,将开发BytecodeVM
[Tip] Evaluator进入Bug fix阶段,新功能延缓开发。转向VM
This commit is contained in:
2026-01-14 17:28:38 +08:00
parent 1ccc63419d
commit e28921ae02
30 changed files with 737 additions and 276 deletions

View File

@@ -56,7 +56,15 @@ namespace Fig
// {Ast::Operator::Dot, {40, 41}},
};
Ast::VarDef Parser::__parseVarDef(bool isPublic)
const std::unordered_map<Ast::Operator, Parser::Precedence> Parser::unaryOpPrecedence = {
{Ast::Operator::Subtract, 150}, // -
{Ast::Operator::BitAnd, 150}, // &
{Ast::Operator::BitNot, 150}, // ~
{Ast::Operator::Not, 150}, // !
};
Ast::VarDef
Parser::__parseVarDef(bool isPublic)
{
// entry: current is keyword `var` or `const`
bool isConst = (currentToken().getType() == TokenType::Const ? true : false);
@@ -416,8 +424,7 @@ namespace Fig
block));
continue;
}
expect(TokenType::Semicolon);
next(); // consume `;`
expectSemicolon();
methods.push_back(Ast::InterfaceMethod(
funcName,
@@ -563,7 +570,7 @@ namespace Fig
return makeAst<Ast::TrySt>(body, catches, finallyBlock);
}
Ast::Statement Parser::__parseStatement()
Ast::Statement Parser::__parseStatement(bool allowExp)
{
Ast::Statement stmt;
if (isThis(TokenType::EndOfFile)) { return makeAst<Ast::EofStmt>(); }
@@ -661,13 +668,21 @@ namespace Fig
{
stmt = __parseTry();
}
else
else if (allowExp)
{
// expression statement
Ast::Expression exp = parseExpression(0);
expectSemicolon();
stmt = makeAst<Ast::ExpressionStmtAst>(exp);
}
else
{
throw SyntaxError(
u8"invalid syntax",
currentAAI.line,
currentAAI.column
);
}
return stmt;
}
Ast::BlockStatement Parser::__parseBlockStatement()
@@ -700,7 +715,7 @@ namespace Fig
}
else
{
condition = parseExpression(0);
condition = parseExpression(0, TokenType::LeftBrace);
}
// parenthesis is not required
expect(TokenType::LeftBrace); // {
@@ -723,7 +738,7 @@ namespace Fig
}
else
{
elifCondition = parseExpression(0);
elifCondition = parseExpression(0, TokenType::LeftBrace);
}
expect(TokenType::LeftBrace); // {
Ast::BlockStatement elifBody = __parseBlockStatement();
@@ -776,7 +791,9 @@ namespace Fig
throwAddressableError<SyntaxError>(u8"Control flow statements cannot be used as for loop increment");
}
return __parseStatement();
Ast::Expression exp = parseExpression(0, TokenType::LeftBrace);
// expectSemicolon(); we dont check the semicolon
return makeAst<Ast::ExpressionStmtAst>(exp);
}
Ast::For Parser::__parseFor()
{
@@ -788,14 +805,14 @@ namespace Fig
next(); // consume `(`
// support 3-part for loop
// for init; condition; increment {}
Ast::Statement initStmt = __parseStatement(); // auto check ``
Ast::Statement initStmt = __parseStatement(false); // auto check ``
Ast::Expression condition = parseExpression(0);
expectSemicolon(); // auto consume `;`
Ast::Statement incrementStmt = nullptr;
if (!isThis(paren ? TokenType::RightParen : TokenType::LeftBrace)) // need parse increment?
{
auto guard = disableSemicolon();
// auto guard = disableSemicolon();
incrementStmt = __parseIncrementStatement();
} // after parse increment, semicolon check state restored
if (paren)
@@ -906,7 +923,7 @@ namespace Fig
return makeAst<Ast::MapExprAst>(val);
}
Ast::InitExpr Parser::__parseInitExpr(FString structName)
Ast::InitExpr Parser::__parseInitExpr(Ast::Expression structe)
{
// entry: current is `{`
next(); // consume `{`
@@ -917,7 +934,7 @@ namespace Fig
.2 Person {name: "Fig", age: 1, sex: "IDK"}; // can be unordered
.3 Person {name, age, sex};
*/
uint8_t mode; // 0=undetermined, 1=positional, 2=named, 3=shorthand
uint8_t mode = 0; // 0=undetermined, 1=positional, 2=named, 3=shorthand
while (!isThis(TokenType::RightBrace))
{
@@ -977,7 +994,7 @@ namespace Fig
}
expect(TokenType::RightBrace);
next(); // consume `}`
return makeAst<Ast::InitExprAst>(structName, args,
return makeAst<Ast::InitExprAst>(structe, args,
(mode == 1 ? Ast::InitExprAst::InitMode::Positional :
(mode == 2 ? Ast::InitExprAst::InitMode::Named : Ast::InitExprAst::InitMode::Shorthand)));
}
@@ -1067,8 +1084,7 @@ namespace Fig
throw SyntaxError();
}
}
expect(TokenType::Semicolon);
next(); // consume `;`
expectSemicolon();
return makeAst<Ast::ImportSt>(path);
}
@@ -1117,31 +1133,24 @@ namespace Fig
{
FString id = tok.getValue();
next();
if (currentToken().getType() == TokenType::LeftBrace)
{
lhs = __parseInitExpr(id); // a_struct{init...}
}
else
{
lhs = __parseVarExpr(id);
}
lhs = __parseVarExpr(id);
}
else if (isTokenOp(tok) && isOpUnary((op = Ast::TokenToOp.at(tok.getType()))))
{
// prefix
next();
lhs = __parsePrefix(op, getRightBindingPower(op));
lhs = makeAst<Ast::UnaryExprAst>(op, parseExpression(bp, stop, stop2));
}
else
{
throwAddressableError<SyntaxError>(FString(u8"Unexpected token in expression"));
throwAddressableError<SyntaxError>(FString(u8"Unexpected token in expression:") + tok.toString());
}
// infix / (postfix) ?
while (true)
{
tok = currentToken();
if (tok.getType() == TokenType::Semicolon || tok == EOFTok) break;
if (tok.getType() == stop || tok.getType() == stop2|| tok == EOFTok) break;
/* Postfix */
@@ -1151,6 +1160,12 @@ namespace Fig
continue;
}
if (tok.getType() == TokenType::LeftBrace)
{
lhs = __parseInitExpr(lhs);
continue;
}
// member access: a.b
if (tok.getType() == TokenType::Dot)
{
@@ -1169,7 +1184,7 @@ namespace Fig
if (tok.getType() == TokenType::LeftBracket)
{
next(); // consume '['
auto indexExpr = parseExpression(0, TokenType::RightBracket);
auto indexExpr = parseExpression(0, TokenType::RightBracket, stop2);
expect(TokenType::RightBracket);
next(); // consume ']'
@@ -1181,7 +1196,7 @@ namespace Fig
if (tok.getType() == TokenType::Question)
{
next(); // consume ?
Ast::Expression trueExpr = parseExpression(0, TokenType::Colon);
Ast::Expression trueExpr = parseExpression(0, TokenType::Colon, stop2);
expect(TokenType::Colon);
next(); // consume :
Ast::Expression falseExpr = parseExpression(0, TokenType::Semicolon, stop2);
@@ -1196,7 +1211,7 @@ namespace Fig
if (bp >= lbp) break;
next(); // consume op
lhs = __parseInfix(lhs, op, getRightBindingPower(op));
lhs = makeAst<Ast::BinaryExprAst>(lhs, op, parseExpression(bp, stop, stop2));
}
return lhs;

View File

@@ -1,5 +1,6 @@
#pragma once
#include "Ast/astBase.hpp"
#include <Ast/ast.hpp>
#include <Lexer/lexer.hpp>
#include <Core/fig_string.hpp>
@@ -38,15 +39,8 @@ namespace Fig
bool original;
public:
SemicolonDisabler(Parser *parser) :
p(parser), original(p->needSemicolon)
{
p->needSemicolon = false;
}
~SemicolonDisabler()
{
p->needSemicolon = original;
}
SemicolonDisabler(Parser *parser) : p(parser), original(p->needSemicolon) { p->needSemicolon = false; }
~SemicolonDisabler() { p->needSemicolon = original; }
// disable copy and assign
SemicolonDisabler(const SemicolonDisabler &) = delete;
SemicolonDisabler &operator=(const SemicolonDisabler &) = delete;
@@ -65,14 +59,8 @@ namespace Fig
output.push_back(node);
}
bool isTokenSymbol(Token tok)
{
return Lexer::symbol_map.contains(tok.getValue());
}
bool isTokenOp(Token tok)
{
return Ast::TokenToOp.contains(tok.getType());
}
bool isTokenSymbol(Token tok) { return Lexer::symbol_map.contains(tok.getValue()); }
bool isTokenOp(Token tok) { return Ast::TokenToOp.contains(tok.getType()); }
bool isEOF()
{
if (tokenPruduced == 0) return false;
@@ -82,21 +70,19 @@ namespace Fig
public:
using Precedence = uint32_t;
static const std::unordered_map<Ast::Operator, std::pair<Precedence, Precedence>> opPrecedence;
Parser(const Lexer &_lexer) :
lexer(_lexer)
{
}
static const std::unordered_map<Ast::Operator, Precedence> unaryOpPrecedence;
AddressableError* getError() const
{
return error.get();
}
Parser(const Lexer &_lexer) : lexer(_lexer) {}
AddressableError *getError() const { return error.get(); }
template <class _ErrT, typename = AddressableError>
void throwAddressableError(FString msg, size_t line, size_t column, std::source_location loc = std::source_location::current())
void throwAddressableError(FString msg,
size_t line,
size_t column,
std::source_location loc = std::source_location::current())
{
static_assert(std::is_base_of_v<AddressableError, _ErrT>,
"_ErrT must derive from AddressableError");
static_assert(std::is_base_of_v<AddressableError, _ErrT>, "_ErrT must derive from AddressableError");
_ErrT spError(msg, line, column, loc);
error = std::make_unique<_ErrT>(spError);
throw spError;
@@ -104,8 +90,7 @@ namespace Fig
template <class _ErrT, typename = AddressableError>
void throwAddressableError(FString msg, std::source_location loc = std::source_location::current())
{
static_assert(std::is_base_of_v<AddressableError, _ErrT>,
"_ErrT must derive from AddressableError");
static_assert(std::is_base_of_v<AddressableError, _ErrT>, "_ErrT must derive from AddressableError");
// line, column provide by `currentAAI`
_ErrT spError(msg, currentAAI.line, currentAAI.column, loc);
error = std::make_unique<_ErrT>(spError);
@@ -115,22 +100,15 @@ namespace Fig
template <class _ErrT, typename = UnaddressableError>
void throwUnaddressableError(FString msg, std::source_location loc = std::source_location::current())
{
static_assert(std::is_base_of_v<AddressableError, _ErrT>,
"_ErrT must derive from AddressableError");
static_assert(std::is_base_of_v<AddressableError, _ErrT>, "_ErrT must derive from AddressableError");
_ErrT spError(msg, loc);
error = std::make_unique<_ErrT>(spError);
throw spError;
}
void setCurrentAAI(Ast::AstAddressInfo _aai)
{
currentAAI = std::move(_aai);
}
void setCurrentAAI(Ast::AstAddressInfo _aai) { currentAAI = std::move(_aai); }
Ast::AstAddressInfo getCurrentAAI() const
{
return currentAAI;
}
Ast::AstAddressInfo getCurrentAAI() const { return currentAAI; }
inline const Token &nextToken()
{
@@ -143,7 +121,8 @@ namespace Fig
if (int64_t(currentTokenIndex - 1) < int64_t(0))
// 同下 next注释
{
throw std::runtime_error("Internal Error in Parser::rollbackToken, trying to rollback but it's already on the begin");
throw std::runtime_error(
"Internal Error in Parser::rollbackToken, trying to rollback but it's already on the begin");
}
currentTokenIndex--;
}
@@ -152,7 +131,8 @@ namespace Fig
if (int64_t(currentTokenIndex) < (int64_t(tokenPruduced) - 1))
{
/*
必须两个都显示转换为int64_t.否则负数时会超出范围变成int64_t max, 并且 CTI也需要显示转换否则转换完的pruduced又会被转回去变为 int64_t max
必须两个都显示转换为int64_t.否则负数时会超出范围变成int64_t max, 并且
CTI也需要显示转换否则转换完的pruduced又会被转回去变为 int64_t max
*/
currentTokenIndex++;
setCurrentAAI(Ast::AstAddressInfo{.line = currentToken().line, .column = currentToken().column});
@@ -184,18 +164,11 @@ namespace Fig
return tok;
}
std::pair<Precedence, Precedence> getBindingPower(Ast::Operator op)
{
return opPrecedence.at(op);
}
Precedence getLeftBindingPower(Ast::Operator op)
{
return getBindingPower(op).first;
}
Precedence getRightBindingPower(Ast::Operator op)
{
return getBindingPower(op).second;
}
const std::pair<Precedence, Precedence> &getBindingPower(Ast::Operator op) const { return opPrecedence.at(op); }
Precedence getLeftBindingPower(Ast::Operator op) const { return getBindingPower(op).first; }
Precedence getRightBindingPower(Ast::Operator op) const { return getBindingPower(op).second; }
const Precedence &getUnaryBp(Ast::Operator op) const { return unaryOpPrecedence.at(op); }
// template <class _Tp, class... Args>
// std::shared_ptr<_Tp> makeAst(Args &&...args)
@@ -217,8 +190,9 @@ namespace Fig
if (peekToken().getType() != type)
{
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
magic_enum::enum_name(type),
magic_enum::enum_name(peekToken().getType()))), loc);
magic_enum::enum_name(type),
magic_enum::enum_name(peekToken().getType()))),
loc);
}
}
@@ -226,9 +200,11 @@ namespace Fig
{
if (currentToken().getType() != type)
{
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
magic_enum::enum_name(type),
magic_enum::enum_name(currentToken().getType()))), loc);
throwAddressableError<SyntaxError>(
FString(std::format("Expected `{}`, but got `{}`",
magic_enum::enum_name(type),
magic_enum::enum_name(currentToken().getType()))),
loc);
}
}
@@ -237,8 +213,9 @@ namespace Fig
if (peekToken().getType() != type)
{
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
expected.toBasicString(),
magic_enum::enum_name(peekToken().getType()))), loc);
expected.toBasicString(),
magic_enum::enum_name(peekToken().getType()))),
loc);
}
}
@@ -246,16 +223,15 @@ namespace Fig
{
if (currentToken().getType() != type)
{
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
expected.toBasicString(),
magic_enum::enum_name(currentToken().getType()))), loc);
throwAddressableError<SyntaxError>(
FString(std::format("Expected `{}`, but got `{}`",
expected.toBasicString(),
magic_enum::enum_name(currentToken().getType()))),
loc);
}
}
[[nodiscard]] SemicolonDisabler disableSemicolon()
{
return SemicolonDisabler(this);
}
[[nodiscard]] SemicolonDisabler disableSemicolon() { return SemicolonDisabler(this); }
void expectSemicolon()
{
@@ -287,14 +263,8 @@ namespace Fig
next();
}
bool isNext(TokenType type)
{
return peekToken().getType() == type;
}
bool isThis(TokenType type)
{
return currentToken().getType() == type;
}
bool isNext(TokenType type) { return peekToken().getType() == type; }
bool isThis(TokenType type) { return currentToken().getType() == type; }
static constexpr FString varDefTypeFollowed = u8"(Followed)";
@@ -313,28 +283,30 @@ namespace Fig
Ast::VarExpr __parseVarExpr(FString);
Ast::FunctionDef __parseFunctionDef(bool); // entry: current is Token::Identifier (isPublic: Bool)
Ast::StructDef __parseStructDef(bool); // entry: current is Token::Identifier (struct name) arg(isPublic: bool)
Ast::InterfaceDef __parseInterfaceDef(bool); // entry: current is Token::Identifier (interface name) arg(isPublic: bool)
Ast::Implement __parseImplement(); // entry: current is `impl`
Ast::StructDef __parseStructDef(bool); // entry: current is Token::Identifier (struct name) arg(isPublic: bool)
Ast::InterfaceDef
__parseInterfaceDef(bool); // entry: current is Token::Identifier (interface name) arg(isPublic: bool)
Ast::Implement __parseImplement(); // entry: current is `impl`
Ast::Throw __parseThrow(); // entry: current is `throw`
Ast::Try __parseTry(); // entry: current is `try`
Ast::Throw __parseThrow(); // entry: current is `throw`
Ast::Try __parseTry(); // entry: current is `try`
Ast::BinaryExpr __parseInfix(Ast::Expression, Ast::Operator, Precedence);
Ast::UnaryExpr __parsePrefix(Ast::Operator, Precedence);
Ast::Expression __parseCall(Ast::Expression);
Ast::ListExpr __parseListExpr(); // entry: current is `[`
Ast::MapExpr __parseMapExpr(); // entry: current is `{`
Ast::InitExpr __parseInitExpr(FString); // entry: current is `{`, ahead is struct name. arg (struct name : FString)
Ast::Expression __parseTupleOrParenExpr(); // entry: current is `(`
Ast::ListExpr __parseListExpr(); // entry: current is `[`
Ast::MapExpr __parseMapExpr(); // entry: current is `{`
Ast::InitExpr __parseInitExpr(
Ast::Expression); // entry: current is `{`, ahead is struct type exp.
Ast::Expression __parseTupleOrParenExpr(); // entry: current is `(`
Ast::FunctionLiteralExpr __parseFunctionLiteralExpr(); // entry: current is Token::LParen after Token::Function
Ast::Import __parseImport(); // entry: current is Token::Import
Ast::Statement __parseStatement(); // entry: (idk)
Ast::Import __parseImport(); // entry: current is Token::Import
Ast::Statement __parseStatement(bool = true); // entry: (idk)
Ast::Expression parseExpression(Precedence, TokenType = TokenType::Semicolon, TokenType = TokenType::Semicolon);
std::vector<Ast::AstBase> parseAll();
};