summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2019-11-26 07:05:23 +0100
committerGeorg Brandl <georg@python.org>2019-11-26 07:05:30 +0100
commitbe43f33d42387e0122244a1a6a99493976459831 (patch)
treee50ad1058d234fb9e89c5f1a6d5b63a7d3e063c9
parent731339d7654fa69d3eaa5ebe2a1d29b1cee6724e (diff)
downloadpygments-git-be43f33d42387e0122244a1a6a99493976459831.tar.gz
Add Solidity lexer.
Fixes #1214
-rw-r--r--CHANGES1
-rw-r--r--pygments/lexers/_mapping.py1
-rw-r--r--pygments/lexers/solidity.py93
-rw-r--r--tests/examplefiles/test.sol74
4 files changed, 169 insertions, 0 deletions
diff --git a/CHANGES b/CHANGES
index 5aa72f03..b12d578c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -17,6 +17,7 @@ Version 2.5.0
* Zeek (new name for Bro) (PR#1264)
* Notmuch (PR#1269)
* Scdoc (PR#1268)
+ * Solidity
- Updated lexers:
diff --git a/pygments/lexers/_mapping.py b/pygments/lexers/_mapping.py
index c6fc606c..acb71ad9 100644
--- a/pygments/lexers/_mapping.py
+++ b/pygments/lexers/_mapping.py
@@ -405,6 +405,7 @@ LEXERS = {
'SmartyLexer': ('pygments.lexers.templates', 'Smarty', ('smarty',), ('*.tpl',), ('application/x-smarty',)),
'SnobolLexer': ('pygments.lexers.snobol', 'Snobol', ('snobol',), ('*.snobol',), ('text/x-snobol',)),
'SnowballLexer': ('pygments.lexers.dsls', 'Snowball', ('snowball',), ('*.sbl',), ()),
+ 'SolidityLexer': ('pygments.lexers.solidity', 'Solidity', ('solidity',), ('*.sol',), ()),
'SourcePawnLexer': ('pygments.lexers.pawn', 'SourcePawn', ('sp',), ('*.sp',), ('text/x-sourcepawn',)),
'SourcesListLexer': ('pygments.lexers.installers', 'Debian Sourcelist', ('sourceslist', 'sources.list', 'debsources'), ('sources.list',), ()),
'SparqlLexer': ('pygments.lexers.rdf', 'SPARQL', ('sparql',), ('*.rq', '*.sparql'), ('application/sparql-query',)),
diff --git a/pygments/lexers/solidity.py b/pygments/lexers/solidity.py
new file mode 100644
index 00000000..99668371
--- /dev/null
+++ b/pygments/lexers/solidity.py
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+"""
+ pygments.lexers.solidity
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Lexers for Solidity.
+
+ :copyright: Copyright 2006-2019 by the Pygments team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+from pygments.lexer import RegexLexer, bygroups, include, words
+from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
+ Number, Punctuation
+
+__all__ = ['SolidityLexer']
+
+
+class SolidityLexer(RegexLexer):
+ """
+ For Solidity source code.
+
+ .. versionadded:: 2.5
+ """
+
+ name = 'Solidity'
+ aliases = ['solidity']
+ filenames = ['*.sol']
+ mimetypes = []
+
+ flags = re.MULTILINE | re.UNICODE
+
+ datatype = (
+ r'\b(address|bool|((bytes|hash|int|string|uint)(8|16|24|32|40|48|56|64'
+ r'|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208'
+ r'|216|224|232|240|248|256)?))\b'
+ )
+
+ tokens = {
+ 'root': [
+ include('whitespace'),
+ include('comments'),
+ (r'\bpragma\s+solidity\b', Keyword, 'pragma'),
+ (r'\b(contract)(\s+)([a-zA-Z_]\w*)',
+ bygroups(Keyword, Text.WhiteSpace, Name.Entity)),
+ (datatype + r'(\s+)((external|public|internal|private)\s+)?' +
+ r'([a-zA-Z_]\w*)',
+ bygroups(Keyword.Type, None, None, None, Text.WhiteSpace, Keyword,
+ None, Name.Variable)),
+ (r'\b(enum|event|function|struct)(\s+)([a-zA-Z_]\w*)',
+ bygroups(Keyword.Type, Text.WhiteSpace, Name.Variable)),
+ (r'\b(msg|block|tx)\.([A-Za-z_][A-Za-z0-9_]*)\b', Keyword),
+ (words((
+ 'block', 'break', 'constant', 'constructor', 'continue',
+ 'contract', 'do', 'else', 'external', 'false', 'for',
+ 'function', 'if', 'import', 'inherited', 'internal', 'is',
+ 'library', 'mapping', 'memory', 'modifier', 'msg', 'new',
+ 'payable', 'private', 'public', 'require', 'return',
+ 'returns', 'struct', 'suicide', 'throw', 'this', 'true',
+ 'tx', 'var', 'while'), prefix=r'\b', suffix=r'\b'),
+ Keyword.Type),
+ (words(('keccak256',), prefix=r'\b', suffix=r'\b'), Name.Builtin),
+ (datatype, Keyword.Type),
+ include('constants'),
+ (r'[a-zA-Z_]\w*', Text),
+ (r'[!<=>+*/-]', Operator),
+ (r'[.;:{}(),\[\]]', Punctuation)
+ ],
+ 'comments': [
+ (r'//(\n|[\w\W]*?[^\\]\n)', Comment.Single),
+ (r'/(\\\n)?[*][\w\W]*?[*](\\\n)?/', Comment.Multiline),
+ (r'/(\\\n)?[*][\w\W]*', Comment.Multiline)
+ ],
+ 'constants': [
+ (r'("([\\]"|.)*?")', String.Double),
+ (r"('([\\]'|.)*?')", String.Single),
+ (r'\b0[xX][0-9a-fA-F]+\b', Number.Hex),
+ (r'\b\d+\b', Number.Decimal),
+ ],
+ 'pragma': [
+ include('whitespace'),
+ include('comments'),
+ (r'(\^|>=|<)(\s*)(\d+\.\d+\.\d+)',
+ bygroups(Operator, Text.WhiteSpace, Keyword)),
+ (r';', Punctuation, '#pop')
+ ],
+ 'whitespace': [
+ (r'\s+', Text.WhiteSpace),
+ (r'\n', Text.WhiteSpace)
+ ]
+ }
diff --git a/tests/examplefiles/test.sol b/tests/examplefiles/test.sol
new file mode 100644
index 00000000..f7a6495e
--- /dev/null
+++ b/tests/examplefiles/test.sol
@@ -0,0 +1,74 @@
+pragma solidity ^0.4.20;
+
+pragma solidity >=0.4.0 <0.7.0;
+
+// one-line singleline comment
+
+/* one-line multiline comment */
+
+/*
+ multi-line multiline comment
+*/
+
+contract ContractName {
+
+ address public publicaddress;
+
+ uint varname1 = 1234;
+ int varname2 = 0x12abcdEF;
+
+ string astringsingle = 'test "string" value\' single';
+ string astringdouble = "test 'string' value\" double";
+
+ enum State {
+ NotStarted,
+ WorkInProgress,
+ Done
+ }
+ State public state;
+
+ struct AStruct {
+ string name;
+ uint8 type;
+ }
+
+ mapping(address => AStruct) registry;
+
+ event Paid(uint256 value);
+ event Received(uint256 time);
+ event Withdraw(uint256 value);
+
+ function addRegistry(string _name, uint8 _type) {
+ AStruct memory newItem = AStruct({
+ name: _name,
+ type: _type
+ });
+
+ registry[msg.sender] = newItem;
+ }
+
+ function getHash(AStruct item) returns(uint) {
+ return uint(keccak256(item.name, item.type));
+ }
+
+ function pay() public payable {
+ require(msg.sender == astronaut);
+ state = State.Paid;
+ Paid(msg.value);
+ }
+
+ function receive() public {
+ require(msg.sender == arbiter);
+ require(state == State.Paid);
+ state = State.Received;
+ Received(now);
+ }
+
+ function withdraw() public {
+ require(msg.sender == shipper);
+ require(state == State.Received);
+ state = State.Withdrawn;
+ Withdraw(this.balance);
+ shipper.transfer(this.balance);
+ }
+}