diff --git a/src/Lib/Script/Ast/IrOption.cc b/src/Lib/Script/Ast/IrOption.cc index beabd87a987d5ecf2973b890f6fd00be55fb2959..78aec6976e6893923b72cea76ccca04a62d2a82c 100644 --- a/src/Lib/Script/Ast/IrOption.cc +++ b/src/Lib/Script/Ast/IrOption.cc @@ -1,9 +1,10 @@ #include "IrOption.hh" +#include "Lib/Script/FrontEnd/Lexer.hh" namespace Vivy::Script { IrOption::IrOption(StrV nameInModule) noexcept - : shapeName(nameInModule) + : moduleName(nameInModule) { } @@ -32,12 +33,6 @@ IrOption::toString() const noexcept return "IrOption"; } -void -IrOption::parse(std::vector<Token> *) -{ - throw std::logic_error("IrOption"); -} - IrOption * IrOption::empty() noexcept { @@ -90,4 +85,50 @@ IrOption::match(const std::vector<IrOption *> &others) const noexcept return this->match(shape); }); } + +void +IrOption::parse(std::vector<Token> *tokens) +{ + const Token firstDeclToken = getInnerTokenOpt(tokenListPop(tokens)); + firstDeclToken.assertTypeSimple(TOKEN_OPTION); + + const Token shapeNameToken = getInnerTokenOpt(tokenListPop(tokens)); + shapeNameToken.assertType(Token::Type::QNAME); + shapeName = shapeNameToken.asQName(); + + getInnerTokenOpt(tokenListPop(tokens)).assertTypeSimple(TOKEN_CURLY_BRACKET_LEFT); + + if (getInnerTokenOpt(tokenListPeek(tokens)).isSimple(TOKEN_CURLY_BRACKET_RIGHT)) { + throw std::runtime_error(firstDeclToken.location().toString() + + ": Empty option groups are not supported!"); + } + + /* ... | name : type = value */ + while (getInnerTokenOpt(tokenListPeek(tokens)).isQName()) { + const Token fieldNameToken = getInnerTokenOpt(tokenListPop(tokens)); + getInnerTokenOpt(tokenListPop(tokens)).assertTypeSimple(TOKEN_COL); + const Token typeNameToken = getInnerTokenOpt(tokenListPop(tokens)); + typeNameToken.assertType(Token::Type::SIMPLE); + getInnerTokenOpt(tokenListPop(tokens)).assertTypeSimple(TOKEN_ASSIGN); + const Token defaultValueToken = getInnerTokenOpt(tokenListPop(tokens)); + + std::cerr << "Found option: " << shapeName.toStdString() << "." + << fieldNameToken.asQName().toStdString() << " : " + << typeNameToken.asSimple().toStdString() << " = " << defaultValueToken.toString() + << ";\n"; + + const Token continuationToken = getInnerTokenOpt(tokenListPop(tokens)); + if (continuationToken.isSimple(TOKEN_COMMA)) + continue; + else if (continuationToken.isSimple(TOKEN_CURLY_BRACKET_RIGHT)) + break; + else { + throw std::runtime_error( + firstDeclToken.location().toString() + + ": invalid option declaration, to separate fields in the option you " + "must use a comma. Found unexpected token: " + + continuationToken.toString()); + } + } +} } diff --git a/src/Lib/Script/Ast/IrOption.hh b/src/Lib/Script/Ast/IrOption.hh index c7389bb6a190e8746beb43181673eef7225ab82f..6e4fae6d57bbc1b27a2ddf178ccc2527929ad764 100644 --- a/src/Lib/Script/Ast/IrOption.hh +++ b/src/Lib/Script/Ast/IrOption.hh @@ -22,8 +22,9 @@ class IrOption final : public IrElement { const Content content; }; + const StrV moduleName; bool optionIsEmpty = true; - const StrV shapeName; + StrV shapeName = STRV_NULL; std::vector<ShapeElement *> shapes; void addShape(const IrModule *module, const ShapeElement::Content &content) noexcept;