diff options
author | chriseth <c@ethdev.com> | 2014-12-01 19:43:32 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2014-12-01 19:43:32 +0800 |
commit | 3fc2708d657525162567b663a07cf8cb5b1c59aa (patch) | |
tree | c55b76eaef68afea87f2318e1ddbf1bdfe1fee2d | |
parent | 4b0d949df3cb006773aabaf34e638ab4639e7044 (diff) | |
parent | 4b845073105bc76793a72a092630fc3bc5077882 (diff) | |
download | dexon-solidity-3fc2708d657525162567b663a07cf8cb5b1c59aa.tar dexon-solidity-3fc2708d657525162567b663a07cf8cb5b1c59aa.tar.gz dexon-solidity-3fc2708d657525162567b663a07cf8cb5b1c59aa.tar.bz2 dexon-solidity-3fc2708d657525162567b663a07cf8cb5b1c59aa.tar.lz dexon-solidity-3fc2708d657525162567b663a07cf8cb5b1c59aa.tar.xz dexon-solidity-3fc2708d657525162567b663a07cf8cb5b1c59aa.tar.zst dexon-solidity-3fc2708d657525162567b663a07cf8cb5b1c59aa.zip |
Merge pull request #545 from LefterisJP/sol_com_in_ast
Solidity function AST nodes get documentation attribute
-rw-r--r-- | AST.h | 27 | ||||
-rw-r--r-- | Parser.cpp | 9 | ||||
-rw-r--r-- | Scanner.cpp | 93 | ||||
-rw-r--r-- | Scanner.h | 32 |
4 files changed, 109 insertions, 52 deletions
@@ -173,14 +173,21 @@ private: class FunctionDefinition: public Declaration { public: - FunctionDefinition(Location const& _location, ASTPointer<ASTString> const& _name, bool _isPublic, - ASTPointer<ParameterList> const& _parameters, - bool _isDeclaredConst, - ASTPointer<ParameterList> const& _returnParameters, - ASTPointer<Block> const& _body): - Declaration(_location, _name), m_isPublic(_isPublic), m_parameters(_parameters), - m_isDeclaredConst(_isDeclaredConst), m_returnParameters(_returnParameters), - m_body(_body) {} + FunctionDefinition(Location const& _location, ASTPointer<ASTString> const& _name, + bool _isPublic, + ASTPointer<ASTString> const& _documentation, + ASTPointer<ParameterList> const& _parameters, + bool _isDeclaredConst, + ASTPointer<ParameterList> const& _returnParameters, + ASTPointer<Block> const& _body): + Declaration(_location, _name), m_isPublic(_isPublic), + m_parameters(_parameters), + m_isDeclaredConst(_isDeclaredConst), + m_returnParameters(_returnParameters), + m_body(_body), + m_documentation(_documentation) + {} + virtual void accept(ASTVisitor& _visitor) override; bool isPublic() const { return m_isPublic; } @@ -190,6 +197,9 @@ public: std::vector<ASTPointer<VariableDeclaration>> const& getReturnParameters() const { return m_returnParameters->getParameters(); } ASTPointer<ParameterList> const& getReturnParameterList() const { return m_returnParameters; } Block& getBody() { return *m_body; } + /// @return A shared pointer of an ASTString. + /// Can contain a nullptr in which case indicates absence of documentation + ASTPointer<ASTString> const& getDocumentation() { return m_documentation; } void addLocalVariable(VariableDeclaration const& _localVariable) { m_localVariables.push_back(&_localVariable); } std::vector<VariableDeclaration const*> const& getLocalVariables() const { return m_localVariables; } @@ -203,6 +213,7 @@ private: bool m_isDeclaredConst; ASTPointer<ParameterList> m_returnParameters; ASTPointer<Block> m_body; + ASTPointer<ASTString> m_documentation; std::vector<VariableDeclaration const*> m_localVariables; }; @@ -117,6 +117,10 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition() ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic) { ASTNodeFactory nodeFactory(*this); + ASTPointer<ASTString> docstring; + if (m_scanner->getCurrentCommentLiteral() != "") + docstring = std::make_shared<ASTString>(m_scanner->getCurrentCommentLiteral()); + expectToken(Token::FUNCTION); ASTPointer<ASTString> name(expectIdentifierToken()); ASTPointer<ParameterList> parameters(parseParameterList()); @@ -142,8 +146,9 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic) } ASTPointer<Block> block = parseBlock(); nodeFactory.setEndPositionFromNode(block); - return nodeFactory.createNode<FunctionDefinition>(name, _isPublic, parameters, - isDeclaredConst, returnParameters, block); + return nodeFactory.createNode<FunctionDefinition>(name, _isPublic, docstring, + parameters, + isDeclaredConst, returnParameters, block); } ASTPointer<StructDefinition> Parser::parseStructDefinition() diff --git a/Scanner.cpp b/Scanner.cpp index dd18a320..4ffc2223 100644 --- a/Scanner.cpp +++ b/Scanner.cpp @@ -102,18 +102,55 @@ int hexValue(char c) } } // end anonymous namespace + + +/// Scoped helper for literal recording. Automatically drops the literal +/// if aborting the scanning before it's complete. +enum LiteralType { + LITERAL_TYPE_STRING, + LITERAL_TYPE_NUMBER, // not really different from string type in behaviour + LITERAL_TYPE_COMMENT +}; + +class LiteralScope +{ +public: + explicit LiteralScope(Scanner* _self, enum LiteralType _type): m_type(_type) + , m_scanner(_self) + , m_complete(false) + { + if (_type == LITERAL_TYPE_COMMENT) + m_scanner->m_nextSkippedComment.literal.clear(); + else + m_scanner->m_nextToken.literal.clear(); + } + ~LiteralScope() + { + if (!m_complete) + { + if (m_type == LITERAL_TYPE_COMMENT) + m_scanner->m_nextSkippedComment.literal.clear(); + else + m_scanner->m_nextToken.literal.clear(); + } + } + void complete() { m_complete = true; } + +private: + enum LiteralType m_type; + Scanner* m_scanner; + bool m_complete; +}; // end of LiteralScope class + + void Scanner::reset(CharStream const& _source) { - bool foundDocComment; m_source = _source; m_char = m_source.get(); skipWhitespace(); - foundDocComment = scanToken(); + scanToken(); - // special version of Scanner:next() taking the previous scanToken() result into account - m_currentToken = m_nextToken; - if (scanToken() || foundDocComment) - m_skippedComment = m_nextSkippedComment; + next(); } @@ -142,8 +179,9 @@ BOOST_STATIC_ASSERT(Token::NUM_TOKENS <= 0x100); Token::Value Scanner::next() { m_currentToken = m_nextToken; - if (scanToken()) - m_skippedComment = m_nextSkippedComment; + m_skippedComment = m_nextSkippedComment; + scanToken(); + return m_currentToken.token; } @@ -180,10 +218,26 @@ Token::Value Scanner::skipSingleLineComment() /// For the moment this function simply consumes a single line triple slash doc comment Token::Value Scanner::scanDocumentationComment() { - LiteralScope literal(this); + LiteralScope literal(this, LITERAL_TYPE_COMMENT); advance(); //consume the last '/' - while (!isSourcePastEndOfInput() && !isLineTerminator(m_char)) + while (!isSourcePastEndOfInput()) { + if (isLineTerminator(m_char)) + { + // check if next line is also a documentation comment + skipWhitespace(); + if (!m_source.isPastEndOfInput(3) && + m_source.get(0) == '/' && + m_source.get(1) == '/' && + m_source.get(2) == '/') + { + addCommentLiteralChar('\n'); + m_char = m_source.advanceAndGet(3); + } + else + break; // next line is not a documentation comment, we are done + + } addCommentLiteralChar(m_char); advance(); } @@ -214,10 +268,10 @@ Token::Value Scanner::skipMultiLineComment() return Token::ILLEGAL; } -bool Scanner::scanToken() +void Scanner::scanToken() { - bool foundDocComment = false; m_nextToken.literal.clear(); + m_nextSkippedComment.literal.clear(); Token::Value token; do { @@ -329,7 +383,6 @@ bool Scanner::scanToken() m_nextSkippedComment.location.end = getSourcePos(); m_nextSkippedComment.token = comment; token = Token::WHITESPACE; - foundDocComment = true; } else token = skipSingleLineComment(); @@ -425,8 +478,6 @@ bool Scanner::scanToken() while (token == Token::WHITESPACE); m_nextToken.location.end = getSourcePos(); m_nextToken.token = token; - - return foundDocComment; } bool Scanner::scanEscape() @@ -474,7 +525,7 @@ Token::Value Scanner::scanString() { char const quote = m_char; advance(); // consume quote - LiteralScope literal(this); + LiteralScope literal(this, LITERAL_TYPE_STRING); while (m_char != quote && !isSourcePastEndOfInput() && !isLineTerminator(m_char)) { char c = m_char; @@ -505,7 +556,7 @@ void Scanner::scanDecimalDigits() Token::Value Scanner::scanNumber(char _charSeen) { enum { DECIMAL, HEX, BINARY } kind = DECIMAL; - LiteralScope literal(this); + LiteralScope literal(this, LITERAL_TYPE_NUMBER); if (_charSeen == '.') { // we have already seen a decimal point of the float @@ -758,7 +809,7 @@ Token::Value Scanner::scanIdentifierOrKeyword() { if (asserts(isIdentifierStart(m_char))) BOOST_THROW_EXCEPTION(InternalCompilerError()); - LiteralScope literal(this); + LiteralScope literal(this, LITERAL_TYPE_STRING); addLiteralCharAndAdvance(); // Scan the rest of the identifier characters. while (isIdentifierPart(m_char)) @@ -767,14 +818,14 @@ Token::Value Scanner::scanIdentifierOrKeyword() return KeywordOrIdentifierToken(m_nextToken.literal); } -char CharStream::advanceAndGet() +char CharStream::advanceAndGet(size_t _chars) { if (isPastEndOfInput()) return 0; - ++m_pos; + m_pos += _chars; if (isPastEndOfInput()) return 0; - return get(); + return m_source[m_pos]; } char CharStream::rollback(size_t _amount) @@ -74,9 +74,9 @@ public: CharStream(): m_pos(0) {} explicit CharStream(std::string const& _source): m_source(_source), m_pos(0) {} int getPos() const { return m_pos; } - bool isPastEndOfInput() const { return m_pos >= m_source.size(); } - char get() const { return m_source[m_pos]; } - char advanceAndGet(); + bool isPastEndOfInput(size_t _charsForward = 0) const { return (m_pos + _charsForward) >= m_source.size(); } + char get(size_t _charsForward = 0) const { return m_source[m_pos + _charsForward]; } + char advanceAndGet(size_t _chars=1); char rollback(size_t _amount); ///@{ @@ -93,22 +93,11 @@ private: }; + class Scanner { + friend class LiteralScope; public: - /// Scoped helper for literal recording. Automatically drops the literal - /// if aborting the scanning before it's complete. - class LiteralScope - { - public: - explicit LiteralScope(Scanner* self): m_scanner(self), m_complete(false) { m_scanner->startNewLiteral(); } - ~LiteralScope() { if (!m_complete) m_scanner->dropLiteral(); } - void complete() { m_complete = true; } - - private: - Scanner* m_scanner; - bool m_complete; - }; Scanner() { reset(CharStream()); } explicit Scanner(CharStream const& _source) { reset(_source); } @@ -133,8 +122,12 @@ public: ///@{ ///@name Information about the current comment token + Location getCurrentCommentLocation() const { return m_skippedComment.location; } std::string const& getCurrentCommentLiteral() const { return m_skippedComment.literal; } + /// Called by the parser during FunctionDefinition parsing to clear the current comment + void clearCurrentCommentLiteral() { m_skippedComment.literal.clear(); } + ///@} ///@{ @@ -165,10 +158,8 @@ private: ///@{ ///@name Literal buffer support - inline void startNewLiteral() { m_nextToken.literal.clear(); } inline void addLiteralChar(char c) { m_nextToken.literal.push_back(c); } inline void addCommentLiteralChar(char c) { m_nextSkippedComment.literal.push_back(c); } - inline void dropLiteral() { m_nextToken.literal.clear(); } inline void addLiteralCharAndAdvance() { addLiteralChar(m_char); advance(); } ///@} @@ -181,9 +172,8 @@ private: bool scanHexByte(char& o_scannedByte); - /// Scans a single Solidity token. Returns true if the scanned token was - /// a skipped documentation comment. False in all other cases. - bool scanToken(); + /// Scans a single Solidity token. + void scanToken(); /// Skips all whitespace and @returns true if something was skipped. bool skipWhitespace(); |