mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
User-defined operators: Parsing and grammar
This commit is contained in:
parent
9a36438441
commit
9445483d60
@ -311,11 +311,31 @@ errorDefinition:
|
|||||||
LParen (parameters+=errorParameter (Comma parameters+=errorParameter)*)? RParen
|
LParen (parameters+=errorParameter (Comma parameters+=errorParameter)*)? RParen
|
||||||
Semicolon;
|
Semicolon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operators that users are allowed to implement for some types with `using for`.
|
||||||
|
*/
|
||||||
|
userDefinableOperator:
|
||||||
|
BitAnd
|
||||||
|
| BitNot
|
||||||
|
| BitOr
|
||||||
|
| BitXor
|
||||||
|
| Add
|
||||||
|
| Div
|
||||||
|
| Mod
|
||||||
|
| Mul
|
||||||
|
| Sub
|
||||||
|
| Equal
|
||||||
|
| GreaterThan
|
||||||
|
| GreaterThanOrEqual
|
||||||
|
| LessThan
|
||||||
|
| LessThanOrEqual
|
||||||
|
| NotEqual;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Using directive to attach library functions and free functions to types.
|
* Using directive to attach library functions and free functions to types.
|
||||||
* Can occur within contracts and libraries and at the file level.
|
* Can occur within contracts and libraries and at the file level.
|
||||||
*/
|
*/
|
||||||
usingDirective: Using (identifierPath | (LBrace identifierPath (Comma identifierPath)* RBrace)) For (Mul | typeName) Global? Semicolon;
|
usingDirective: Using (identifierPath | (LBrace identifierPath (As userDefinableOperator)? (Comma identifierPath (As userDefinableOperator)?)* RBrace)) For (Mul | typeName) Global? Semicolon;
|
||||||
/**
|
/**
|
||||||
* A type name can be an elementary type, a function type, a mapping type, a user-defined type
|
* A type name can be an elementary type, a function type, a mapping type, a user-defined type
|
||||||
* (e.g. a contract or struct) or an array type.
|
* (e.g. a contract or struct) or an array type.
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include <libsolidity/parsing/Parser.h>
|
#include <libsolidity/parsing/Parser.h>
|
||||||
|
|
||||||
|
#include <libsolidity/ast/UserDefinableOperators.h>
|
||||||
#include <libsolidity/interface/Version.h>
|
#include <libsolidity/interface/Version.h>
|
||||||
#include <libyul/AST.h>
|
#include <libyul/AST.h>
|
||||||
#include <libyul/AsmParser.h>
|
#include <libyul/AsmParser.h>
|
||||||
@ -976,6 +977,7 @@ ASTPointer<UsingForDirective> Parser::parseUsingDirective()
|
|||||||
expectToken(Token::Using);
|
expectToken(Token::Using);
|
||||||
|
|
||||||
vector<ASTPointer<IdentifierPath>> functions;
|
vector<ASTPointer<IdentifierPath>> functions;
|
||||||
|
vector<optional<Token>> operators;
|
||||||
bool const usesBraces = m_scanner->currentToken() == Token::LBrace;
|
bool const usesBraces = m_scanner->currentToken() == Token::LBrace;
|
||||||
if (usesBraces)
|
if (usesBraces)
|
||||||
{
|
{
|
||||||
@ -983,12 +985,35 @@ ASTPointer<UsingForDirective> Parser::parseUsingDirective()
|
|||||||
{
|
{
|
||||||
advance();
|
advance();
|
||||||
functions.emplace_back(parseIdentifierPath());
|
functions.emplace_back(parseIdentifierPath());
|
||||||
|
if (m_scanner->currentToken() == Token::As)
|
||||||
|
{
|
||||||
|
advance();
|
||||||
|
Token operator_ = m_scanner->currentToken();
|
||||||
|
if (!util::contains(userDefinableOperators, operator_))
|
||||||
|
{
|
||||||
|
parserError(
|
||||||
|
4403_error,
|
||||||
|
fmt::format(
|
||||||
|
"Not a user-definable operator: {}. Only the following operators can be user-defined: {}",
|
||||||
|
(!m_scanner->currentLiteral().empty() ? m_scanner->currentLiteral() : string(TokenTraits::toString(operator_))),
|
||||||
|
util::joinHumanReadable(userDefinableOperators | ranges::views::transform([](Token _t) { return string{TokenTraits::toString(_t)}; }))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
operators.emplace_back(operator_);
|
||||||
|
advance();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
operators.emplace_back(nullopt);
|
||||||
}
|
}
|
||||||
while (m_scanner->currentToken() == Token::Comma);
|
while (m_scanner->currentToken() == Token::Comma);
|
||||||
expectToken(Token::RBrace);
|
expectToken(Token::RBrace);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
functions.emplace_back(parseIdentifierPath());
|
functions.emplace_back(parseIdentifierPath());
|
||||||
|
operators.emplace_back(nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
ASTPointer<TypeName> typeName;
|
ASTPointer<TypeName> typeName;
|
||||||
expectToken(Token::For);
|
expectToken(Token::For);
|
||||||
@ -1004,7 +1029,7 @@ ASTPointer<UsingForDirective> Parser::parseUsingDirective()
|
|||||||
}
|
}
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
expectToken(Token::Semicolon);
|
expectToken(Token::Semicolon);
|
||||||
return nodeFactory.createNode<UsingForDirective>(std::move(functions), usesBraces, typeName, global);
|
return nodeFactory.createNode<UsingForDirective>(std::move(functions), std::move(operators), usesBraces, typeName, global);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<ModifierInvocation> Parser::parseModifierInvocation()
|
ASTPointer<ModifierInvocation> Parser::parseModifierInvocation()
|
||||||
|
Loading…
Reference in New Issue
Block a user