Expressions in brackets
This commit is contained in:
@@ -24,6 +24,7 @@ namespace Solstice {
|
|||||||
{")", TT::CloseParen},
|
{")", TT::CloseParen},
|
||||||
{"<", TT::OpenSpiky},
|
{"<", TT::OpenSpiky},
|
||||||
{">", TT::CloseSpiky},
|
{">", TT::CloseSpiky},
|
||||||
|
{",", TT::Comma},
|
||||||
|
|
||||||
{"+", TT::Math_Add},
|
{"+", TT::Math_Add},
|
||||||
{"-", TT::Math_Subtract},
|
{"-", TT::Math_Subtract},
|
||||||
@@ -251,6 +252,7 @@ namespace Solstice {
|
|||||||
case '+':
|
case '+':
|
||||||
case '*':
|
case '*':
|
||||||
case '/':
|
case '/':
|
||||||
|
case ',':
|
||||||
{
|
{
|
||||||
if (!buf.empty()) {
|
if (!buf.empty()) {
|
||||||
output.push_back(processToken(buf));
|
output.push_back(processToken(buf));
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ namespace Solstice {
|
|||||||
CloseParen,
|
CloseParen,
|
||||||
OpenSpiky,
|
OpenSpiky,
|
||||||
CloseSpiky,
|
CloseSpiky,
|
||||||
|
Comma,
|
||||||
NewLine,
|
NewLine,
|
||||||
|
|
||||||
// other
|
// other
|
||||||
|
|||||||
16
src/main.cpp
16
src/main.cpp
@@ -1,20 +1,14 @@
|
|||||||
#include "lexer/lexer.hpp"
|
#include "lexer/lexer.hpp"
|
||||||
#include "parser/parser.hpp"
|
#include "parser/parser.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
try {
|
Solstice::Lexer lexer{"(2 + 2) / 5"};
|
||||||
Solstice::Lexer lexer{"2 + 2 / 5"};
|
auto lexed = lexer.lex();
|
||||||
auto lexed = lexer.lex();
|
|
||||||
|
|
||||||
Solstice::Parser parser{lexed};
|
Solstice::Parser parser{lexed};
|
||||||
auto parsed = parser.parse();
|
auto parsed = parser.parse();
|
||||||
std::cout << parsed << std::endl;
|
std::cout << parsed << std::endl;
|
||||||
|
|
||||||
} catch (const std::runtime_error& e) {
|
|
||||||
std::cout << e.what() << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ namespace Solstice {
|
|||||||
return "Literal";
|
return "Literal";
|
||||||
case NodeType::Identifier:
|
case NodeType::Identifier:
|
||||||
return "Identifier";
|
return "Identifier";
|
||||||
|
case NodeType::Expression:
|
||||||
|
return "Expression";
|
||||||
|
case NodeType::Tuple:
|
||||||
|
return "Tuple";
|
||||||
case NodeType::FunctionBind:
|
case NodeType::FunctionBind:
|
||||||
return "FunctionBind";
|
return "FunctionBind";
|
||||||
case NodeType::Bind:
|
case NodeType::Bind:
|
||||||
@@ -115,17 +119,19 @@ namespace Solstice {
|
|||||||
return input[current++];
|
return input[current++];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Node> Parser::getPreviousNode(Node& parent) {
|
std::optional<Node> Parser::getPreviousNode(Node& parent, bool popBack) {
|
||||||
if (parent.children.empty()) {
|
if (parent.children.empty()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
Node node = parent.children[parent.children.size() - 1];
|
Node node = parent.children[parent.children.size() - 1];
|
||||||
parent.children.pop_back();
|
if (popBack) {
|
||||||
|
parent.children.pop_back();
|
||||||
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node Parser::parseExpr(TT type) {
|
Node Parser::parseExpr(TT type) {
|
||||||
auto left = getPreviousNode(output);
|
auto left = getPreviousNode(*context);
|
||||||
if (!left.has_value()) {
|
if (!left.has_value()) {
|
||||||
throw std::runtime_error("Expecting expression on left of expression");
|
throw std::runtime_error("Expecting expression on left of expression");
|
||||||
}
|
}
|
||||||
@@ -158,6 +164,57 @@ namespace Solstice {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node Parser::parseOpenParen() {
|
||||||
|
Node node{NodeType::Expression};
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
auto next = peek();
|
||||||
|
if (!next.has_value()) {
|
||||||
|
throw std::runtime_error("unclosed parens");
|
||||||
|
}
|
||||||
|
if (next->type == TT::CloseParen) {
|
||||||
|
consume();
|
||||||
|
if (node.children.size() != 1) {
|
||||||
|
node.type = NodeType::Tuple;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node elem{NodeType::Root};
|
||||||
|
Node* prevContext = context;
|
||||||
|
context = &elem;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
auto t = peek();
|
||||||
|
if (!t.has_value() || t->type == TT::CloseParen || t->type == TT::Comma) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto n = parseOneNode(Precedence::NewLine);
|
||||||
|
if (!n.has_value()) break;
|
||||||
|
elem.children.push_back(*n);
|
||||||
|
}
|
||||||
|
|
||||||
|
context = prevContext;
|
||||||
|
|
||||||
|
if (elem.children.empty()) {
|
||||||
|
throw std::runtime_error("expecting expression in parens");
|
||||||
|
}
|
||||||
|
node.children.push_back(elem.children.back());
|
||||||
|
|
||||||
|
auto sep = peek();
|
||||||
|
if (!sep.has_value()) {
|
||||||
|
throw std::runtime_error("unclosed parens");
|
||||||
|
}
|
||||||
|
if (sep->type == TT::Comma) {
|
||||||
|
consume();
|
||||||
|
} else if (sep->type != TT::CloseParen) {
|
||||||
|
throw std::runtime_error("expecting comma between expressions in parens");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
Node Parser::parseLiteral() {
|
Node Parser::parseLiteral() {
|
||||||
auto current = peek(-1);
|
auto current = peek(-1);
|
||||||
if (!current.has_value()) {
|
if (!current.has_value()) {
|
||||||
@@ -190,14 +247,15 @@ namespace Solstice {
|
|||||||
return Precedence::Root;
|
return Precedence::Root;
|
||||||
case NodeType::Literal:
|
case NodeType::Literal:
|
||||||
case NodeType::Identifier:
|
case NodeType::Identifier:
|
||||||
|
case NodeType::Lambda:
|
||||||
|
case NodeType::FunctionCall:
|
||||||
|
case NodeType::Expression:
|
||||||
|
case NodeType::Tuple:
|
||||||
return Precedence::Identifier;
|
return Precedence::Identifier;
|
||||||
case NodeType::FunctionBind:
|
case NodeType::FunctionBind:
|
||||||
case NodeType::Bind:
|
case NodeType::Bind:
|
||||||
case NodeType::Set:
|
case NodeType::Set:
|
||||||
return Precedence::Set;
|
return Precedence::Set;
|
||||||
case NodeType::Lambda:
|
|
||||||
case NodeType::FunctionCall:
|
|
||||||
return Precedence::Identifier;
|
|
||||||
case NodeType::Add:
|
case NodeType::Add:
|
||||||
case NodeType::Subtract:
|
case NodeType::Subtract:
|
||||||
return Precedence::Add;
|
return Precedence::Add;
|
||||||
@@ -214,42 +272,6 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Precedence Parser::getTokenPrecedence(const Token& token) {
|
Precedence Parser::getTokenPrecedence(const Token& token) {
|
||||||
switch (token.type) {
|
|
||||||
case TT::OpenCurly: {
|
|
||||||
braceCount++;
|
|
||||||
return Precedence::Other;
|
|
||||||
}
|
|
||||||
case TT::CloseCurly: {
|
|
||||||
braceCount--;
|
|
||||||
return Precedence::Other;
|
|
||||||
}
|
|
||||||
case TT::OpenSpiky: {
|
|
||||||
spikyBracketCount++;
|
|
||||||
return Precedence::Other;
|
|
||||||
}
|
|
||||||
case TT::CloseSpiky: {
|
|
||||||
spikyBracketCount--;
|
|
||||||
return Precedence::Other;
|
|
||||||
}
|
|
||||||
case TT::OpenParen: {
|
|
||||||
bracketCount++;
|
|
||||||
return Precedence::Other;
|
|
||||||
}
|
|
||||||
case TT::CloseParen: {
|
|
||||||
bracketCount--;
|
|
||||||
return Precedence::Other;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
if (braceCount > 0) {
|
|
||||||
return Precedence::Other;
|
|
||||||
}
|
|
||||||
if (bracketCount > 0) {
|
|
||||||
return Precedence::Other;
|
|
||||||
}
|
|
||||||
if (spikyBracketCount > 0) {
|
|
||||||
return Precedence::Other;
|
|
||||||
}
|
|
||||||
switch (token.type) {
|
switch (token.type) {
|
||||||
case TT::None:
|
case TT::None:
|
||||||
case TT::Kw_Type:
|
case TT::Kw_Type:
|
||||||
@@ -298,6 +320,16 @@ namespace Solstice {
|
|||||||
case TT::Math_Multiply:
|
case TT::Math_Multiply:
|
||||||
case TT::Math_Divide:
|
case TT::Math_Divide:
|
||||||
return parseExpr(next->type);
|
return parseExpr(next->type);
|
||||||
|
case TT::OpenParen:
|
||||||
|
return parseOpenParen();
|
||||||
|
|
||||||
|
// stuff that causes errors
|
||||||
|
case TT::CloseParen:
|
||||||
|
throw std::runtime_error("Extra closing paren");
|
||||||
|
case TT::CloseSpiky:
|
||||||
|
throw std::runtime_error("Extra closing angle bracket");
|
||||||
|
case TT::CloseCurly:
|
||||||
|
throw std::runtime_error("Extra closing curly brace");
|
||||||
}
|
}
|
||||||
throw std::runtime_error("FIXME: unimplemented parsing case");
|
throw std::runtime_error("FIXME: unimplemented parsing case");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
namespace Solstice {
|
namespace Solstice {
|
||||||
|
|
||||||
enum class NodeType {
|
enum class NodeType {
|
||||||
Root, Literal, Identifier,
|
Root, Literal, Identifier, Expression, Tuple,
|
||||||
FunctionBind, Bind, Set,
|
FunctionBind, Bind, Set,
|
||||||
Lambda, FunctionCall,
|
Lambda, FunctionCall,
|
||||||
Add, Subtract, Multiply, Divide,
|
Add, Subtract, Multiply, Divide,
|
||||||
@@ -58,14 +58,12 @@ namespace Solstice {
|
|||||||
|
|
||||||
size_t current = 0;
|
size_t current = 0;
|
||||||
|
|
||||||
size_t braceCount = 0;
|
|
||||||
size_t bracketCount = 0;
|
|
||||||
size_t spikyBracketCount = 0;
|
|
||||||
|
|
||||||
std::optional<Token> peek(int64_t ahead = 0);
|
std::optional<Token> peek(int64_t ahead = 0);
|
||||||
std::optional<Token> consume();
|
std::optional<Token> consume();
|
||||||
|
|
||||||
std::optional<Node> getPreviousNode(Node& parent);
|
std::optional<Node> getPreviousNode(Node& parent, bool popBack = true);
|
||||||
|
|
||||||
|
Node* context = &output;
|
||||||
|
|
||||||
Node parseKwType();
|
Node parseKwType();
|
||||||
|
|
||||||
@@ -83,9 +81,6 @@ namespace Solstice {
|
|||||||
Node parseOpenCurly();
|
Node parseOpenCurly();
|
||||||
Node parseOpenParen();
|
Node parseOpenParen();
|
||||||
Node parseOpenSpiky();
|
Node parseOpenSpiky();
|
||||||
Node parseCloseCurly();
|
|
||||||
Node parseCloseParen();
|
|
||||||
Node parseCloseSpiky();
|
|
||||||
Node parseNewLine();
|
Node parseNewLine();
|
||||||
|
|
||||||
Node parseLiteral();
|
Node parseLiteral();
|
||||||
|
|||||||
Reference in New Issue
Block a user