Initial Parser Implementation and Feature Completion #1
@ -93,7 +93,8 @@ namespace arti::lang::ast {
|
||||
WhileStmtNode,
|
||||
DoWhileStmtNode,
|
||||
InfLoopStmtNode,
|
||||
ExpressionStmtNode
|
||||
ExpressionStmtNode,
|
||||
CodeBlockStmtNode
|
||||
>;
|
||||
|
||||
using ElseBranchNode = Variant<
|
||||
|
||||
@ -1002,6 +1002,7 @@ namespace arti::lang::ast {
|
||||
[&g](const DoWhileStmtNode &n) { return emit(n, g); },
|
||||
[&g](const InfLoopStmtNode &n) { return emit(n, g); },
|
||||
[&g](const ExpressionStmtNode &n) { return emit(n, g); },
|
||||
[&g](const CodeBlockStmtNode &n) { return emit(n, g); },
|
||||
};
|
||||
return std::visit(visitor, node);
|
||||
}
|
||||
|
||||
@ -1419,6 +1419,9 @@ namespace arti::lang::ast {
|
||||
[padding](const ExpressionStmtNode &node) -> std::string {
|
||||
return toString(node, padding);
|
||||
},
|
||||
[padding](const CodeBlockStmtNode &node) -> std::string {
|
||||
return toString(node, padding);
|
||||
}
|
||||
};
|
||||
|
||||
return std::visit(visitor, node);
|
||||
|
||||
@ -468,6 +468,13 @@ namespace arti::lang {
|
||||
|
||||
bool keepParsing = true;
|
||||
|
||||
if (auto close = match(TokenV::opRSquirly); ! close) {
|
||||
return Unexpected{ std::move(close).error() };
|
||||
}
|
||||
else if (close.value()) {
|
||||
keepParsing = false;
|
||||
}
|
||||
|
||||
while (keepParsing) {
|
||||
if (auto member = parseStructMember(); ! member) {
|
||||
return Unexpected{ std::move(member).error() };
|
||||
@ -479,13 +486,22 @@ namespace arti::lang {
|
||||
if (auto comma = matchAndConsume(TokenV::opComma); ! comma) {
|
||||
return Unexpected<>{ std::move(comma).error() };
|
||||
}
|
||||
|
||||
if (auto peekToken = tokenizer.peek(); ! peekToken) {
|
||||
return Unexpected{ std::move(peekToken).error() };
|
||||
}
|
||||
else {
|
||||
if (peekToken->value == TokenV::opRSquirly) {
|
||||
keepParsing = false;
|
||||
else if (! comma.value()) {
|
||||
if (auto peekToken = tokenizer.peek(); ! peekToken) {
|
||||
return Unexpected{ std::move(peekToken).error() };
|
||||
}
|
||||
else {
|
||||
if (peekToken->value != TokenV::opRSquirly) {
|
||||
return langException<ExceptCode::ecUnexpectedToken>(
|
||||
peekToken->line,
|
||||
peekToken->column,
|
||||
toString(*peekToken),
|
||||
"',' or '}'"
|
||||
);
|
||||
}
|
||||
else {
|
||||
keepParsing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -533,6 +549,13 @@ namespace arti::lang {
|
||||
|
||||
bool keepParsing = true;
|
||||
|
||||
if (auto close = match(TokenV::opRSquirly); ! close) {
|
||||
return Unexpected{ std::move(close).error() };
|
||||
}
|
||||
else if (close.value()) {
|
||||
keepParsing = false;
|
||||
}
|
||||
|
||||
while (keepParsing) {
|
||||
if (auto member = parseEnumMember(); ! member) {
|
||||
return Unexpected{ std::move(member).error() };
|
||||
@ -544,13 +567,22 @@ namespace arti::lang {
|
||||
if (auto comma = matchAndConsume(TokenV::opComma); ! comma) {
|
||||
return Unexpected<>{ std::move(comma).error() };
|
||||
}
|
||||
|
||||
if (auto peekToken = tokenizer.peek(); ! peekToken) {
|
||||
return Unexpected{ std::move(peekToken).error() };
|
||||
}
|
||||
else {
|
||||
if (peekToken->value == TokenV::opRSquirly) {
|
||||
keepParsing = false;
|
||||
else if (! comma.value()) {
|
||||
if (auto peekToken = tokenizer.peek(); ! peekToken) {
|
||||
return Unexpected{ std::move(peekToken).error() };
|
||||
}
|
||||
else {
|
||||
if (peekToken->value != TokenV::opRSquirly) {
|
||||
return langException<ExceptCode::ecUnexpectedToken>(
|
||||
peekToken->line,
|
||||
peekToken->column,
|
||||
toString(*peekToken),
|
||||
"',' or '}'"
|
||||
);
|
||||
}
|
||||
else {
|
||||
keepParsing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,6 +36,13 @@ namespace arti::lang {
|
||||
return Unexpected<>{ std::move(lsquirly).error() };
|
||||
}
|
||||
|
||||
if (auto close = match(TokenV::opRSquirly); ! close) {
|
||||
return Unexpected<>{ std::move(close).error() };
|
||||
}
|
||||
else if (close.value()) {
|
||||
keepParsing = false;
|
||||
}
|
||||
|
||||
while (keepParsing) {
|
||||
if (auto ok = parseStatement(); ! ok) {
|
||||
return Unexpected<>{ std::move(ok).error() };
|
||||
@ -50,6 +57,13 @@ namespace arti::lang {
|
||||
node->statements.push_back(std::move(stmt).value());
|
||||
}
|
||||
}
|
||||
|
||||
if (auto close = match(TokenV::opRSquirly); ! close) {
|
||||
return Unexpected<>{ std::move(close).error() };
|
||||
}
|
||||
else if (close.value()) {
|
||||
keepParsing = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto rsquirly = consume(TokenV::opRSquirly, "'}'"); ! rsquirly) {
|
||||
@ -300,6 +314,23 @@ namespace arti::lang {
|
||||
return ast::StatementNode{ std::move(stmt).value() };
|
||||
}
|
||||
}
|
||||
else if (peekToken->value == TokenV::opLSquirly) {
|
||||
if (label.has_value()) {
|
||||
return langException<ExceptCode::ecUnexpectedToken>(
|
||||
peekToken->line,
|
||||
peekToken->column,
|
||||
toString(*peekToken),
|
||||
"loop keyword, i.e. any of ( for, while, do, loop )"
|
||||
);
|
||||
}
|
||||
|
||||
if (auto stmt = parseCodeBlock(); ! stmt) {
|
||||
return Unexpected<>{ std::move(stmt).error() };
|
||||
}
|
||||
else {
|
||||
return ast::StatementNode{ std::move(stmt).value() };
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (label.has_value()) {
|
||||
return langException<ExceptCode::ecUnexpectedToken>(
|
||||
@ -981,7 +1012,7 @@ namespace arti::lang {
|
||||
return Unexpected<>{ std::move(lParen).error() };
|
||||
}
|
||||
|
||||
if (auto skipPre = match(TokenV::opSemicolon); ! skipPre) {
|
||||
if (auto skipPre = matchAndConsume(TokenV::opSemicolon); ! skipPre) {
|
||||
return Unexpected<>{ std::move(skipPre).error() };
|
||||
}
|
||||
else if (not skipPre.value()) {
|
||||
@ -1234,6 +1265,10 @@ namespace arti::lang {
|
||||
return Unexpected<>{ std::move(rParen).error() };
|
||||
}
|
||||
|
||||
if (auto rParen = consume(TokenV::opSemicolon, "';'"); ! rParen) {
|
||||
return Unexpected<>{ std::move(rParen).error() };
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user