mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Coding style and cleanup
This commit is contained in:
parent
8a506b505f
commit
a7f9815c0f
25
AST.cpp
25
AST.cpp
@ -45,18 +45,14 @@ void ContractDefinition::accept(ASTVisitor& _visitor)
|
||||
void StructDefinition::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
listAccept(m_members, _visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void ParameterList::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
listAccept(m_parameters, _visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
@ -75,10 +71,8 @@ void FunctionDefinition::accept(ASTVisitor& _visitor)
|
||||
void VariableDeclaration::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
if (m_typeName)
|
||||
m_typeName->accept(_visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
@ -119,9 +113,7 @@ void Statement::accept(ASTVisitor& _visitor)
|
||||
void Block::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
listAccept(m_statements, _visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
@ -168,10 +160,8 @@ void Break::accept(ASTVisitor& _visitor)
|
||||
void Return::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
if (m_expression)
|
||||
m_expression->accept(_visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
@ -199,9 +189,7 @@ void Assignment::accept(ASTVisitor& _visitor)
|
||||
void UnaryOperation::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
m_subExpression->accept(_visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
@ -228,9 +216,7 @@ void FunctionCall::accept(ASTVisitor& _visitor)
|
||||
void MemberAccess::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
m_expression->accept(_visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
@ -281,7 +267,8 @@ ptr<Type> IfStatement::checkTypeRequirements()
|
||||
{
|
||||
expectType(*m_condition, BoolType());
|
||||
m_trueBody->checkTypeRequirements();
|
||||
if (m_falseBody) m_falseBody->checkTypeRequirements();
|
||||
if (m_falseBody)
|
||||
m_falseBody->checkTypeRequirements();
|
||||
return ptr<Type>();
|
||||
}
|
||||
|
||||
@ -324,15 +311,11 @@ ptr<Type> VariableDefinition::checkTypeRequirements()
|
||||
if (m_value)
|
||||
{
|
||||
if (m_variable->getType())
|
||||
{
|
||||
expectType(*m_value, *m_variable->getType());
|
||||
}
|
||||
else
|
||||
{
|
||||
// no type declared and no previous assignment, infer the type
|
||||
m_variable->setType(m_value->checkTypeRequirements());
|
||||
}
|
||||
}
|
||||
return ptr<Type>();
|
||||
}
|
||||
|
||||
@ -371,9 +354,7 @@ ptr<Type> BinaryOperation::checkTypeRequirements()
|
||||
else
|
||||
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("No common type found in binary operation."));
|
||||
if (Token::isCompareOp(m_operator))
|
||||
{
|
||||
m_type = std::make_shared<BoolType>();
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(Token::isBinaryOp(m_operator));
|
||||
@ -418,11 +399,9 @@ ptr<Type> FunctionCall::checkTypeRequirements()
|
||||
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Wrong argument count for "
|
||||
"function call."));
|
||||
for (size_t i = 0; i < m_arguments.size(); ++i)
|
||||
{
|
||||
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameters[i]->getType()))
|
||||
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Invalid type for argument in "
|
||||
"function call."));
|
||||
}
|
||||
// @todo actually the return type should be an anonymous struct,
|
||||
// but we change it to the type of the first return value until we have structs
|
||||
if (fun.getReturnParameterList()->getParameters().empty())
|
||||
|
60
AST.h
60
AST.h
@ -104,8 +104,7 @@ public:
|
||||
StructDefinition(Location const& _location,
|
||||
ptr<ASTString> const& _name,
|
||||
vecptr<VariableDeclaration> const& _members)
|
||||
: Declaration(_location, _name), m_members(_members)
|
||||
{}
|
||||
: Declaration(_location, _name), m_members(_members) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
|
||||
private:
|
||||
@ -119,8 +118,7 @@ class ParameterList : public ASTNode
|
||||
{
|
||||
public:
|
||||
ParameterList(Location const& _location, vecptr<VariableDeclaration> const& _parameters)
|
||||
: ASTNode(_location), m_parameters(_parameters)
|
||||
{}
|
||||
: ASTNode(_location), m_parameters(_parameters) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
|
||||
vecptr<VariableDeclaration> const& getParameters() { return m_parameters; }
|
||||
@ -138,8 +136,7 @@ public:
|
||||
ptr<Block> const& _body)
|
||||
: Declaration(_location, _name), m_isPublic(_isPublic), m_parameters(_parameters),
|
||||
m_isDeclaredConst(_isDeclaredConst), m_returnParameters(_returnParameters),
|
||||
m_body(_body)
|
||||
{}
|
||||
m_body(_body) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
|
||||
bool isPublic() const { return m_isPublic; }
|
||||
@ -159,11 +156,9 @@ private:
|
||||
class VariableDeclaration: public Declaration
|
||||
{
|
||||
public:
|
||||
VariableDeclaration(Location const& _location,
|
||||
ptr<TypeName> const& _type,
|
||||
VariableDeclaration(Location const& _location, ptr<TypeName> const& _type,
|
||||
ptr<ASTString> const& _name)
|
||||
: Declaration(_location, _name), m_typeName(_type)
|
||||
{}
|
||||
: Declaration(_location, _name), m_typeName(_type) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
|
||||
bool isTypeGivenExplicitly() const { return m_typeName.get() != nullptr; }
|
||||
@ -196,8 +191,7 @@ class ElementaryTypeName : public TypeName
|
||||
{
|
||||
public:
|
||||
explicit ElementaryTypeName(Location const& _location, Token::Value _type)
|
||||
: TypeName(_location), m_type(_type)
|
||||
{}
|
||||
: TypeName(_location), m_type(_type) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual ptr<Type> toType() override { return Type::fromElementaryTypeName(m_type); }
|
||||
|
||||
@ -210,8 +204,7 @@ class UserDefinedTypeName : public TypeName
|
||||
{
|
||||
public:
|
||||
UserDefinedTypeName(Location const& _location, ptr<ASTString> const& _name)
|
||||
: TypeName(_location), m_name(_name)
|
||||
{}
|
||||
: TypeName(_location), m_name(_name) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual ptr<Type> toType() override { return Type::fromUserDefinedTypeName(*this); }
|
||||
|
||||
@ -229,8 +222,7 @@ class Mapping : public TypeName
|
||||
public:
|
||||
Mapping(Location const& _location, ptr<ElementaryTypeName> const& _keyType,
|
||||
ptr<TypeName> const& _valueType)
|
||||
: TypeName(_location), m_keyType(_keyType), m_valueType(_valueType)
|
||||
{}
|
||||
: TypeName(_location), m_keyType(_keyType), m_valueType(_valueType) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual ptr<Type> toType() override { return Type::fromMapping(*this); }
|
||||
private:
|
||||
@ -263,8 +255,7 @@ class Block : public Statement
|
||||
{
|
||||
public:
|
||||
Block(Location const& _location, vecptr<Statement> const& _statements)
|
||||
: Statement(_location), m_statements(_statements)
|
||||
{}
|
||||
: Statement(_location), m_statements(_statements) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
|
||||
virtual ptr<Type> checkTypeRequirements() override;
|
||||
@ -278,8 +269,7 @@ public:
|
||||
IfStatement(Location const& _location, ptr<Expression> const& _condition,
|
||||
ptr<Statement> const& _trueBody, ptr<Statement> const& _falseBody)
|
||||
: Statement(_location), m_condition(_condition),
|
||||
m_trueBody(_trueBody), m_falseBody(_falseBody)
|
||||
{}
|
||||
m_trueBody(_trueBody), m_falseBody(_falseBody) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual ptr<Type> checkTypeRequirements() override;
|
||||
private:
|
||||
@ -300,8 +290,7 @@ class WhileStatement : public BreakableStatement
|
||||
public:
|
||||
WhileStatement(Location const& _location, ptr<Expression> const& _condition,
|
||||
ptr<Statement> const& _body)
|
||||
: BreakableStatement(_location), m_condition(_condition), m_body(_body)
|
||||
{}
|
||||
: BreakableStatement(_location), m_condition(_condition), m_body(_body) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual ptr<Type> checkTypeRequirements() override;
|
||||
private:
|
||||
@ -329,8 +318,7 @@ class Return : public Statement
|
||||
{
|
||||
public:
|
||||
Return(Location const& _location, ptr<Expression> _expression)
|
||||
: Statement(_location), m_expression(_expression)
|
||||
{}
|
||||
: Statement(_location), m_expression(_expression) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual ptr<Type> checkTypeRequirements() override;
|
||||
|
||||
@ -346,8 +334,7 @@ class VariableDefinition : public Statement
|
||||
public:
|
||||
VariableDefinition(Location const& _location, ptr<VariableDeclaration> _variable,
|
||||
ptr<Expression> _value)
|
||||
: Statement(_location), m_variable(_variable), m_value(_value)
|
||||
{}
|
||||
: Statement(_location), m_variable(_variable), m_value(_value) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual ptr<Type> checkTypeRequirements() override;
|
||||
|
||||
@ -376,8 +363,7 @@ public:
|
||||
Assignment(Location const& _location, ptr<Expression> const& _leftHandSide,
|
||||
Token::Value _assignmentOperator, ptr<Expression> const& _rightHandSide)
|
||||
: Expression(_location), m_leftHandSide(_leftHandSide),
|
||||
m_assigmentOperator(_assignmentOperator), m_rightHandSide(_rightHandSide)
|
||||
{}
|
||||
m_assigmentOperator(_assignmentOperator), m_rightHandSide(_rightHandSide) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual ptr<Type> checkTypeRequirements() override;
|
||||
|
||||
@ -394,8 +380,7 @@ public:
|
||||
UnaryOperation(Location const& _location, Token::Value _operator,
|
||||
ptr<Expression> const& _subExpression, bool _isPrefix)
|
||||
: Expression(_location), m_operator(_operator),
|
||||
m_subExpression(_subExpression), m_isPrefix(_isPrefix)
|
||||
{}
|
||||
m_subExpression(_subExpression), m_isPrefix(_isPrefix) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual ptr<Type> checkTypeRequirements() override;
|
||||
|
||||
@ -412,8 +397,7 @@ class BinaryOperation : public Expression
|
||||
public:
|
||||
BinaryOperation(Location const& _location, ptr<Expression> const& _left,
|
||||
Token::Value _operator, ptr<Expression> const& _right)
|
||||
: Expression(_location), m_left(_left), m_operator(_operator), m_right(_right)
|
||||
{}
|
||||
: Expression(_location), m_left(_left), m_operator(_operator), m_right(_right) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual ptr<Type> checkTypeRequirements() override;
|
||||
|
||||
@ -432,8 +416,7 @@ class FunctionCall : public Expression
|
||||
public:
|
||||
FunctionCall(Location const& _location, ptr<Expression> const& _expression,
|
||||
vecptr<Expression> const& _arguments)
|
||||
: Expression(_location), m_expression(_expression), m_arguments(_arguments)
|
||||
{}
|
||||
: Expression(_location), m_expression(_expression), m_arguments(_arguments) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual ptr<Type> checkTypeRequirements() override;
|
||||
private:
|
||||
@ -446,8 +429,7 @@ class MemberAccess : public Expression
|
||||
public:
|
||||
MemberAccess(Location const& _location, ptr<Expression> _expression,
|
||||
ptr<ASTString> const& _memberName)
|
||||
: Expression(_location), m_expression(_expression), m_memberName(_memberName)
|
||||
{}
|
||||
: Expression(_location), m_expression(_expression), m_memberName(_memberName) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
const ASTString& getMemberName() const { return *m_memberName; }
|
||||
virtual ptr<Type> checkTypeRequirements() override;
|
||||
@ -461,8 +443,7 @@ class IndexAccess : public Expression
|
||||
public:
|
||||
IndexAccess(Location const& _location, ptr<Expression> const& _base,
|
||||
ptr<Expression> const& _index)
|
||||
: Expression(_location), m_base(_base), m_index(_index)
|
||||
{}
|
||||
: Expression(_location), m_base(_base), m_index(_index) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual ptr<Type> checkTypeRequirements() override;
|
||||
private:
|
||||
@ -511,8 +492,7 @@ class Literal : public PrimaryExpression
|
||||
{
|
||||
public:
|
||||
Literal(Location const& _location, Token::Value _token, ptr<ASTString> const& _value)
|
||||
: PrimaryExpression(_location), m_token(_token), m_value(_value)
|
||||
{}
|
||||
: PrimaryExpression(_location), m_token(_token), m_value(_value) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual ptr<Type> checkTypeRequirements() override;
|
||||
|
||||
|
@ -244,7 +244,7 @@ bool ASTPrinter::visit(Literal& _node)
|
||||
{
|
||||
const char* tokenString = Token::toString(_node.getToken());
|
||||
if (tokenString == nullptr)
|
||||
tokenString = "----";
|
||||
tokenString = "[no token]";
|
||||
writeLine(std::string("Literal, token: ") + tokenString + " value: " + _node.getValue());
|
||||
printSourcePart(_node);
|
||||
return goDeeper();
|
||||
@ -255,8 +255,6 @@ void ASTPrinter::endVisit(ASTNode&)
|
||||
m_indentation--;
|
||||
}
|
||||
|
||||
// @todo instead of this, we could make the default implementation of endVisit call the
|
||||
// superclass' endVisit
|
||||
void ASTPrinter::endVisit(ContractDefinition&)
|
||||
{
|
||||
m_indentation--;
|
||||
|
@ -50,7 +50,7 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
|
||||
ReferencesResolver referencesResolver(*function, *this,
|
||||
function->getReturnParameterList().get());
|
||||
}
|
||||
// First, all function parameter types need to be resolved before we can check
|
||||
// First, the parameter types of all functions need to be resolved before we can check
|
||||
// the types, since it is possible to call functions that are only defined later
|
||||
// in the source.
|
||||
for (ptr<FunctionDefinition> const& function: _contract.getDefinedFunctions())
|
||||
|
@ -34,7 +34,8 @@ namespace dev
|
||||
namespace solidity
|
||||
{
|
||||
|
||||
|
||||
//! Resolves name references, resolves all types and checks that all operations are valid for the
|
||||
//! inferred types. An exception is throw on the first error.
|
||||
class NameAndTypeResolver: private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
|
48
Parser.cpp
48
Parser.cpp
@ -43,27 +43,13 @@ ptr<ContractDefinition> Parser::parse(std::shared_ptr<Scanner> const& _scanner)
|
||||
class Parser::ASTNodeFactory
|
||||
{
|
||||
public:
|
||||
ASTNodeFactory(const Parser& _parser)
|
||||
: m_parser(_parser), m_location(_parser.getPosition(), -1)
|
||||
{}
|
||||
|
||||
void markEndPosition()
|
||||
{
|
||||
m_location.end = m_parser.getEndPosition();
|
||||
}
|
||||
|
||||
void setLocationEmpty()
|
||||
{
|
||||
m_location.end = m_location.start;
|
||||
}
|
||||
ASTNodeFactory(const Parser& _parser) : m_parser(_parser), m_location(_parser.getPosition(), -1) {}
|
||||
|
||||
void markEndPosition() { m_location.end = m_parser.getEndPosition(); }
|
||||
void setLocationEmpty() { m_location.end = m_location.start; }
|
||||
/// Set the end position to the one of the given node.
|
||||
void setEndPositionFromNode(const ptr<ASTNode>& _node)
|
||||
{
|
||||
m_location.end = _node->getLocation().end;
|
||||
}
|
||||
void setEndPositionFromNode(const ptr<ASTNode>& _node) { m_location.end = _node->getLocation().end; }
|
||||
|
||||
/// @todo: check that this actually uses perfect forwarding
|
||||
template <class NodeType, typename... Args>
|
||||
ptr<NodeType> createNode(Args&& ... _args)
|
||||
{
|
||||
@ -102,9 +88,7 @@ ptr<ContractDefinition> Parser::parseContractDefinition()
|
||||
{
|
||||
Token::Value currentToken = m_scanner->getCurrentToken();
|
||||
if (currentToken == Token::RBRACE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (currentToken == Token::PUBLIC || currentToken == Token::PRIVATE)
|
||||
{
|
||||
visibilityIsPublic = (m_scanner->getCurrentToken() == Token::PUBLIC);
|
||||
@ -112,13 +96,9 @@ ptr<ContractDefinition> Parser::parseContractDefinition()
|
||||
expectToken(Token::COLON);
|
||||
}
|
||||
else if (currentToken == Token::FUNCTION)
|
||||
{
|
||||
functions.push_back(parseFunctionDefinition(visibilityIsPublic));
|
||||
}
|
||||
else if (currentToken == Token::STRUCT)
|
||||
{
|
||||
structs.push_back(parseStructDefinition());
|
||||
}
|
||||
else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING ||
|
||||
Token::isElementaryTypeName(currentToken))
|
||||
{
|
||||
@ -127,10 +107,8 @@ ptr<ContractDefinition> Parser::parseContractDefinition()
|
||||
expectToken(Token::SEMICOLON);
|
||||
}
|
||||
else
|
||||
{
|
||||
throwExpectationError("Function, variable or struct declaration expected.");
|
||||
}
|
||||
}
|
||||
nodeFactory.markEndPosition();
|
||||
expectToken(Token::RBRACE);
|
||||
expectToken(Token::EOS);
|
||||
@ -221,9 +199,7 @@ ptr<TypeName> Parser::parseTypeName(bool _allowVar)
|
||||
type = nodeFactory.createNode<UserDefinedTypeName>(expectIdentifierToken());
|
||||
}
|
||||
else
|
||||
{
|
||||
throwExpectationError("Expected type name");
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -271,9 +247,7 @@ ptr<Block> Parser::parseBlock()
|
||||
expectToken(Token::LBRACE);
|
||||
vecptr<Statement> statements;
|
||||
while (m_scanner->getCurrentToken() != Token::RBRACE)
|
||||
{
|
||||
statements.push_back(parseStatement());
|
||||
}
|
||||
nodeFactory.markEndPosition();
|
||||
expectToken(Token::RBRACE);
|
||||
return nodeFactory.createNode<Block>(statements);
|
||||
@ -318,16 +292,11 @@ ptr<Statement> Parser::parseStatement()
|
||||
m_scanner->getCurrentToken() == Token::VAR ||
|
||||
Token::isElementaryTypeName(m_scanner->getCurrentToken()) ||
|
||||
(m_scanner->getCurrentToken() == Token::IDENTIFIER &&
|
||||
m_scanner->peek() == Token::IDENTIFIER))
|
||||
{
|
||||
m_scanner->peekNextToken() == Token::IDENTIFIER))
|
||||
statement = parseVariableDefinition();
|
||||
}
|
||||
else
|
||||
{
|
||||
// "ordinary" expression
|
||||
else // "ordinary" expression
|
||||
statement = parseExpression();
|
||||
}
|
||||
}
|
||||
expectToken(Token::SEMICOLON);
|
||||
return statement;
|
||||
}
|
||||
@ -348,9 +317,7 @@ ptr<IfStatement> Parser::parseIfStatement()
|
||||
nodeFactory.setEndPositionFromNode(falseBody);
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeFactory.setEndPositionFromNode(trueBody);
|
||||
}
|
||||
return nodeFactory.createNode<IfStatement>(condition, trueBody, falseBody);
|
||||
}
|
||||
|
||||
@ -379,9 +346,7 @@ ptr<VariableDefinition> Parser::parseVariableDefinition()
|
||||
nodeFactory.setEndPositionFromNode(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeFactory.setEndPositionFromNode(variable);
|
||||
}
|
||||
return nodeFactory.createNode<VariableDefinition>(variable, value);
|
||||
}
|
||||
|
||||
@ -520,6 +485,7 @@ ptr<Expression> Parser::parsePrimaryExpression()
|
||||
throwExpectationError("Expected primary expression.");
|
||||
return ptr<Expression>(); // this is not reached
|
||||
}
|
||||
break;
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
56
Scanner.cpp
56
Scanner.cpp
@ -103,11 +103,11 @@ void Scanner::reset(const CharStream& _source)
|
||||
}
|
||||
|
||||
|
||||
bool Scanner::scanHexNumber(char& scanned_number, int expected_length)
|
||||
bool Scanner::scanHexNumber(char& o_scannedNumber, int _expectedLength)
|
||||
{
|
||||
BOOST_ASSERT(expected_length <= 4); // prevent overflow
|
||||
BOOST_ASSERT(_expectedLength <= 4); // prevent overflow
|
||||
char x = 0;
|
||||
for (int i = 0; i < expected_length; i++)
|
||||
for (int i = 0; i < _expectedLength; i++)
|
||||
{
|
||||
int d = HexValue(m_char);
|
||||
if (d < 0)
|
||||
@ -118,7 +118,7 @@ bool Scanner::scanHexNumber(char& scanned_number, int expected_length)
|
||||
x = x * 16 + d;
|
||||
advance();
|
||||
}
|
||||
scanned_number = x;
|
||||
o_scannedNumber = x;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -129,24 +129,25 @@ BOOST_STATIC_ASSERT(Token::NUM_TOKENS <= 0x100);
|
||||
Token::Value Scanner::next()
|
||||
{
|
||||
m_current_token = m_next_token;
|
||||
m_hasLineTerminatorBeforeNext = false;
|
||||
m_hasMultilineCommentBeforeNext = false;
|
||||
scanToken();
|
||||
return m_current_token.token;
|
||||
}
|
||||
|
||||
Token::Value Scanner::selectToken(char _next, Token::Value _then, Token::Value _else)
|
||||
{
|
||||
advance();
|
||||
if (m_char == _next)
|
||||
selectToken(_then);
|
||||
else
|
||||
return _else;
|
||||
}
|
||||
|
||||
|
||||
bool Scanner::skipWhitespace()
|
||||
{
|
||||
const int start_position = getSourcePos();
|
||||
while (true)
|
||||
{
|
||||
if (IsLineTerminator(m_char))
|
||||
m_hasLineTerminatorBeforeNext = true;
|
||||
else if (!IsWhiteSpace(m_char))
|
||||
break;
|
||||
while (IsWhiteSpace(m_char))
|
||||
advance();
|
||||
}
|
||||
// Return whether or not we skipped any characters.
|
||||
return getSourcePos() != start_position;
|
||||
}
|
||||
@ -170,12 +171,7 @@ Token::Value Scanner::skipMultiLineComment()
|
||||
{
|
||||
char ch = m_char;
|
||||
advance();
|
||||
if (IsLineTerminator(ch))
|
||||
{
|
||||
// Following ECMA-262, section 7.4, a comment containing
|
||||
// a newline will make the comment count as a line-terminator.
|
||||
m_hasMultilineCommentBeforeNext = true;
|
||||
}
|
||||
|
||||
// If we have reached the end of the multi-line comment, we
|
||||
// consume the '/' and insert a whitespace. This way all
|
||||
// multi-line comments are treated as whitespace.
|
||||
@ -199,8 +195,7 @@ void Scanner::scanToken()
|
||||
m_next_token.location.start = getSourcePos();
|
||||
switch (m_char)
|
||||
{
|
||||
case '\n':
|
||||
m_hasLineTerminatorBeforeNext = true; // fall-through
|
||||
case '\n': // fall-through
|
||||
case ' ':
|
||||
case '\t':
|
||||
token = selectToken(Token::WHITESPACE);
|
||||
@ -423,9 +418,7 @@ bool Scanner::scanEscape()
|
||||
if (!scanHexNumber(c, 2)) return false;
|
||||
break;
|
||||
}
|
||||
// According to ECMA-262, section 7.8.4, characters not covered by the
|
||||
// above cases should be illegal, but they are commonly handled as
|
||||
// non-escaped characters by JS VMs.
|
||||
|
||||
addLiteralChar(c);
|
||||
return true;
|
||||
}
|
||||
@ -653,6 +646,21 @@ Token::Value Scanner::scanIdentifierOrKeyword()
|
||||
return KeywordOrIdentifierToken(m_next_token.literal);
|
||||
}
|
||||
|
||||
char CharStream::advanceAndGet()
|
||||
{
|
||||
if (isPastEndOfInput()) return 0;
|
||||
++m_pos;
|
||||
if (isPastEndOfInput()) return 0;
|
||||
return get();
|
||||
}
|
||||
|
||||
char CharStream::rollback(size_t _amount)
|
||||
{
|
||||
BOOST_ASSERT(m_pos >= _amount);
|
||||
m_pos -= _amount;
|
||||
return get();
|
||||
}
|
||||
|
||||
std::string CharStream::getLineAtPosition(int _position) const
|
||||
{
|
||||
// if _position points to \n, it returns the line before the \n
|
||||
|
109
Scanner.h
109
Scanner.h
@ -63,27 +63,13 @@ class ParserRecorder;
|
||||
class CharStream
|
||||
{
|
||||
public:
|
||||
CharStream()
|
||||
: m_pos(0)
|
||||
{}
|
||||
|
||||
CharStream() : m_pos(0) {}
|
||||
explicit CharStream(const std::string& _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()
|
||||
{
|
||||
if (isPastEndOfInput()) return 0;
|
||||
++m_pos;
|
||||
if (isPastEndOfInput()) return 0;
|
||||
return get();
|
||||
}
|
||||
char rollback(size_t _amount)
|
||||
{
|
||||
BOOST_ASSERT(m_pos >= _amount);
|
||||
m_pos -= _amount;
|
||||
return get();
|
||||
}
|
||||
char advanceAndGet();
|
||||
char rollback(size_t _amount);
|
||||
|
||||
/// Functions that help pretty-printing parse errors
|
||||
/// Do only use in error cases, they are quite expensive.
|
||||
@ -96,8 +82,6 @@ private:
|
||||
size_t m_pos;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// JavaScript Scanner.
|
||||
|
||||
class Scanner
|
||||
{
|
||||
@ -118,47 +102,36 @@ public:
|
||||
|
||||
explicit Scanner(const CharStream& _source);
|
||||
|
||||
// Resets the scanner as if newly constructed with _input as input.
|
||||
/// Resets the scanner as if newly constructed with _input as input.
|
||||
void reset(const CharStream& _source);
|
||||
|
||||
// Returns the next token and advances input.
|
||||
/// Returns the next token and advances input.
|
||||
Token::Value next();
|
||||
// Returns the current token again.
|
||||
|
||||
/// Information about the current token
|
||||
/// @{
|
||||
|
||||
/// Returns the current token
|
||||
Token::Value getCurrentToken() { return m_current_token.token; }
|
||||
// Returns the location information for the current token
|
||||
// (the token last returned by Next()).
|
||||
Location getCurrentLocation() const { return m_current_token.location; }
|
||||
const std::string& getCurrentLiteral() const { return m_current_token.literal; }
|
||||
/// @}
|
||||
|
||||
// Similar functions for the upcoming token.
|
||||
|
||||
// One token look-ahead (past the token returned by Next()).
|
||||
Token::Value peek() const { return m_next_token.token; }
|
||||
|
||||
/// Information about the next token
|
||||
/// @{
|
||||
/// Returns the next token without advancing input.
|
||||
Token::Value peekNextToken() const { return m_next_token.token; }
|
||||
Location peekLocation() const { return m_next_token.location; }
|
||||
const std::string& peekLiteral() const { return m_next_token.literal; }
|
||||
/// @}
|
||||
|
||||
/// Functions that help pretty-printing parse errors.
|
||||
/// Do only use in error cases, they are quite expensive.
|
||||
/// @{
|
||||
std::string getLineAtPosition(int _position) const
|
||||
{
|
||||
return m_source.getLineAtPosition(_position);
|
||||
}
|
||||
std::tuple<int, int> translatePositionToLineColumn(int _position) const
|
||||
{
|
||||
return m_source.translatePositionToLineColumn(_position);
|
||||
}
|
||||
std::string getLineAtPosition(int _position) const { return m_source.getLineAtPosition(_position); }
|
||||
std::tuple<int, int> translatePositionToLineColumn(int _position) const { return m_source.translatePositionToLineColumn(_position); }
|
||||
/// @}
|
||||
|
||||
// Returns true if there was a line terminator before the peek'ed token,
|
||||
// possibly inside a multi-line comment.
|
||||
bool hasAnyLineTerminatorBeforeNext() const
|
||||
{
|
||||
return m_hasLineTerminatorBeforeNext ||
|
||||
m_hasMultilineCommentBeforeNext;
|
||||
}
|
||||
|
||||
private:
|
||||
// Used for the current and look-ahead token.
|
||||
struct TokenDesc
|
||||
@ -168,34 +141,22 @@ private:
|
||||
std::string literal;
|
||||
};
|
||||
|
||||
// Literal buffer support
|
||||
/// Literal buffer support
|
||||
/// @{
|
||||
inline void startNewLiteral() { m_next_token.literal.clear(); }
|
||||
|
||||
inline void addLiteralChar(char c) { m_next_token.literal.push_back(c); }
|
||||
|
||||
inline void dropLiteral() { m_next_token.literal.clear(); }
|
||||
|
||||
inline void addLiteralCharAndAdvance() { addLiteralChar(m_char); advance(); }
|
||||
/// @}
|
||||
|
||||
// Low-level scanning support.
|
||||
bool advance() { m_char = m_source.advanceAndGet(); return !m_source.isPastEndOfInput(); }
|
||||
void rollback(int amount) { m_char = m_source.rollback(amount); }
|
||||
void rollback(int _amount) { m_char = m_source.rollback(_amount); }
|
||||
|
||||
inline Token::Value selectToken(Token::Value tok) { advance(); return tok; }
|
||||
inline Token::Value selectToken(Token::Value _tok) { advance(); return _tok; }
|
||||
/// If the next character is _next, advance and return _then, otherwise return _else.
|
||||
inline Token::Value selectToken(char _next, Token::Value _then, Token::Value _else);
|
||||
|
||||
inline Token::Value selectToken(char next, Token::Value then, Token::Value else_)
|
||||
{
|
||||
advance();
|
||||
if (m_char == next)
|
||||
{
|
||||
advance();
|
||||
return then;
|
||||
}
|
||||
else
|
||||
return else_;
|
||||
}
|
||||
|
||||
bool scanHexNumber(char& scanned_number, int expected_length);
|
||||
bool scanHexNumber(char& o_scannedNumber, int _expectedLength);
|
||||
|
||||
// Scans a single JavaScript token.
|
||||
void scanToken();
|
||||
@ -210,12 +171,12 @@ private:
|
||||
|
||||
Token::Value scanString();
|
||||
|
||||
// Scans an escape-sequence which is part of a string and adds the
|
||||
// decoded character to the current literal. Returns true if a pattern
|
||||
// is scanned.
|
||||
/// Scans an escape-sequence which is part of a string and adds the
|
||||
/// decoded character to the current literal. Returns true if a pattern
|
||||
/// is scanned.
|
||||
bool scanEscape();
|
||||
|
||||
// Return the current source position.
|
||||
/// Return the current source position.
|
||||
int getSourcePos() { return m_source.getPos(); }
|
||||
bool isSourcePastEndOfInput() { return m_source.isPastEndOfInput(); }
|
||||
|
||||
@ -224,16 +185,8 @@ private:
|
||||
|
||||
CharStream m_source;
|
||||
|
||||
// one character look-ahead, equals 0 at end of input
|
||||
/// one character look-ahead, equals 0 at end of input
|
||||
char m_char;
|
||||
|
||||
// Whether there is a line terminator whitespace character after
|
||||
// the current token, and before the next. Does not count newlines
|
||||
// inside multiline comments.
|
||||
bool m_hasLineTerminatorBeforeNext;
|
||||
// Whether there is a multi-line comment that contains a
|
||||
// line-terminator after the current token, and before the next.
|
||||
bool m_hasMultilineCommentBeforeNext;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user