Browse Source

Import directive.

cl-refactor
Christian 10 years ago
parent
commit
8621949067
  1. 69
      libsolidity/AST.cpp
  2. 34
      libsolidity/AST.h
  3. 2
      libsolidity/ASTForward.h
  4. 9
      libsolidity/ASTPrinter.cpp
  5. 3
      libsolidity/ASTPrinter.h
  6. 4
      libsolidity/ASTVisitor.h
  7. 87
      libsolidity/CompilerStack.cpp
  8. 5
      libsolidity/CompilerStack.h
  9. 43
      libsolidity/Parser.cpp
  10. 3
      libsolidity/Parser.h
  11. 2
      solc/main.cpp
  12. 26
      test/solidityCompiler.cpp
  13. 47
      test/solidityExpressionCompiler.cpp
  14. 11
      test/solidityNameAndTypeResolution.cpp
  15. 55
      test/solidityParser.cpp

69
libsolidity/AST.cpp

@ -33,6 +33,19 @@ namespace dev
namespace solidity namespace solidity
{ {
void SourceUnit::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))
listAccept(m_nodes, _visitor);
_visitor.endVisit(*this);
}
void ImportDirective::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void ContractDefinition::accept(ASTVisitor& _visitor) void ContractDefinition::accept(ASTVisitor& _visitor)
{ {
if (_visitor.visit(*this)) if (_visitor.visit(*this))
@ -57,34 +70,6 @@ void StructDefinition::checkValidityOfMembers()
checkRecursion(); checkRecursion();
} }
void StructDefinition::checkMemberTypes()
{
for (ASTPointer<VariableDeclaration> const& member: getMembers())
if (!member->getType()->canBeStored())
BOOST_THROW_EXCEPTION(member->createTypeError("Type cannot be used in struct."));
}
void StructDefinition::checkRecursion()
{
set<StructDefinition const*> definitionsSeen;
vector<StructDefinition const*> queue = {this};
while (!queue.empty())
{
StructDefinition const* def = queue.back();
queue.pop_back();
if (definitionsSeen.count(def))
BOOST_THROW_EXCEPTION(ParserError() << errinfo_sourceLocation(def->getLocation())
<< errinfo_comment("Recursive struct definition."));
definitionsSeen.insert(def);
for (ASTPointer<VariableDeclaration> const& member: def->getMembers())
if (member->getType()->getCategory() == Type::Category::STRUCT)
{
UserDefinedTypeName const& typeName = dynamic_cast<UserDefinedTypeName&>(*member->getTypeName());
queue.push_back(&dynamic_cast<StructDefinition const&>(*typeName.getReferencedDeclaration()));
}
}
}
void ParameterList::accept(ASTVisitor& _visitor) void ParameterList::accept(ASTVisitor& _visitor)
{ {
if (_visitor.visit(*this)) if (_visitor.visit(*this))
@ -312,6 +297,34 @@ vector<FunctionDefinition const*> ContractDefinition::getInterfaceFunctions() co
return exportedFunctions; return exportedFunctions;
} }
void StructDefinition::checkMemberTypes()
{
for (ASTPointer<VariableDeclaration> const& member: getMembers())
if (!member->getType()->canBeStored())
BOOST_THROW_EXCEPTION(member->createTypeError("Type cannot be used in struct."));
}
void StructDefinition::checkRecursion()
{
set<StructDefinition const*> definitionsSeen;
vector<StructDefinition const*> queue = {this};
while (!queue.empty())
{
StructDefinition const* def = queue.back();
queue.pop_back();
if (definitionsSeen.count(def))
BOOST_THROW_EXCEPTION(ParserError() << errinfo_sourceLocation(def->getLocation())
<< errinfo_comment("Recursive struct definition."));
definitionsSeen.insert(def);
for (ASTPointer<VariableDeclaration> const& member: def->getMembers())
if (member->getType()->getCategory() == Type::Category::STRUCT)
{
UserDefinedTypeName const& typeName = dynamic_cast<UserDefinedTypeName&>(*member->getTypeName());
queue.push_back(&dynamic_cast<StructDefinition const&>(*typeName.getReferencedDeclaration()));
}
}
}
void FunctionDefinition::checkTypeRequirements() void FunctionDefinition::checkTypeRequirements()
{ {
for (ASTPointer<VariableDeclaration> const& var: getParameters() + getReturnParameters()) for (ASTPointer<VariableDeclaration> const& var: getParameters() + getReturnParameters())

34
libsolidity/AST.h

@ -79,6 +79,40 @@ private:
Location m_location; Location m_location;
}; };
/**
* Source unit containing import directives and contract definitions.
*/
class SourceUnit: public ASTNode
{
public:
SourceUnit(Location const& _location, std::vector<ASTPointer<ASTNode>> const& _nodes):
ASTNode(_location), m_nodes(_nodes) {}
virtual void accept(ASTVisitor& _visitor) override;
std::vector<ASTPointer<ASTNode>> getNodes() const { return m_nodes; }
private:
std::vector<ASTPointer<ASTNode>> m_nodes;
};
/**
* Import directive for referencing other files / source objects.
*/
class ImportDirective: public ASTNode
{
public:
ImportDirective(Location const& _location, ASTPointer<ASTString> const& _url):
ASTNode(_location), m_url(_url) {}
virtual void accept(ASTVisitor& _visitor) override;
ASTString const& getURL() const { return *m_url; }
private:
ASTPointer<ASTString> m_url;
};
/** /**
* Abstract AST class for a declaration (contract, function, struct, variable). * Abstract AST class for a declaration (contract, function, struct, variable).
*/ */

2
libsolidity/ASTForward.h

@ -34,6 +34,8 @@ namespace solidity
{ {
class ASTNode; class ASTNode;
class SourceUnit;
class ImportDirective;
class Declaration; class Declaration;
class ContractDefinition; class ContractDefinition;
class StructDefinition; class StructDefinition;

9
libsolidity/ASTPrinter.cpp

@ -43,6 +43,13 @@ void ASTPrinter::print(ostream& _stream)
} }
bool ASTPrinter::visit(ImportDirective& _node)
{
writeLine("ImportDirective \"" + _node.getURL() + "\"");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(ContractDefinition& _node) bool ASTPrinter::visit(ContractDefinition& _node)
{ {
writeLine("ContractDefinition \"" + _node.getName() + "\""); writeLine("ContractDefinition \"" + _node.getName() + "\"");
@ -270,7 +277,7 @@ bool ASTPrinter::visit(Literal& _node)
return goDeeper(); return goDeeper();
} }
void ASTPrinter::endVisit(ASTNode&) void ASTPrinter::endVisit(ImportDirective&)
{ {
m_indentation--; m_indentation--;
} }

3
libsolidity/ASTPrinter.h

@ -42,6 +42,7 @@ public:
/// Output the string representation of the AST to _stream. /// Output the string representation of the AST to _stream.
void print(std::ostream& _stream); void print(std::ostream& _stream);
bool visit(ImportDirective& _node) override;
bool visit(ContractDefinition& _node) override; bool visit(ContractDefinition& _node) override;
bool visit(StructDefinition& _node) override; bool visit(StructDefinition& _node) override;
bool visit(ParameterList& _node) override; bool visit(ParameterList& _node) override;
@ -73,7 +74,7 @@ public:
bool visit(ElementaryTypeNameExpression& _node) override; bool visit(ElementaryTypeNameExpression& _node) override;
bool visit(Literal& _node) override; bool visit(Literal& _node) override;
void endVisit(ASTNode& _node) override; void endVisit(ImportDirective&) override;
void endVisit(ContractDefinition&) override; void endVisit(ContractDefinition&) override;
void endVisit(StructDefinition&) override; void endVisit(StructDefinition&) override;
void endVisit(ParameterList&) override; void endVisit(ParameterList&) override;

4
libsolidity/ASTVisitor.h

@ -42,6 +42,8 @@ class ASTVisitor
{ {
public: public:
virtual bool visit(ASTNode&) { return true; } virtual bool visit(ASTNode&) { return true; }
virtual bool visit(SourceUnit&) { return true; }
virtual bool visit(ImportDirective&) { return true; }
virtual bool visit(ContractDefinition&) { return true; } virtual bool visit(ContractDefinition&) { return true; }
virtual bool visit(StructDefinition&) { return true; } virtual bool visit(StructDefinition&) { return true; }
virtual bool visit(ParameterList&) { return true; } virtual bool visit(ParameterList&) { return true; }
@ -74,6 +76,8 @@ public:
virtual bool visit(Literal&) { return true; } virtual bool visit(Literal&) { return true; }
virtual void endVisit(ASTNode&) { } virtual void endVisit(ASTNode&) { }
virtual void endVisit(SourceUnit&) { }
virtual void endVisit(ImportDirective&) { }
virtual void endVisit(ContractDefinition&) { } virtual void endVisit(ContractDefinition&) { }
virtual void endVisit(StructDefinition&) { } virtual void endVisit(StructDefinition&) { }
virtual void endVisit(ParameterList&) { } virtual void endVisit(ParameterList&) { }

87
libsolidity/CompilerStack.cpp

@ -45,10 +45,14 @@ void CompilerStack::parse()
{ {
if (!m_scanner) if (!m_scanner)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Source not available.")); BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Source not available."));
m_contractASTNode = Parser().parse(m_scanner); m_sourceUnitASTNode = Parser().parse(m_scanner);
m_globalContext = make_shared<GlobalContext>(); m_globalContext = make_shared<GlobalContext>();
m_globalContext->setCurrentContract(*m_contractASTNode); for (ASTPointer<ASTNode> const& node: m_sourceUnitASTNode->getNodes())
NameAndTypeResolver(m_globalContext->getDeclarations()).resolveNamesAndTypes(*m_contractASTNode); if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
{
m_globalContext->setCurrentContract(*contract);
NameAndTypeResolver(m_globalContext->getDeclarations()).resolveNamesAndTypes(*contract);
}
m_parseSuccessful = true; m_parseSuccessful = true;
} }
@ -62,10 +66,16 @@ bytes const& CompilerStack::compile(bool _optimize)
{ {
if (!m_parseSuccessful) if (!m_parseSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
m_bytecode.clear(); //@todo returns only the last contract for now
m_compiler = make_shared<Compiler>(); for (ASTPointer<ASTNode> const& node: m_sourceUnitASTNode->getNodes())
m_compiler->compileContract(*m_contractASTNode, m_globalContext->getMagicVariables()); if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
return m_bytecode = m_compiler->getAssembledBytecode(_optimize); {
m_bytecode.clear();
m_compiler = make_shared<Compiler>();
m_compiler->compileContract(*contract, m_globalContext->getMagicVariables());
m_bytecode = m_compiler->getAssembledBytecode(_optimize);
}
return m_bytecode;
} }
bytes const& CompilerStack::compile(string const& _sourceCode, bool _optimize) bytes const& CompilerStack::compile(string const& _sourceCode, bool _optimize)
@ -87,40 +97,45 @@ string const& CompilerStack::getInterface()
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
if (m_interface.empty()) if (m_interface.empty())
{ {
stringstream interface; //@todo returns only the last contract for now
interface << '['; for (ASTPointer<ASTNode> const& node: m_sourceUnitASTNode->getNodes())
vector<FunctionDefinition const*> exportedFunctions = m_contractASTNode->getInterfaceFunctions(); if (ContractDefinition const* contract = dynamic_cast<ContractDefinition*>(node.get()))
unsigned functionsCount = exportedFunctions.size();
for (FunctionDefinition const* f: exportedFunctions)
{
auto streamVariables = [&](vector<ASTPointer<VariableDeclaration>> const& _vars)
{ {
unsigned varCount = _vars.size(); stringstream interface;
for (ASTPointer<VariableDeclaration> const& var: _vars) interface << '[';
vector<FunctionDefinition const*> exportedFunctions = contract->getInterfaceFunctions();
unsigned functionsCount = exportedFunctions.size();
for (FunctionDefinition const* f: exportedFunctions)
{ {
interface << "{" auto streamVariables = [&](vector<ASTPointer<VariableDeclaration>> const& _vars)
<< "\"name\":" << escaped(var->getName(), false) << "," {
<< "\"type\":" << escaped(var->getType()->toString(), false) unsigned varCount = _vars.size();
for (ASTPointer<VariableDeclaration> const& var: _vars)
{
interface << "{"
<< "\"name\":" << escaped(var->getName(), false) << ","
<< "\"type\":" << escaped(var->getType()->toString(), false)
<< "}";
if (--varCount > 0)
interface << ",";
}
};
interface << '{'
<< "\"name\":" << escaped(f->getName(), false) << ","
<< "\"inputs\":[";
streamVariables(f->getParameters());
interface << "],"
<< "\"outputs\":[";
streamVariables(f->getReturnParameters());
interface << "]"
<< "}"; << "}";
if (--varCount > 0) if (--functionsCount > 0)
interface << ","; interface << ",";
} }
}; interface << ']';
m_interface = interface.str();
interface << '{' }
<< "\"name\":" << escaped(f->getName(), false) << ","
<< "\"inputs\":[";
streamVariables(f->getParameters());
interface << "],"
<< "\"outputs\":[";
streamVariables(f->getReturnParameters());
interface << "]"
<< "}";
if (--functionsCount > 0)
interface << ",";
}
interface << ']';
m_interface = interface.str();
} }
return m_interface; return m_interface;
} }

5
libsolidity/CompilerStack.h

@ -32,6 +32,7 @@ namespace solidity {
// forward declarations // forward declarations
class Scanner; class Scanner;
class SourceUnit;
class ContractDefinition; class ContractDefinition;
class Compiler; class Compiler;
class GlobalContext; class GlobalContext;
@ -65,7 +66,7 @@ public:
/// Returns the previously used scanner, useful for counting lines during error reporting. /// Returns the previously used scanner, useful for counting lines during error reporting.
Scanner const& getScanner() const { return *m_scanner; } Scanner const& getScanner() const { return *m_scanner; }
ContractDefinition& getAST() const { return *m_contractASTNode; } SourceUnit& getAST() const { return *m_sourceUnitASTNode; }
/// Compile the given @a _sourceCode to bytecode. If a scanner is provided, it is used for /// Compile the given @a _sourceCode to bytecode. If a scanner is provided, it is used for
/// scanning the source code - this is useful for printing exception information. /// scanning the source code - this is useful for printing exception information.
@ -74,7 +75,7 @@ public:
private: private:
std::shared_ptr<Scanner> m_scanner; std::shared_ptr<Scanner> m_scanner;
std::shared_ptr<GlobalContext> m_globalContext; std::shared_ptr<GlobalContext> m_globalContext;
std::shared_ptr<ContractDefinition> m_contractASTNode; std::shared_ptr<SourceUnit> m_sourceUnitASTNode;
bool m_parseSuccessful; bool m_parseSuccessful;
std::string m_interface; std::string m_interface;
std::shared_ptr<Compiler> m_compiler; std::shared_ptr<Compiler> m_compiler;

43
libsolidity/Parser.cpp

@ -20,6 +20,7 @@
* Solidity parser. * Solidity parser.
*/ */
#include <vector>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libsolidity/BaseTypes.h> #include <libsolidity/BaseTypes.h>
#include <libsolidity/Parser.h> #include <libsolidity/Parser.h>
@ -33,13 +34,6 @@ namespace dev
namespace solidity namespace solidity
{ {
ASTPointer<ContractDefinition> Parser::parse(shared_ptr<Scanner> const& _scanner)
{
m_scanner = _scanner;
return parseContractDefinition();
}
/// AST node factory that also tracks the begin and end position of an AST node /// AST node factory that also tracks the begin and end position of an AST node
/// while it is being parsed /// while it is being parsed
class Parser::ASTNodeFactory class Parser::ASTNodeFactory
@ -65,6 +59,28 @@ private:
Location m_location; Location m_location;
}; };
ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner)
{
m_scanner = _scanner;
ASTNodeFactory nodeFactory(*this);
vector<ASTPointer<ASTNode>> nodes;
while (_scanner->getCurrentToken() != Token::EOS)
{
switch (m_scanner->getCurrentToken())
{
case Token::IMPORT:
nodes.push_back(parseImportDirective());
break;
case Token::CONTRACT:
nodes.push_back(parseContractDefinition());
break;
default:
BOOST_THROW_EXCEPTION(createParserError(std::string("Expected import directive or contract definition.")));
}
}
return nodeFactory.createNode<SourceUnit>(nodes);
}
int Parser::getPosition() const int Parser::getPosition() const
{ {
return m_scanner->getCurrentLocation().start; return m_scanner->getCurrentLocation().start;
@ -75,6 +91,18 @@ int Parser::getEndPosition() const
return m_scanner->getCurrentLocation().end; return m_scanner->getCurrentLocation().end;
} }
ASTPointer<ImportDirective> Parser::parseImportDirective()
{
ASTNodeFactory nodeFactory(*this);
expectToken(Token::IMPORT);
if (m_scanner->getCurrentToken() != Token::STRING_LITERAL)
BOOST_THROW_EXCEPTION(createParserError("Expected string literal (URL)."));
ASTPointer<ASTString> url = getLiteralAndAdvance();
nodeFactory.markEndPosition();
expectToken(Token::SEMICOLON);
return nodeFactory.createNode<ImportDirective>(url);
}
ASTPointer<ContractDefinition> Parser::parseContractDefinition() ASTPointer<ContractDefinition> Parser::parseContractDefinition()
{ {
ASTNodeFactory nodeFactory(*this); ASTNodeFactory nodeFactory(*this);
@ -112,7 +140,6 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
} }
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
expectToken(Token::RBRACE); expectToken(Token::RBRACE);
expectToken(Token::EOS);
return nodeFactory.createNode<ContractDefinition>(name, structs, stateVariables, functions); return nodeFactory.createNode<ContractDefinition>(name, structs, stateVariables, functions);
} }

3
libsolidity/Parser.h

@ -34,7 +34,7 @@ class Scanner;
class Parser class Parser
{ {
public: public:
ASTPointer<ContractDefinition> parse(std::shared_ptr<Scanner> const& _scanner); ASTPointer<SourceUnit> parse(std::shared_ptr<Scanner> const& _scanner);
private: private:
class ASTNodeFactory; class ASTNodeFactory;
@ -46,6 +46,7 @@ private:
///@{ ///@{
///@name Parsing functions for the AST nodes ///@name Parsing functions for the AST nodes
ASTPointer<ImportDirective> parseImportDirective();
ASTPointer<ContractDefinition> parseContractDefinition(); ASTPointer<ContractDefinition> parseContractDefinition();
ASTPointer<FunctionDefinition> parseFunctionDefinition(bool _isPublic); ASTPointer<FunctionDefinition> parseFunctionDefinition(bool _isPublic);
ASTPointer<StructDefinition> parseStructDefinition(); ASTPointer<StructDefinition> parseStructDefinition();

2
solc/main.cpp

@ -127,7 +127,7 @@ int main(int argc, char** argv)
return -1; return -1;
} }
cout << "Syntax tree for the contract:" << endl; cout << "Syntax tree for the source unit:" << endl;
ASTPrinter printer(compiler.getAST(), sourceCode); ASTPrinter printer(compiler.getAST(), sourceCode);
printer.print(cout); printer.print(cout);
cout << "EVM assembly:" << endl; cout << "EVM assembly:" << endl;

26
test/solidityCompiler.cpp

@ -46,16 +46,22 @@ namespace
bytes compileContract(const string& _sourceCode) bytes compileContract(const string& _sourceCode)
{ {
Parser parser; Parser parser;
ASTPointer<ContractDefinition> contract; ASTPointer<SourceUnit> sourceUnit;
BOOST_REQUIRE_NO_THROW(contract = parser.parse(make_shared<Scanner>(CharStream(_sourceCode)))); BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared<Scanner>(CharStream(_sourceCode))));
NameAndTypeResolver resolver({}); for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract)); if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
{
Compiler compiler; NameAndTypeResolver resolver({});
compiler.compileContract(*contract, {}); BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract));
// debug
//compiler.streamAssembly(cout); Compiler compiler;
return compiler.getAssembledBytecode(); compiler.compileContract(*contract, {});
// debug
//compiler.streamAssembly(cout);
return compiler.getAssembledBytecode();
}
BOOST_FAIL("No contract found in source.");
return bytes();
} }
/// Checks that @a _compiledCode is present starting from offset @a _offset in @a _expectation. /// Checks that @a _compiledCode is present starting from offset @a _offset in @a _expectation.

47
test/solidityExpressionCompiler.cpp

@ -86,27 +86,32 @@ bytes compileFirstExpression(const string& _sourceCode, vector<vector<string>> _
vector<vector<string>> _localVariables = {}) vector<vector<string>> _localVariables = {})
{ {
Parser parser; Parser parser;
ASTPointer<ContractDefinition> contract; ASTPointer<SourceUnit> sourceUnit;
BOOST_REQUIRE_NO_THROW(contract = parser.parse(make_shared<Scanner>(CharStream(_sourceCode)))); BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared<Scanner>(CharStream(_sourceCode))));
NameAndTypeResolver resolver({}); for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract)); if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
FirstExpressionExtractor extractor(*contract); {
BOOST_REQUIRE(extractor.getExpression() != nullptr); NameAndTypeResolver resolver({});
BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract));
CompilerContext context; FirstExpressionExtractor extractor(*contract);
for (vector<string> const& function: _functions) BOOST_REQUIRE(extractor.getExpression() != nullptr);
context.addFunction(dynamic_cast<FunctionDefinition const&>(resolveDeclaration(function, resolver)));
for (vector<string> const& variable: _localVariables) CompilerContext context;
context.addVariable(dynamic_cast<VariableDeclaration const&>(resolveDeclaration(variable, resolver))); for (vector<string> const& function: _functions)
context.addFunction(dynamic_cast<FunctionDefinition const&>(resolveDeclaration(function, resolver)));
ExpressionCompiler::compileExpression(context, *extractor.getExpression()); for (vector<string> const& variable: _localVariables)
context.addVariable(dynamic_cast<VariableDeclaration const&>(resolveDeclaration(variable, resolver)));
for (vector<string> const& function: _functions)
context << context.getFunctionEntryLabel(dynamic_cast<FunctionDefinition const&>(resolveDeclaration(function, resolver))); ExpressionCompiler::compileExpression(context, *extractor.getExpression());
bytes instructions = context.getAssembledBytecode();
// debug for (vector<string> const& function: _functions)
// cout << eth::disassemble(instructions) << endl; context << context.getFunctionEntryLabel(dynamic_cast<FunctionDefinition const&>(resolveDeclaration(function, resolver)));
return instructions; bytes instructions = context.getAssembledBytecode();
// debug
// cout << eth::disassemble(instructions) << endl;
return instructions;
}
BOOST_FAIL("No contract found in source.");
} }
} // end anonymous namespace } // end anonymous namespace

11
test/solidityNameAndTypeResolution.cpp

@ -41,10 +41,13 @@ namespace
void parseTextAndResolveNames(std::string const& _source) void parseTextAndResolveNames(std::string const& _source)
{ {
Parser parser; Parser parser;
ASTPointer<ContractDefinition> contract = parser.parse( ASTPointer<SourceUnit> sourceUnit = parser.parse(std::make_shared<Scanner>(CharStream(_source)));
std::make_shared<Scanner>(CharStream(_source))); for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
NameAndTypeResolver resolver({}); if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
resolver.resolveNamesAndTypes(*contract); {
NameAndTypeResolver resolver({});
resolver.resolveNamesAndTypes(*contract);
}
} }
} }

55
test/solidityParser.cpp

@ -21,13 +21,15 @@
*/ */
#include <string> #include <string>
#include <memory>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>
#include <libsolidity/Parser.h> #include <libsolidity/Parser.h>
#include <libsolidity/Exceptions.h> #include <libsolidity/Exceptions.h>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
using namespace std;
namespace dev namespace dev
{ {
namespace solidity namespace solidity
@ -40,7 +42,12 @@ namespace
ASTPointer<ContractDefinition> parseText(std::string const& _source) ASTPointer<ContractDefinition> parseText(std::string const& _source)
{ {
Parser parser; Parser parser;
return parser.parse(std::make_shared<Scanner>(CharStream(_source))); ASTPointer<SourceUnit> sourceUnit = parser.parse(std::make_shared<Scanner>(CharStream(_source)));
for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
if (ASTPointer<ContractDefinition> contract = dynamic_pointer_cast<ContractDefinition>(node))
return contract;
BOOST_FAIL("No contract found in source.");
return ASTPointer<ContractDefinition>();
} }
} }
@ -380,6 +387,50 @@ BOOST_AUTO_TEST_CASE(statement_starting_with_type_conversion)
BOOST_CHECK_NO_THROW(parseText(text)); BOOST_CHECK_NO_THROW(parseText(text));
} }
BOOST_AUTO_TEST_CASE(import_directive)
{
char const* text = "import \"abc\";\n"
"contract test {\n"
" function fun() {\n"
" uint64(2);\n"
" }\n"
"}\n";
BOOST_CHECK_NO_THROW(parseText(text));
}
BOOST_AUTO_TEST_CASE(multiple_contracts)
{
char const* text = "contract test {\n"
" function fun() {\n"
" uint64(2);\n"
" }\n"
"}\n"
"contract test2 {\n"
" function fun() {\n"
" uint64(2);\n"
" }\n"
"}\n";
BOOST_CHECK_NO_THROW(parseText(text));
}
BOOST_AUTO_TEST_CASE(multiple_contracts_and_imports)
{
char const* text = "import \"abc\";\n"
"contract test {\n"
" function fun() {\n"
" uint64(2);\n"
" }\n"
"}\n"
"import \"def\";\n"
"contract test2 {\n"
" function fun() {\n"
" uint64(2);\n"
" }\n"
"}\n"
"import \"ghi\";\n";
BOOST_CHECK_NO_THROW(parseText(text));
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

Loading…
Cancel
Save