Revert "Make it possible to nest match-expressions"
This reverts commit ac7467bccb
.
The commit breaks too much syntax.
This commit is contained in:
parent
ac7467bccb
commit
8b1263c376
5 changed files with 31 additions and 102 deletions
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
@ -9,7 +9,7 @@
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug",
|
"name": "Debug",
|
||||||
"program": "${workspaceFolder}/build/bolt",
|
"program": "${workspaceFolder}/build/bolt",
|
||||||
"args": [ "--direct-diagnostics", "check", "test.bolt" ],
|
"args": [ "--direct-diagnostics", "verify", "test/checker/wrong_return_type.bolt" ],
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"preLaunchTask": "CMake: build"
|
"preLaunchTask": "CMake: build"
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,9 +99,6 @@ namespace bolt {
|
||||||
void checkLineFoldEnd();
|
void checkLineFoldEnd();
|
||||||
void skipToLineFoldEnd();
|
void skipToLineFoldEnd();
|
||||||
|
|
||||||
void disablePunctuation();
|
|
||||||
void enablePunctuation();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Parser(TextFile& File, Stream<Token*>& S, DiagnosticEngine& DE);
|
Parser(TextFile& File, Stream<Token*>& S, DiagnosticEngine& DE);
|
||||||
|
|
|
@ -61,25 +61,16 @@ namespace bolt {
|
||||||
enum class FrameType {
|
enum class FrameType {
|
||||||
Block,
|
Block,
|
||||||
LineFold,
|
LineFold,
|
||||||
};
|
Fallthrough,
|
||||||
|
|
||||||
struct Frame {
|
|
||||||
FrameType Type;
|
|
||||||
int Parens = 0;
|
|
||||||
int Braces = 0;
|
|
||||||
int Brackets = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Punctuator : public BufferedStream<Token*> {
|
class Punctuator : public BufferedStream<Token*> {
|
||||||
|
|
||||||
Stream<Token*>& Tokens;
|
Stream<Token*>& Tokens;
|
||||||
|
|
||||||
std::stack<Frame> Frames;
|
std::stack<FrameType> Frames;
|
||||||
std::stack<TextLoc> Locations;
|
std::stack<TextLoc> Locations;
|
||||||
|
|
||||||
bool ShouldYieldNextTokenInLineFold = false;
|
|
||||||
bool isTerminal(NodeKind Kind);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual Token* read() override;
|
virtual Token* read() override;
|
||||||
|
|
|
@ -492,8 +492,8 @@ after_tuple_element:
|
||||||
}
|
}
|
||||||
|
|
||||||
MatchExpression* Parser::parseMatchExpression() {
|
MatchExpression* Parser::parseMatchExpression() {
|
||||||
auto Match = expectToken<MatchKeyword>();
|
auto T0 = expectToken<MatchKeyword>();
|
||||||
if (!Match) {
|
if (!T0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto T1 = Tokens.peek();
|
auto T1 = Tokens.peek();
|
||||||
|
@ -506,12 +506,12 @@ after_tuple_element:
|
||||||
} else {
|
} else {
|
||||||
Value = parseExpression();
|
Value = parseExpression();
|
||||||
if (!Value) {
|
if (!Value) {
|
||||||
Match->unref();
|
T0->unref();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
BlockStart = expectToken<class BlockStart>();
|
BlockStart = expectToken<class BlockStart>();
|
||||||
if (!BlockStart) {
|
if (!BlockStart) {
|
||||||
Match->unref();
|
T0->unref();
|
||||||
Value->unref();
|
Value->unref();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -544,7 +544,7 @@ after_tuple_element:
|
||||||
checkLineFoldEnd();
|
checkLineFoldEnd();
|
||||||
Cases.push_back(new MatchCase { Pattern, RArrowAlt, Expression });
|
Cases.push_back(new MatchCase { Pattern, RArrowAlt, Expression });
|
||||||
}
|
}
|
||||||
return new MatchExpression(Match, Value, BlockStart, Cases);
|
return new MatchExpression(static_cast<MatchKeyword*>(T0), Value, BlockStart, Cases);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordExpression* Parser::parseRecordExpression() {
|
RecordExpression* Parser::parseRecordExpression() {
|
||||||
|
@ -688,13 +688,10 @@ after_tuple_element:
|
||||||
case NodeKind::LineFoldEnd:
|
case NodeKind::LineFoldEnd:
|
||||||
case NodeKind::BlockStart:
|
case NodeKind::BlockStart:
|
||||||
case NodeKind::EndOfFile:
|
case NodeKind::EndOfFile:
|
||||||
|
// Can recover from this one
|
||||||
|
RParen = nullptr;
|
||||||
DE.add<UnexpectedTokenDiagnostic>(File, T2, std::vector { NodeKind::RParen, NodeKind::Comma });
|
DE.add<UnexpectedTokenDiagnostic>(File, T2, std::vector { NodeKind::RParen, NodeKind::Comma });
|
||||||
LParen->unref();
|
goto after_tuple_elements;
|
||||||
for (auto [E, Comma]: Elements) {
|
|
||||||
E->unref();
|
|
||||||
Comma->unref();
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
after_tuple_elements:
|
after_tuple_elements:
|
||||||
|
@ -767,7 +764,6 @@ finish:
|
||||||
if (T1->getKind() == NodeKind::LineFoldEnd
|
if (T1->getKind() == NodeKind::LineFoldEnd
|
||||||
|| T1->getKind() == NodeKind::RParen
|
|| T1->getKind() == NodeKind::RParen
|
||||||
|| T1->getKind() == NodeKind::RBrace
|
|| T1->getKind() == NodeKind::RBrace
|
||||||
|| T1->getKind() == NodeKind::RBracket
|
|
||||||
|| T1->getKind() == NodeKind::BlockStart
|
|| T1->getKind() == NodeKind::BlockStart
|
||||||
|| T1->getKind() == NodeKind::Comma
|
|| T1->getKind() == NodeKind::Comma
|
||||||
|| ExprOperators.isInfix(T1)) {
|
|| ExprOperators.isInfix(T1)) {
|
||||||
|
|
|
@ -426,77 +426,17 @@ after_string_contents:
|
||||||
|
|
||||||
Punctuator::Punctuator(Stream<Token*>& Tokens):
|
Punctuator::Punctuator(Stream<Token*>& Tokens):
|
||||||
Tokens(Tokens) {
|
Tokens(Tokens) {
|
||||||
Frames.push({ FrameType::Block });
|
Frames.push(FrameType::Block);
|
||||||
Locations.push(TextLoc { 0, 0 });
|
Locations.push(TextLoc { 0, 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isCloseDelim(NodeKind Kind) {
|
|
||||||
switch (Kind) {
|
|
||||||
case NodeKind::RParen:
|
|
||||||
case NodeKind::RBrace:
|
|
||||||
case NodeKind::RBracket:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// struct DelimCounter {
|
|
||||||
// int Parens = 0;
|
|
||||||
// int Braces = 0;
|
|
||||||
// int Brackets = 0;
|
|
||||||
// };
|
|
||||||
|
|
||||||
bool Punctuator::isTerminal(NodeKind Kind) {
|
|
||||||
auto& Frame = Frames.top();
|
|
||||||
switch (Kind) {
|
|
||||||
case NodeKind::RParen:
|
|
||||||
return Frame.Parens == 0;
|
|
||||||
case NodeKind::RBrace:
|
|
||||||
return Frame.Braces == 0;
|
|
||||||
case NodeKind::RBracket:
|
|
||||||
return Frame.Brackets == 0;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Token* Punctuator::read() {
|
Token* Punctuator::read() {
|
||||||
|
|
||||||
auto T0 = Tokens.peek();
|
auto T0 = Tokens.peek();
|
||||||
auto& RefLoc = Locations.top();
|
|
||||||
auto& Frame = Frames.top();
|
|
||||||
|
|
||||||
switch (T0->getKind()) {
|
switch (T0->getKind()) {
|
||||||
case NodeKind::LParen:
|
|
||||||
++Frame.Parens;
|
|
||||||
break;
|
|
||||||
case NodeKind::LBrace:
|
case NodeKind::LBrace:
|
||||||
++Frame.Braces;
|
Frames.push(FrameType::Fallthrough);
|
||||||
break;
|
|
||||||
case NodeKind::LBracket:
|
|
||||||
++Frame.Brackets;
|
|
||||||
break;
|
|
||||||
case NodeKind::RParen:
|
|
||||||
if (Frame.Parens == 0) {
|
|
||||||
// TODO add diagnostic?
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
--Frame.Parens;
|
|
||||||
break;
|
|
||||||
case NodeKind::RBrace:
|
|
||||||
if (Frame.Braces == 0) {
|
|
||||||
// TODO add diagnostic?
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
--Frame.Braces;
|
|
||||||
break;
|
|
||||||
case NodeKind::RBracket:
|
|
||||||
if (Frame.Brackets == 0) {
|
|
||||||
// TODO add diagnostic?
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
--Frame.Brackets;
|
|
||||||
break;
|
break;
|
||||||
case NodeKind::EndOfFile:
|
case NodeKind::EndOfFile:
|
||||||
{
|
{
|
||||||
|
@ -505,7 +445,9 @@ after_string_contents:
|
||||||
}
|
}
|
||||||
auto Frame = Frames.top();
|
auto Frame = Frames.top();
|
||||||
Frames.pop();
|
Frames.pop();
|
||||||
switch (Frame.Type) {
|
switch (Frame) {
|
||||||
|
case FrameType::Fallthrough:
|
||||||
|
break;
|
||||||
case FrameType::Block:
|
case FrameType::Block:
|
||||||
return new BlockEnd(T0->getStartLoc());
|
return new BlockEnd(T0->getStartLoc());
|
||||||
case FrameType::LineFold:
|
case FrameType::LineFold:
|
||||||
|
@ -516,17 +458,20 @@ after_string_contents:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Frame.Type) {
|
auto RefLoc = Locations.top();
|
||||||
|
switch (Frames.top()) {
|
||||||
|
case FrameType::Fallthrough:
|
||||||
|
{
|
||||||
|
if (T0->getKind() == NodeKind::RBrace) {
|
||||||
|
Frames.pop();
|
||||||
|
}
|
||||||
|
Tokens.get();
|
||||||
|
return T0;
|
||||||
|
}
|
||||||
case FrameType::LineFold:
|
case FrameType::LineFold:
|
||||||
{
|
{
|
||||||
if (ShouldYieldNextTokenInLineFold) {
|
if (T0->getStartLine() > RefLoc.Line
|
||||||
ShouldYieldNextTokenInLineFold = false;
|
&& T0->getStartColumn() <= RefLoc.Column) {
|
||||||
return Tokens.get();
|
|
||||||
}
|
|
||||||
ShouldYieldNextTokenInLineFold = isTerminal(T0->getKind());
|
|
||||||
if (ShouldYieldNextTokenInLineFold
|
|
||||||
|| (T0->getStartLine() > RefLoc.Line
|
|
||||||
&& T0->getStartColumn() <= RefLoc.Column)) {
|
|
||||||
Frames.pop();
|
Frames.pop();
|
||||||
Locations.pop();
|
Locations.pop();
|
||||||
return new LineFoldEnd(T0->getStartLoc());
|
return new LineFoldEnd(T0->getStartLoc());
|
||||||
|
@ -535,7 +480,7 @@ after_string_contents:
|
||||||
auto T1 = Tokens.peek(1);
|
auto T1 = Tokens.peek(1);
|
||||||
if (T1->getStartLine() > T0->getEndLine()) {
|
if (T1->getStartLine() > T0->getEndLine()) {
|
||||||
Tokens.get();
|
Tokens.get();
|
||||||
Frames.push({ FrameType::Block });
|
Frames.push(FrameType::Block);
|
||||||
return new BlockStart(T0->getStartLoc());
|
return new BlockStart(T0->getStartLoc());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -543,12 +488,12 @@ after_string_contents:
|
||||||
}
|
}
|
||||||
case FrameType::Block:
|
case FrameType::Block:
|
||||||
{
|
{
|
||||||
if (T0->getStartColumn() <= RefLoc.Column || isTerminal(T0->getKind())) {
|
if (T0->getStartColumn() <= RefLoc.Column) {
|
||||||
Frames.pop();
|
Frames.pop();
|
||||||
return new BlockEnd(T0->getStartLoc());
|
return new BlockEnd(T0->getStartLoc());
|
||||||
}
|
}
|
||||||
|
|
||||||
Frames.push({ FrameType::LineFold });
|
Frames.push(FrameType::LineFold);
|
||||||
Locations.push(T0->getStartLoc());
|
Locations.push(T0->getStartLoc());
|
||||||
|
|
||||||
return Tokens.get();
|
return Tokens.get();
|
||||||
|
|
Loading…
Reference in a new issue