diff options
author | chriseth <c@ethdev.com> | 2016-03-12 00:53:33 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2016-03-12 00:53:33 +0800 |
commit | 1f9578cea3f7ea1982ba2288cd3238bfe791b348 (patch) | |
tree | 9cc3e20fde1c8c89afd3ca33a6c4b067c448e4bc /libsolidity | |
parent | 60a21c6487743578af6fd4e1540a36a2b80fcac7 (diff) | |
parent | 1bf87c6c2b90406d8a59aa928a9fe43a169e157a (diff) | |
download | dexon-solidity-1f9578cea3f7ea1982ba2288cd3238bfe791b348.tar dexon-solidity-1f9578cea3f7ea1982ba2288cd3238bfe791b348.tar.gz dexon-solidity-1f9578cea3f7ea1982ba2288cd3238bfe791b348.tar.bz2 dexon-solidity-1f9578cea3f7ea1982ba2288cd3238bfe791b348.tar.lz dexon-solidity-1f9578cea3f7ea1982ba2288cd3238bfe791b348.tar.xz dexon-solidity-1f9578cea3f7ea1982ba2288cd3238bfe791b348.tar.zst dexon-solidity-1f9578cea3f7ea1982ba2288cd3238bfe791b348.zip |
Merge pull request #429 from chriseth/keywords
Breaking changes for version 0.3.0
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/ast/Types.cpp | 47 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 6 | ||||
-rw-r--r-- | libsolidity/codegen/Compiler.cpp | 10 | ||||
-rw-r--r-- | libsolidity/codegen/Compiler.h | 2 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 29 | ||||
-rw-r--r-- | libsolidity/formal/Why3Translator.h | 2 | ||||
-rw-r--r-- | libsolidity/interface/CompilerStack.h | 10 | ||||
-rw-r--r-- | libsolidity/interface/InterfaceHandler.h | 2 | ||||
-rw-r--r-- | libsolidity/parsing/Parser.h | 4 | ||||
-rw-r--r-- | libsolidity/parsing/Scanner.h | 6 | ||||
-rw-r--r-- | libsolidity/parsing/Token.cpp | 43 | ||||
-rw-r--r-- | libsolidity/parsing/Token.h | 22 |
12 files changed, 112 insertions, 71 deletions
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index bca83d59..4dc1eb13 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -333,6 +333,7 @@ MemberList::MemberMap IntegerType::nativeMembers(ContractDefinition const*) cons {"balance", make_shared<IntegerType >(256)}, {"call", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Location::Bare, true)}, {"callcode", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Location::BareCallCode, true)}, + {"delegatecall", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Location::BareDelegateCall, true)}, {"send", make_shared<FunctionType>(strings{"uint"}, strings{"bool"}, FunctionType::Location::Send)} }; else @@ -1561,9 +1562,9 @@ unsigned FunctionType::sizeOnStack() const } unsigned size = 0; - if (location == Location::External || location == Location::CallCode) + if (location == Location::External || location == Location::CallCode || location == Location::DelegateCall) size = 2; - else if (location == Location::Bare || location == Location::BareCallCode) + else if (location == Location::Bare || location == Location::BareCallCode || location == Location::BareDelegateCall) size = 1; else if (location == Location::Internal) size = 1; @@ -1619,9 +1620,11 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con case Location::RIPEMD160: case Location::Bare: case Location::BareCallCode: + case Location::BareDelegateCall: { - MemberList::MemberMap members{ - { + MemberList::MemberMap members; + if (m_location != Location::BareDelegateCall && m_location != Location::DelegateCall) + members.push_back(MemberList::Member( "value", make_shared<FunctionType>( parseElementaryTypeVector({"uint"}), @@ -1634,25 +1637,22 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con m_gasSet, m_valueSet ) - } - }; + )); if (m_location != Location::Creation) - members.push_back( - MemberList::Member( - "gas", - make_shared<FunctionType>( - parseElementaryTypeVector({"uint"}), - TypePointers{copyAndSetGasOrValue(true, false)}, - strings(), - strings(), - Location::SetGas, - false, - nullptr, - m_gasSet, - m_valueSet - ) + members.push_back(MemberList::Member( + "gas", + make_shared<FunctionType>( + parseElementaryTypeVector({"uint"}), + TypePointers{copyAndSetGasOrValue(true, false)}, + strings(), + strings(), + Location::SetGas, + false, + nullptr, + m_gasSet, + m_valueSet ) - ); + )); return members; } default: @@ -1700,6 +1700,7 @@ bool FunctionType::isBareCall() const { case Location::Bare: case Location::BareCallCode: + case Location::BareDelegateCall: case Location::ECRecover: case Location::SHA256: case Location::RIPEMD160: @@ -1785,7 +1786,7 @@ FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary, bool _bound) returnParameterTypes, m_parameterNames, returnParameterNames, - _inLibrary ? Location::CallCode : m_location, + _inLibrary ? Location::DelegateCall : m_location, m_arbitraryParameters, m_declaration, m_gasSet, @@ -1884,7 +1885,7 @@ MemberList::MemberMap TypeType::nativeMembers(ContractDefinition const* _current for (auto const& it: contract.interfaceFunctions()) members.push_back(MemberList::Member( it.second->declaration().name(), - it.second->asMemberFunction(true), // use callcode + it.second->asMemberFunction(true), &it.second->declaration() )); if (isBase) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index b4a2d573..1d65aeb6 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -732,8 +732,10 @@ public: Internal, ///< stack-call using plain JUMP External, ///< external call using CALL CallCode, ///< extercnal call using CALLCODE, i.e. not exchanging the storage + DelegateCall, ///< extercnal call using DELEGATECALL, i.e. not exchanging the storage Bare, ///< CALL without function hash BareCallCode, ///< CALLCODE without function hash + BareDelegateCall, ///< DELEGATECALL without function hash Creation, ///< external call using CREATE Send, ///< CALL, but without data and gas SHA3, ///< SHA3 @@ -824,7 +826,7 @@ public: /// @returns TypePointer of a new FunctionType object. All input/return parameters are an /// appropriate external types (i.e. the interfaceType()s) of input/return parameters of /// current function. - /// Returns an empty shared pointer if one of the input/return parameters does not have an + /// @returns an empty shared pointer if one of the input/return parameters does not have an /// external type. FunctionTypePointer interfaceFunctionType() const; @@ -869,7 +871,7 @@ public: /// removed and the location of reference types is changed from CallData to Memory. /// This is needed if external functions are called on other contracts, as they cannot return /// dynamic values. - /// @param _inLibrary if true, uses CallCode as location. + /// @param _inLibrary if true, uses DelegateCall as location. /// @param _bound if true, the argumenst are placed as `arg1.functionName(arg2, ..., argn)`. FunctionTypePointer asMemberFunction(bool _inLibrary, bool _bound = false) const; diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp index 18803b71..c7eb71a8 100644 --- a/libsolidity/codegen/Compiler.cpp +++ b/libsolidity/codegen/Compiler.cpp @@ -773,15 +773,13 @@ eth::Assembly Compiler::cloneRuntime() a << u256(0) << eth::Instruction::DUP1 << eth::Instruction::CALLDATACOPY; //@todo adjust for larger return values, make this dynamic. a << u256(0x20) << u256(0) << eth::Instruction::CALLDATASIZE; - // unfortunately, we have to send the value again, so that CALLVALUE returns the correct value - // in the callcoded contract. - a << u256(0) << eth::Instruction::CALLVALUE; + a << u256(0); // this is the address which has to be substituted by the linker. //@todo implement as special "marker" AssemblyItem. a << u256("0xcafecafecafecafecafecafecafecafecafecafe"); - a << u256(schedule.callGas + schedule.callValueTransferGas + 10) << eth::Instruction::GAS << eth::Instruction::SUB; - a << eth::Instruction::CALLCODE; - //Propagate error condition (if CALLCODE pushes 0 on stack). + a << u256(schedule.callGas + 10) << eth::Instruction::GAS << eth::Instruction::SUB; + a << eth::Instruction::DELEGATECALL; + //Propagate error condition (if DELEGATECALL pushes 0 on stack). a << eth::Instruction::ISZERO; a.appendJumpI(a.errorTag()); //@todo adjust for larger return values, make this dynamic. diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index 9d069f7c..fa33bd30 100644 --- a/libsolidity/codegen/Compiler.h +++ b/libsolidity/codegen/Compiler.h @@ -44,7 +44,7 @@ public: ContractDefinition const& _contract, std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts ); - /// Compiles a contract that uses CALLCODE to call into a pre-deployed version of the given + /// Compiles a contract that uses DELEGATECALL to call into a pre-deployed version of the given /// contract at runtime, but contains the full creation-time code. void compileClone( ContractDefinition const& _contract, diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 58db07b1..e0b2b5f6 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -465,8 +465,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) { FunctionType const& function = *functionType; if (function.bound()) - // Only callcode functions can be bound, this might be lifted later. - solAssert(function.location() == Location::CallCode, ""); + // Only delegatecall functions can be bound, this might be lifted later. + solAssert(function.location() == Location::DelegateCall, ""); switch (function.location()) { case Location::Internal: @@ -492,8 +492,10 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) } case Location::External: case Location::CallCode: + case Location::DelegateCall: case Location::Bare: case Location::BareCallCode: + case Location::BareDelegateCall: _functionCall.expression().accept(*this); appendExternalFunctionCall(function, arguments); break; @@ -875,7 +877,7 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) ); m_context << eth::Instruction::BALANCE; } - else if ((set<string>{"send", "call", "callcode"}).count(member)) + else if ((set<string>{"send", "call", "callcode", "delegatecall"}).count(member)) utils().convertType( *_memberAccess.expression().annotation().type, IntegerType(0, IntegerType::Modifier::Address), @@ -1356,6 +1358,7 @@ void ExpressionCompiler::appendExternalFunctionCall( FunctionKind funKind = _functionType.location(); bool returnSuccessCondition = funKind == FunctionKind::Bare || funKind == FunctionKind::BareCallCode; bool isCallCode = funKind == FunctionKind::BareCallCode || funKind == FunctionKind::CallCode; + bool isDelegateCall = funKind == FunctionKind::BareDelegateCall || funKind == FunctionKind::DelegateCall; unsigned retSize = 0; if (returnSuccessCondition) @@ -1371,13 +1374,13 @@ void ExpressionCompiler::appendExternalFunctionCall( TypePointers argumentTypes; TypePointers parameterTypes = _functionType.parameterTypes(); bool manualFunctionId = - (funKind == FunctionKind::Bare || funKind == FunctionKind::BareCallCode) && + (funKind == FunctionKind::Bare || funKind == FunctionKind::BareCallCode || funKind == FunctionKind::BareDelegateCall) && !_arguments.empty() && _arguments.front()->annotation().type->mobileType()->calldataEncodedSize(false) == CompilerUtils::dataStartOffset; if (manualFunctionId) { - // If we have a BareCall or BareCallCode and the first type has exactly 4 bytes, use it as + // If we have a Bare* and the first type has exactly 4 bytes, use it as // function identifier. _arguments.front()->accept(*this); utils().convertType( @@ -1416,7 +1419,7 @@ void ExpressionCompiler::appendExternalFunctionCall( parameterTypes, _functionType.padArguments(), _functionType.takesArbitraryParameters(), - isCallCode + isCallCode || isDelegateCall ); // Stack now: @@ -1435,8 +1438,10 @@ void ExpressionCompiler::appendExternalFunctionCall( m_context << eth::Instruction::DUP2; // CALL arguments: outSize, outOff, inSize, inOff (already present up to here) - // value, addr, gas (stack top) - if (_functionType.valueSet()) + // [value,] addr, gas (stack top) + if (isDelegateCall) + solAssert(!_functionType.valueSet(), "Value set for delegatecall"); + else if (_functionType.valueSet()) m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(valueStackPos)); else m_context << u256(0); @@ -1446,20 +1451,22 @@ void ExpressionCompiler::appendExternalFunctionCall( m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos)); else { - eth::EVMSchedule schedule;// TODO: Make relevant to current suppose context. + eth::EVMSchedule schedule; // send all gas except the amount needed to execute "SUB" and "CALL" // @todo this retains too much gas for now, needs to be fine-tuned. u256 gasNeededByCaller = schedule.callGas + 10; if (_functionType.valueSet()) gasNeededByCaller += schedule.callValueTransferGas; - if (!isCallCode) + if (!isCallCode && !isDelegateCall) gasNeededByCaller += schedule.callNewAccountGas; // we never know m_context << gasNeededByCaller << eth::Instruction::GAS << eth::Instruction::SUB; } - if (isCallCode) + if (isDelegateCall) + m_context << eth::Instruction::DELEGATECALL; + else if (isCallCode) m_context << eth::Instruction::CALLCODE; else m_context << eth::Instruction::CALL; diff --git a/libsolidity/formal/Why3Translator.h b/libsolidity/formal/Why3Translator.h index f4315a7a..588b6d80 100644 --- a/libsolidity/formal/Why3Translator.h +++ b/libsolidity/formal/Why3Translator.h @@ -52,7 +52,7 @@ public: std::string translation() const; private: - /// Returns an error. + /// Creates an error and adds it to errors list. void error(ASTNode const& _node, std::string const& _description); /// Reports a fatal error and throws. void fatalError(ASTNode const& _node, std::string const& _description); diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 517d0055..c7f98184 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -101,7 +101,7 @@ public: /// Sets the given source code as the only source unit apart from standard sources and parses it. /// @returns false on error. bool parse(std::string const& _sourceCode); - /// Returns a list of the contract names in the sources. + /// @returns a list of the contract names in the sources. std::vector<std::string> contractNames() const; std::string defaultContractName() const; @@ -124,7 +124,7 @@ public: eth::LinkerObject const& object(std::string const& _contractName = "") const; /// @returns the runtime object for the contract. eth::LinkerObject const& runtimeObject(std::string const& _contractName = "") const; - /// @returns the bytecode of a contract that uses an already deployed contract via CALLCODE. + /// @returns the bytecode of a contract that uses an already deployed contract via DELEGATECALL. /// The returned bytes will contain a sequence of 20 bytes of the format "XXX...XXX" which have to /// substituted by the actual address. Note that this sequence starts end ends in three X /// characters but can contain anything in between. @@ -144,13 +144,13 @@ public: /// Prerequisite: Successful compilation. Json::Value streamAssembly(std::ostream& _outStream, std::string const& _contractName = "", StringMap _sourceCodes = StringMap(), bool _inJsonFormat = false) const; - /// Returns a string representing the contract interface in JSON. + /// @returns a string representing the contract interface in JSON. /// Prerequisite: Successful call to parse or compile. std::string const& interface(std::string const& _contractName = "") const; - /// Returns a string representing the contract interface in Solidity. + /// @returns a string representing the contract interface in Solidity. /// Prerequisite: Successful call to parse or compile. std::string const& solidityInterface(std::string const& _contractName = "") const; - /// Returns a string representing the contract's documentation in JSON. + /// @returns a string representing the contract's documentation in JSON. /// Prerequisite: Successful call to parse or compile. /// @param type The type of the documentation to get. /// Can be one of 4 types defined at @c DocumentationType diff --git a/libsolidity/interface/InterfaceHandler.h b/libsolidity/interface/InterfaceHandler.h index 30b8f520..3e0a1660 100644 --- a/libsolidity/interface/InterfaceHandler.h +++ b/libsolidity/interface/InterfaceHandler.h @@ -85,7 +85,7 @@ public: static std::string devDocumentation(ContractDefinition const& _contractDef); private: - /// Returns concatenation of all content under the given tag name. + /// @returns concatenation of all content under the given tag name. static std::string extractDoc(std::multimap<std::string, DocTag> const& _tags, std::string const& _name); }; diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 9db3b3c4..a093cc5b 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -124,12 +124,12 @@ private: /// For source code of the form "a[][8]" ("IndexAccessStructure"), this is not possible to /// decide with constant look-ahead. LookAheadInfo peekStatementType() const; - /// Returns a typename parsed in look-ahead fashion from something like "a.b[8][2**70]". + /// @returns a typename parsed in look-ahead fashion from something like "a.b[8][2**70]". ASTPointer<TypeName> typeNameIndexAccessStructure( std::vector<ASTPointer<PrimaryExpression>> const& _path, std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> const& _indices ); - /// Returns an expression parsed in look-ahead fashion from something like "a.b[8][2**70]". + /// @returns an expression parsed in look-ahead fashion from something like "a.b[8][2**70]". ASTPointer<Expression> expressionFromIndexAccessStructure( std::vector<ASTPointer<PrimaryExpression>> const& _path, std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> const& _indices diff --git a/libsolidity/parsing/Scanner.h b/libsolidity/parsing/Scanner.h index 8dde922d..cffcec8e 100644 --- a/libsolidity/parsing/Scanner.h +++ b/libsolidity/parsing/Scanner.h @@ -108,13 +108,13 @@ public: /// Resets scanner to the start of input. void reset(); - /// Returns the next token and advances input + /// @returns the next token and advances input Token::Value next(); ///@{ ///@name Information about the current token - /// Returns the current token + /// @returns the current token Token::Value currentToken() { return m_currentToken.token; @@ -138,7 +138,7 @@ public: ///@{ ///@name Information about the next token - /// Returns the next token without advancing input. + /// @returns the next token without advancing input. Token::Value peekNextToken() const { return m_nextToken.token; } SourceLocation peekLocation() const { return m_nextToken.location; } std::string const& peekLiteral() const { return m_nextToken.literal; } diff --git a/libsolidity/parsing/Token.cpp b/libsolidity/parsing/Token.cpp index 78a90559..3812a83f 100644 --- a/libsolidity/parsing/Token.cpp +++ b/libsolidity/parsing/Token.cpp @@ -42,6 +42,7 @@ #include <map> #include <libsolidity/parsing/Token.h> +#include <boost/range/iterator_range.hpp> using namespace std; @@ -66,6 +67,13 @@ void ElementaryTypeNameToken::assertDetails(Token::Value _baseType, unsigned con "No elementary type " + string(Token::toString(_baseType)) + to_string(_first) + "." ); } + else if (_baseType == Token::UFixedMxN || _baseType == Token::FixedMxN) + { + solAssert( + _first + _second <= 256 && _first % 8 == 0 && _second % 8 == 0, + "No elementary type " + string(Token::toString(_baseType)) + to_string(_first) + "x" + to_string(_second) + "." + ); + } m_token = _baseType; m_firstNumber = _first; m_secondNumber = _second; @@ -101,26 +109,26 @@ char const Token::m_tokenType[] = { TOKEN_LIST(KT, KK) }; -unsigned Token::extractM(string const& _literal) +int Token::parseSize(string::const_iterator _begin, string::const_iterator _end) { try { - unsigned short m = stoi(_literal); + unsigned int m = boost::lexical_cast<int>(boost::make_iterator_range(_begin, _end)); return m; } - catch(out_of_range& e) + catch(boost::bad_lexical_cast const&) { - return 0; + return -1; } } -tuple<Token::Value, unsigned short, unsigned short> Token::fromIdentifierOrKeyword(string const& _literal) +tuple<Token::Value, unsigned int, unsigned int> Token::fromIdentifierOrKeyword(string const& _literal) { auto positionM = find_if(_literal.begin(), _literal.end(), ::isdigit); if (positionM != _literal.end()) { string baseType(_literal.begin(), positionM); auto positionX = find_if_not(positionM, _literal.end(), ::isdigit); - unsigned short m = extractM(string(positionM, positionX)); + int m = parseSize(positionM, positionX); Token::Value keyword = keywordByName(baseType); if (keyword == Token::Bytes) { @@ -137,6 +145,29 @@ tuple<Token::Value, unsigned short, unsigned short> Token::fromIdentifierOrKeywo return make_tuple(Token::IntM, m, 0); } } + else if (keyword == Token::UFixed || keyword == Token::Fixed) + { + if ( + positionM < positionX && + positionX < _literal.end() && + *positionX == 'x' && + all_of(positionX + 1, _literal.end(), ::isdigit) + ) { + int n = parseSize(positionX + 1, _literal.end()); + if ( + 0 < m && m < 256 && + 0 < n && n < 256 && + m + n <= 256 && + m % 8 == 0 && + n % 8 == 0 + ) { + if (keyword == Token::UFixed) + return make_tuple(Token::UFixed, m, n); + else + return make_tuple(Token::Fixed, m, n); + } + } + } return make_tuple(Token::Identifier, 0, 0); } return make_tuple(keywordByName(_literal), 0, 0); diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h index a64eded5..31646f8d 100644 --- a/libsolidity/parsing/Token.h +++ b/libsolidity/parsing/Token.h @@ -143,6 +143,7 @@ namespace solidity \ /* Keywords */ \ K(Anonymous, "anonymous", 0) \ + K(Assembly, "assembly", 0) \ K(Break, "break", 0) \ K(Const, "constant", 0) \ K(Continue, "continue", 0) \ @@ -198,8 +199,10 @@ namespace solidity K(String, "string", 0) \ K(Address, "address", 0) \ K(Bool, "bool", 0) \ - K(Real, "real", 0) \ - K(UReal, "ureal", 0) \ + K(Fixed, "fixed", 0) \ + T(FixedMxN, "fixedMxN", 0) \ + K(UFixed, "ufixed", 0) \ + T(UFixedMxN, "ufixedMxN", 0) \ T(TypesEnd, NULL, 0) /* used as type enum end marker */ \ \ /* Literals */ \ @@ -218,6 +221,7 @@ namespace solidity K(Case, "case", 0) \ K(Catch, "catch", 0) \ K(Final, "final", 0) \ + K(Inline, "inline", 0) \ K(Let, "let", 0) \ K(Match, "match", 0) \ K(Of, "of", 0) \ @@ -249,7 +253,7 @@ public: }; #undef T - // Returns a string corresponding to the C++ token name + // @returns a string corresponding to the C++ token name // (e.g. "LT" for the token LT). static char const* name(Value tok) { @@ -283,7 +287,7 @@ public: static bool isEtherSubdenomination(Value op) { return op == SubWei || op == SubSzabo || op == SubFinney || op == SubEther; } static bool isTimeSubdenomination(Value op) { return op == SubSecond || op == SubMinute || op == SubHour || op == SubDay || op == SubWeek || op == SubYear; } - // Returns a string corresponding to the JS token string + // @returns a string corresponding to the JS token string // (.e., "<" for the token LT) or NULL if the token doesn't // have a (unique) string (e.g. an IDENTIFIER). static char const* toString(Value tok) @@ -292,7 +296,7 @@ public: return m_string[tok]; } - // Returns the precedence > 0 for binary and compare + // @returns the precedence > 0 for binary and compare // operators; returns 0 otherwise. static int precedence(Value tok) { @@ -300,13 +304,11 @@ public: return m_precedence[tok]; } - static std::tuple<Token::Value, unsigned short, unsigned short> fromIdentifierOrKeyword(std::string const& _literal); + static std::tuple<Token::Value, unsigned int, unsigned int> fromIdentifierOrKeyword(std::string const& _literal); private: - // extractM provides a safe way to extract numbers, - // if out_of_range error is thrown, they returns 0s, therefore securing - // the variable's identity as an identifier. - static unsigned extractM(std::string const& _literal); + // @returns -1 on error (invalid digit or number too large) + static int parseSize(std::string::const_iterator _begin, std::string::const_iterator _end); // @returns the keyword with name @a _name or Token::Identifier of no such keyword exists. static Token::Value keywordByName(std::string const& _name); static char const* const m_name[NUM_TOKENS]; |