Add break and continue (partial)
This commit is contained in:
parent
cee884342a
commit
62eb2bece6
@ -12,4 +12,20 @@ using namespace std;
|
|||||||
*/
|
*/
|
||||||
EvalResult eval(Node &ast, Memory& memory);
|
EvalResult eval(Node &ast, Memory& memory);
|
||||||
|
|
||||||
|
class BreakException : public runtime_error {
|
||||||
|
public:
|
||||||
|
explicit BreakException(const string& message, CodePosition pos)
|
||||||
|
: runtime_error(message), pos(pos) {}
|
||||||
|
|
||||||
|
const CodePosition pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ContinueException : public runtime_error {
|
||||||
|
public:
|
||||||
|
explicit ContinueException(const string& message, CodePosition pos)
|
||||||
|
: runtime_error(message), pos(pos) {}
|
||||||
|
|
||||||
|
const CodePosition pos;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -12,7 +12,7 @@ using namespace std;
|
|||||||
/**
|
/**
|
||||||
* Tokens definition
|
* Tokens definition
|
||||||
*/
|
*/
|
||||||
enum class TokenType { Identifier, Litteral, Plus, Minus, DoublePlus, DoubleMinus, DoubleEqual, Land, Lor, Lt, Gt, Leq, Geq, NotEqual, Not, Star, Slash, Percent, Equal, Semicolon, LParenthese, RParenthese, LCurlyBracket, RCurlyBracket, If, Else, While, For, Comma };
|
enum class TokenType { Identifier, Litteral, Plus, Minus, DoublePlus, DoubleMinus, DoubleEqual, Land, Lor, Lt, Gt, Leq, Geq, NotEqual, Not, Star, Slash, Percent, Equal, Semicolon, LParenthese, RParenthese, LCurlyBracket, RCurlyBracket, If, Else, While, For, Break, Continue, Comma };
|
||||||
enum class Type { Int, Double };
|
enum class Type { Int, Double };
|
||||||
|
|
||||||
using TokenData = variant<int, double, string, Type>;
|
using TokenData = variant<int, double, string, Type>;
|
||||||
|
@ -79,32 +79,60 @@ EvalResult eval(Node &ast, Memory &memory) {
|
|||||||
int cond = bool_cast(eval(node.children[0], memory));
|
int cond = bool_cast(eval(node.children[0], memory));
|
||||||
if (!cond) break;
|
if (!cond) break;
|
||||||
|
|
||||||
|
try {
|
||||||
eval(node.children[1], memory);
|
eval(node.children[1], memory);
|
||||||
}
|
}
|
||||||
|
catch (const BreakException& e) { break; }
|
||||||
|
catch (const ContinueException& e) {}
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
} break;
|
} break;
|
||||||
case NodeType::For: {
|
case NodeType::For: {
|
||||||
memory.add_scope(ScopeType::For);
|
memory.add_scope(ScopeType::For);
|
||||||
|
|
||||||
|
try {
|
||||||
eval(node.children[0], memory);
|
eval(node.children[0], memory);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
int cond = bool_cast(eval(node.children[1], memory));
|
int cond = bool_cast(eval(node.children[1], memory));
|
||||||
if (!cond) break;
|
if (!cond) break;
|
||||||
|
|
||||||
|
try {
|
||||||
eval(node.children[3], memory);
|
eval(node.children[3], memory);
|
||||||
|
}
|
||||||
|
catch (const BreakException& e) { break; }
|
||||||
|
catch (const ContinueException& e) {}
|
||||||
|
|
||||||
eval(node.children[2], memory);
|
eval(node.children[2], memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
memory.remove_scope();
|
memory.remove_scope();
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
memory.remove_scope();
|
||||||
|
|
||||||
|
exception_ptr e = current_exception();
|
||||||
|
if (e) rethrow_exception(e);
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
} break;
|
} break;
|
||||||
case NodeType::Bloc: {
|
case NodeType::Bloc: {
|
||||||
memory.add_scope(ScopeType::Block);
|
memory.add_scope(ScopeType::Block);
|
||||||
|
|
||||||
|
try {
|
||||||
eval(node.children[0], memory);
|
eval(node.children[0], memory);
|
||||||
|
|
||||||
memory.remove_scope();
|
memory.remove_scope();
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
memory.remove_scope();
|
||||||
|
|
||||||
|
exception_ptr e = current_exception();
|
||||||
|
if (e) rethrow_exception(e);
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
} break;
|
} break;
|
||||||
case NodeType::Eq: {
|
case NodeType::Eq: {
|
||||||
@ -393,6 +421,12 @@ EvalResult eval(Node &ast, Memory &memory) {
|
|||||||
|
|
||||||
return var.value;
|
return var.value;
|
||||||
} break;
|
} break;
|
||||||
|
case TokenType::Break: {
|
||||||
|
throw BreakException("", token.pos);
|
||||||
|
} break;
|
||||||
|
case TokenType::Continue: {
|
||||||
|
throw ContinueException("", token.pos);
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
throw exception();
|
throw exception();
|
||||||
break;
|
break;
|
||||||
|
@ -14,6 +14,8 @@ vector<tuple<string, TokenType>> simpleTokens = {
|
|||||||
{ "else", TokenType::Else },
|
{ "else", TokenType::Else },
|
||||||
{ "while", TokenType::While },
|
{ "while", TokenType::While },
|
||||||
{ "for", TokenType::For },
|
{ "for", TokenType::For },
|
||||||
|
{ "break", TokenType::Break },
|
||||||
|
{ "continue", TokenType::Continue },
|
||||||
{ "++", TokenType::DoublePlus },
|
{ "++", TokenType::DoublePlus },
|
||||||
{ "--", TokenType::DoubleMinus },
|
{ "--", TokenType::DoubleMinus },
|
||||||
{ "==", TokenType::DoubleEqual },
|
{ "==", TokenType::DoubleEqual },
|
||||||
@ -77,6 +79,9 @@ string _debug_get_token_type_name(TokenType type) {
|
|||||||
case TokenType::Else: return "Else";
|
case TokenType::Else: return "Else";
|
||||||
case TokenType::While: return "While";
|
case TokenType::While: return "While";
|
||||||
case TokenType::For: return "For";
|
case TokenType::For: return "For";
|
||||||
|
case TokenType::Break: return "Break";
|
||||||
|
case TokenType::Continue: return "Continue";
|
||||||
|
case TokenType::Comma: return "Comma";
|
||||||
default: return "Unknown";
|
default: return "Unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,6 +177,12 @@ void _debug_print_token(Token token) {
|
|||||||
case TokenType::For:
|
case TokenType::For:
|
||||||
cout << "For";
|
cout << "For";
|
||||||
break;
|
break;
|
||||||
|
case TokenType::Break:
|
||||||
|
cout << "Break";
|
||||||
|
break;
|
||||||
|
case TokenType::Continue:
|
||||||
|
cout << "Continue";
|
||||||
|
break;
|
||||||
case TokenType::Comma:
|
case TokenType::Comma:
|
||||||
cout << "Comma";
|
cout << "Comma";
|
||||||
break;
|
break;
|
||||||
|
@ -11,7 +11,7 @@ int main() {
|
|||||||
|
|
||||||
/* All tokens */
|
/* All tokens */
|
||||||
vector<string> inputs = {
|
vector<string> inputs = {
|
||||||
"int", "a", "=", "x", "++", "--", "==", "&&", "||", "<", ">", "<=", ">=", "!=", "!", "*", "/", "%", "=", ";", "(", ")", "{", "}", "if", "else", "while", "for", ","
|
"int", "a", "=", "x", "++", "--", "==", "&&", "||", "<", ">", "<=", ">=", "!=", "!", "*", "/", "%", "=", ";", "(", ")", "{", "}", "if", "else", "while", "for", "break", "continue", ","
|
||||||
};
|
};
|
||||||
|
|
||||||
vector<TokenType> expectedTypes = {
|
vector<TokenType> expectedTypes = {
|
||||||
@ -21,7 +21,7 @@ int main() {
|
|||||||
TokenType::Not, TokenType::Star, TokenType::Slash, TokenType::Percent, TokenType::Equal,
|
TokenType::Not, TokenType::Star, TokenType::Slash, TokenType::Percent, TokenType::Equal,
|
||||||
TokenType::Semicolon, TokenType::LParenthese, TokenType::RParenthese, TokenType::LCurlyBracket,
|
TokenType::Semicolon, TokenType::LParenthese, TokenType::RParenthese, TokenType::LCurlyBracket,
|
||||||
TokenType::RCurlyBracket, TokenType::If, TokenType::Else, TokenType::While, TokenType::For,
|
TokenType::RCurlyBracket, TokenType::If, TokenType::Else, TokenType::While, TokenType::For,
|
||||||
TokenType::Comma
|
TokenType::Break, TokenType::Continue, TokenType::Comma
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < inputs.size(); i++) {
|
for (size_t i = 0; i < inputs.size(); i++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user