solidity 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a34efb053c8fd9211832cedb2a99a05362f10fb3e43323d6bca7cd69783a88d
4
- data.tar.gz: 3e113d90344d4a4745836b3b8bea5f18f4ac3c621d56914e5610c331f25dba20
3
+ metadata.gz: 7039440cfd0f451c6d990c35cdbef3a23309b86ce3c380cb4716ad9647b27f5d
4
+ data.tar.gz: e69c2a1a4273a5c9abc2858d5fe5a9cc27dc46656acf321e39cb520addb579c1
5
5
  SHA512:
6
- metadata.gz: ea91690f94b665991f5f2e6934def21c1dd70ac475efc1e6cd578d84a05e31a7437dac0c1c3f9bffecb1283655ba3454d663f04a4ff190246ce240b4ea900535
7
- data.tar.gz: f8b3f08e0691d3cfc34b25ab6652a632f41df90a6d0d593f699971886301a329fcb4f6fac048d3d041432d446030b89338cf9cabd01239a00a4a69aa50de9c45
6
+ metadata.gz: a97fb7eeac099baf18b2045fa60351b97ac36207c68517553498c35912f4eed73727aa94d8e9b70a7b2512e9efeb865d764161fa56876c1fcac2f87782333049
7
+ data.tar.gz: 68abe7d1bb83abdbd5a45f6cd3303a9ff368ae87f73046a9f3d40858e4407fc4f8fb300e599aca915a68921a9d3ff286b88ae4b29746e5fcd7b2ac0d2634f324
data/Manifest.txt CHANGED
@@ -3,5 +3,6 @@ Manifest.txt
3
3
  README.md
4
4
  Rakefile
5
5
  lib/solidity.rb
6
+ lib/solidity/lexer.rb
6
7
  lib/solidity/parser.rb
7
8
  lib/solidity/version.rb
data/README.md CHANGED
@@ -1,23 +1,6 @@
1
-
2
- ---
3
-
4
- _The Ruby Programming Language for Contract / Transaction Scripts on the Blockchain World Computer - Yes, It's Just Ruby_
5
-
6
- **sruby - Small, Smart, Secure, Safe, Solid & Sound (S6) Ruby**
7
-
8
- sruby is a subset of mruby that is a subset of "classic" ruby.
9
-
10
-
11
- For more see the [**Red Paper »**](https://github.com/s6ruby/redpaper)
12
-
13
- ---
14
-
15
-
16
-
17
-
18
1
  # Solidity
19
2
 
20
- solidity gem - (fuzzy) parser for (crypto) contracts for ethereum & co.
3
+ solidity gem - (fuzzy) lexer & parser for (crypto) contracts for ethereum & co.
21
4
 
22
5
 
23
6
  * home :: [github.com/rubycocos/blockchain](https://github.com/rubycocos/blockchain)
@@ -29,25 +12,7 @@ solidity gem - (fuzzy) parser for (crypto) contracts for ethereum & co.
29
12
 
30
13
  ## New to the Solidity (Contract) Programming Language?
31
14
 
32
- _Official_
33
-
34
- Solidity Language @ <https://soliditylang.org>
35
-
36
- - Read the Docs @ <https://docs.soliditylang.org/en/latest/>
37
- - Blog @ <https://blog.soliditylang.org>
38
- - Forum @ <https://forum.soliditylang.org>
39
- - Source @ <https://github.com/ethereum/solidity>
40
-
41
- <!-- break -->
42
-
43
- _More_
44
-
45
- Solidity by Example @ <https://solidity-by-example.org>
46
-
47
- Learn X in Y Minutes (Where X=Solidity) @ <https://learnxinyminutes.com/docs/solidity>
48
-
49
- Awesome Solidity @ <https://github.com/bkrem/awesome-solidity>
50
-
15
+ See [**Awesome Solidity @ Open Blockchains »**](https://github.com/openblockchains/awesome-solidity)
51
16
 
52
17
 
53
18
 
@@ -55,7 +20,6 @@ Awesome Solidity @ <https://github.com/bkrem/awesome-solidity>
55
20
  ## Usage
56
21
 
57
22
  Get / generate outline from source in the solidity (`.sol`) contract programming language:
58
-
59
23
  ```ruby
60
24
  [
61
25
  "0x34625ecaa75c0ea33733a05c584f4cf112c10b6b",
@@ -92,6 +56,36 @@ library Base64
92
56
  ```
93
57
 
94
58
 
59
+ Note: The outline includes:
60
+
61
+ 1. contract definitions e.g.
62
+
63
+ contract NounsDescriptor is INounsDescriptor, Ownable
64
+
65
+ 2. abstract contract definitions e.g.
66
+
67
+ abstract contract Ownable is Context
68
+ abstract contract Context
69
+
70
+ 3. library definitions e.g.
71
+
72
+ library Strings
73
+ library NFTDescriptor
74
+ library MultiPartRLEToSVG
75
+ library Base64
76
+
77
+ 4. interface definitions e.g.
78
+
79
+ interface INounsDescriptor
80
+ interface INounsSeeder
81
+
82
+
83
+
84
+
85
+ <!-- break -->
86
+
87
+ More outline samples:
88
+
95
89
  ```
96
90
  outline:
97
91
  contract Indelible is ERC721A, ReentrancyGuard, Ownable
data/Rakefile CHANGED
@@ -14,7 +14,7 @@ Hoe.spec 'solidity' do
14
14
 
15
15
  self.version = Solidity::VERSION
16
16
 
17
- self.summary = "solidity - (fuzzy) parser for (crypto) contracts for ethereum & co."
17
+ self.summary = "solidity - (fuzzy) lexer & parser for (crypto) contracts for ethereum & co."
18
18
  self.description = summary
19
19
 
20
20
  self.urls = { home: 'https://github.com/rubycocos/blockchain' }
@@ -0,0 +1,166 @@
1
+ module Solidity
2
+
3
+ class Lexer
4
+
5
+ def self.read( path )
6
+ txt = read_text( path )
7
+ new( txt )
8
+ end
9
+
10
+
11
+
12
+ def initialize( txt )
13
+ @txt = txt
14
+ @tokens = tokenize
15
+ @pos = 0
16
+ end
17
+
18
+
19
+
20
+ ###############
21
+ ## quotes
22
+ ##
23
+ ## note: regex pattern \\ needs to get escaped twice, thus, \\.
24
+ ## and for literal \\ use \\\\\.
25
+
26
+ ## => \\\\. -- allow backslash escapes e.g. \n \t \\ etc.
27
+ ## => [^`] -- everything except backquote
28
+
29
+ ## todo/fix - check if [^`] includes/matches newline too (yes)? -- add \n for multi-line!
30
+
31
+
32
+ ## from the solidity grammar
33
+ ##
34
+ ## StringLiteralFragment
35
+ ## : 'unicode'? '"' DoubleQuotedStringCharacter* '"'
36
+ ## | 'unicode'? '\'' SingleQuotedStringCharacter* '\'' ;
37
+ ##
38
+ ## fragment
39
+ ## DoubleQuotedStringCharacter
40
+ ## : ~["\r\n\\] | ('\\' .) ;
41
+ ##
42
+ ## fragment
43
+ ## SingleQuotedStringCharacter
44
+ ## : ~['\r\n\\] | ('\\' .) ;
45
+
46
+
47
+ SINGLE_QUOTE = %r{'
48
+ ( \\\\. | [^'] )*
49
+ '}x
50
+
51
+ DOUBLE_QUOTE = %r{"
52
+ ( \\\\. | [^"] )*
53
+ "}x
54
+
55
+
56
+ ## from the solidity grammar
57
+ ## > An identifier in solidity has to start with a letter,
58
+ ## > a dollar-sign or an underscore and
59
+ ## > may additionally contain numbers after the first symbol.
60
+ ##
61
+ ## Identifier
62
+ ## : IdentifierStart IdentifierPart* ;
63
+ ##
64
+ ## fragment
65
+ ## IdentifierStart
66
+ ## : [a-zA-Z$_] ;
67
+ ##
68
+ ## fragment
69
+ ## IdentifierPart
70
+ ## : [a-zA-Z0-9$_] ;
71
+
72
+ NAME = /[a-zA-Z$_][a-zA-Z0-9$_]*/
73
+
74
+
75
+ ## from the solidity grammar
76
+ ##
77
+ ## COMMENT
78
+ ## : '/*' .*? '*/' ;
79
+ ##
80
+ ## LINE_COMMENT
81
+ ## : '//' ~[\r\n]* ;
82
+
83
+
84
+ def tokenize
85
+ t = []
86
+ s = StringScanner.new( @txt )
87
+
88
+ until s.eos? ## loop until hitting end-of-string (file)
89
+ if s.check( /[ \t]*\/\*/ )
90
+ ## note: auto-slurp leading (optinal) spaces!!!! - why? why not?
91
+ comment = s.scan_until( /\*\// )
92
+ ## print "multi-line comment:"
93
+ ## pp comment
94
+ t << [:comment, comment.lstrip]
95
+ elsif s.check( /[ \t]*\/\// )
96
+ ## note: auto-slurp leading (optinal) spaces!!!! - why? why not?
97
+ ## note: auto-remove newline AND trailing whitespace - why? why not?
98
+ comment = s.scan_until( /\n|$/ ).strip
99
+ ## print "comment:"
100
+ ## pp comment
101
+ t << [:comment, comment]
102
+ elsif s.scan( /[ \t]+/ ) ## one or more spaces
103
+ ## note: (auto-)convert tab to space - why? why not?
104
+ t << [:sp, s.matched.gsub( /[\t]/, ' ') ]
105
+ elsif s.scan( /\r?\n/ ) ## check for (windows) carriage return (\r) - why? why not?
106
+ t << [:nl, "\n" ]
107
+ elsif s.check( "'" ) ## single-quoted string
108
+ str = s.scan( SINGLE_QUOTE )
109
+ t << [:string, str]
110
+ elsif s.check( '"' ) ## double-quoted string
111
+ str = s.scan( DOUBLE_QUOTE )
112
+ t << [:string, str]
113
+ elsif s.scan( NAME )
114
+ name = s.matched
115
+ case name
116
+ when 'pragma' then t << [:pragma, name]
117
+ when 'contract' then t << [:contract, name]
118
+ when 'abstract' then t << [:abstract, name]
119
+ when 'library' then t << [:library, name]
120
+ when 'interface' then t << [:interface, name]
121
+ when 'function' then t << [:function, name]
122
+ when 'struct' then t << [:struct, name]
123
+ when 'enum' then t << [:enum, name]
124
+ when 'event' then t << [:event, name]
125
+ else
126
+ t << [:ident, name]
127
+ end
128
+ elsif s.scan( /;/ ) then t << [:';', ';']
129
+ elsif s.scan( /\{/ ) then t << [:'{', '{']
130
+ elsif s.scan( /\}/ ) then t << [:'}', '}']
131
+ else ## slurp until hitting a "tracked" token again
132
+ last = t[-1]
133
+ if last.is_a?( String )
134
+ last << s.getch ## append char to last chunk
135
+ else
136
+ t << s.getch ## start a new chunk
137
+ end
138
+ end
139
+ end
140
+ t
141
+ end
142
+
143
+
144
+
145
+ def reset() @pos = 0; end
146
+ def pos() @pos; end
147
+ def peek
148
+ ## note: returns token type for now (e.g. :string, :sp, etc.)
149
+ ## and NOT token struct for now - why? why not?
150
+ t = @tokens[@pos]
151
+ t.nil? || t.is_a?( String ) ? t : t[0]
152
+ end
153
+ def next
154
+ ## note: returns type lexeme (string content) for now
155
+ ## and NOT token struct for now - why? why not?
156
+ t = @tokens[@pos]
157
+ tt = t.nil? || t.is_a?( String ) ? t : t[1]
158
+ @pos += 1 unless t.nil?
159
+ tt
160
+ end
161
+ def eos?() peek().nil?; end
162
+
163
+
164
+
165
+ end # class Lexer
166
+ end # module Solidity
@@ -14,40 +14,24 @@ class Parser
14
14
  end
15
15
 
16
16
 
17
- ###############
18
- ## quotes
19
- ##
20
- ## note: regex pattern \\ needs to get escaped twice, thus, \\.
21
- ## and for literal \\ use \\\\\.
22
17
 
23
- ## => \\\\. -- allow backslash escapes e.g. \n \t \\ etc.
24
- ## => [^`] -- everything except backquote
25
18
 
26
- ## todo/fix - check if [^`] includes/matches newline too (yes)? -- add \n for multi-line!
27
-
28
- SINGLE_QUOTE = %r{'
29
- ( \\\\. | [^'] )*
30
- '}x
31
-
32
- DOUBLE_QUOTE = %r{"
33
- ( \\\\. | [^"] )*
34
- "}x
35
-
36
-
37
- NAME = /[a-zA-Z][a-zA-Z0-9_]*/
38
- END_OF_LINE = /\n|$/
39
- ## inline comments (multi- or end-of-line)
40
- END_OF_LINE_OR_COMMENT_OR_KEYWORD_OR_QUOTE = / \n
41
- | $
42
- | (?=['"])
43
- | (?=\/(\/|\*))
44
- | (?=\bpragma\b)
45
- | (?=\bcontract\b)
46
- | (?=\babstract\b)
47
- | (?=\blibrary\b)
48
- | (?=\binterface\b)
49
- /x
50
19
 
20
+ def _scan_until( lex, tt, include: false )
21
+ code = String.new('')
22
+ while (peek=lex.peek) != tt do
23
+ ## note: turn inline comments into a single space
24
+ code << if peek == :comment
25
+ lex.next
26
+ ' '
27
+ else
28
+ lex.next
29
+ end
30
+ end
31
+ code << lex.next if include ## include ';' too - why? why not?
32
+ code = _norm_whitespace( code )
33
+ code
34
+ end
51
35
 
52
36
  def _norm_whitespace( str )
53
37
  ## change newlines to spaces and
@@ -56,82 +40,62 @@ class Parser
56
40
  str.strip
57
41
  end
58
42
 
43
+
59
44
  def _quick_pass_one
60
- ## note: CANNOT handle inline comments
61
- ## in pragma, contract, etc. (get "silently" slurped)
62
- ## report a parse error - if comments slurped - why? why not?
63
- ##
45
+ tree = []
64
46
 
47
+ lex = Lexer.new( @txt )
65
48
 
66
- tree = []
49
+ until lex.eos?
50
+ while lex.peek == :sp do ## note: do NOT skip newlines here; pass along blank/empty lines for now - why? why not?
51
+ lex.next
52
+ end
67
53
 
68
- s = StringScanner.new( @txt )
69
-
70
- loop do
71
- s.skip( /[ \t]+/ ) ## note: do NOT skip newlines here; pass along blank/empty lines for now - why? why not?
72
- if s.check( "'" ) ## single-quoted string
73
- str = s.scan( SINGLE_QUOTE )
74
- tree << [:string, str]
75
- elsif s.check( '"' ) ## double-quoted string
76
- str = s.scan( DOUBLE_QUOTE )
77
- tree << [:string, str]
78
- elsif s.check( '/*' )
79
- comment = s.scan_until( /\*\// )
80
- ## print "multi-line comment:"
81
- ## pp comment
82
- tree << [:comment, comment]
83
- elsif s.check( '//' )
84
- comment = s.scan_until( END_OF_LINE ).rstrip
85
- ## print "comment:"
86
- ## pp comment
87
- tree << [:comment, comment]
88
- else
89
- name = s.check( NAME )
90
- case name
91
- when 'pragma'
92
- code = s.scan_until( /;/ )
93
- code = _norm_whitespace( code )
54
+ case lex.peek
55
+ when :comment ## single or multi-line comment
56
+ tree << [:comment, lex.next]
57
+ when :pragma
58
+ code = _scan_until( lex, :';',
59
+ include: true )
94
60
  ## print "pragma:"
95
61
  ## pp code
96
62
  tree << [:pragma, code]
97
- when 'contract'
98
- code = s.scan_until( /(?=\{)/ )
99
- code = _norm_whitespace( code )
63
+ when :contract
64
+ code = _scan_until( lex, :'{' )
100
65
  ## print "contract:"
101
66
  ## pp code
102
67
  tree << [:contract, code]
103
- when 'abstract'
104
- code = s.scan_until( /(?=\{)/ )
105
- code = _norm_whitespace( code )
106
- ## print "abstract contract:"
107
- ## pp code
108
- tree << [:abstract_contract, code]
109
- when 'library'
110
- code = s.scan_until( /(?=\{)/ )
111
- code = _norm_whitespace( code )
112
- ## print "library:"
113
- ## pp code
114
- tree << [:library, code]
115
- when 'interface'
116
- code = s.scan_until( /(?=\{)/ )
117
- code = _norm_whitespace( code )
118
- ## print "interface:"
119
- ## pp code
120
- tree << [:interface, code]
121
- else
68
+ when :abstract
69
+ code = _scan_until( lex, :'{' )
70
+ ## print "abstract contract:"
71
+ ## pp code
72
+ tree << [:abstract_contract, code]
73
+ when :library
74
+ code = _scan_until( lex, :'{' )
75
+ ## print "library:"
76
+ ## pp code
77
+ tree << [:library, code]
78
+ when :interface
79
+ code = _scan_until( lex, :'{' )
80
+ ## print "interface:"
81
+ ## pp code
82
+ tree << [:interface, code]
83
+ else
122
84
  ## slurp chunk ,that is, until newline or comment or tracked keyword
123
- chunk = s.scan_until( END_OF_LINE_OR_COMMENT_OR_KEYWORD_OR_QUOTE ).rstrip
124
- ## puts "chunk: >#{chunk.inspect}<"
125
- tree << chunk
126
- end
85
+ last = tree[-1]
86
+ if last.is_a?( String )
87
+ last << lex.next ## append lexeme to last chunk
88
+ else
89
+ tree << lex.next ## start a new chunk
90
+ end
127
91
  end
128
- break if s.eos?
129
- end
92
+ end
130
93
 
131
94
  tree
132
95
  end
133
96
 
134
97
 
98
+
135
99
  def outline
136
100
  buf = String.new( '' )
137
101
  tree = _quick_pass_one
@@ -2,7 +2,7 @@
2
2
  module Solidity
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- PATCH = 3
5
+ PATCH = 5
6
6
  VERSION = [MAJOR,MINOR,PATCH].join('.')
7
7
 
8
8
  def self.version
data/lib/solidity.rb CHANGED
@@ -3,6 +3,7 @@ require 'cocos'
3
3
 
4
4
  ## our own code
5
5
  require_relative 'solidity/version' # note: let version always go first
6
+ require_relative 'solidity/lexer'
6
7
  require_relative 'solidity/parser'
7
8
 
8
9
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solidity
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-01 00:00:00.000000000 Z
11
+ date: 2023-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cocos
@@ -58,7 +58,8 @@ dependencies:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '3.23'
61
- description: solidity - (fuzzy) parser for (crypto) contracts for ethereum & co.
61
+ description: solidity - (fuzzy) lexer & parser for (crypto) contracts for ethereum
62
+ & co.
62
63
  email: wwwmake@googlegroups.com
63
64
  executables: []
64
65
  extensions: []
@@ -72,6 +73,7 @@ files:
72
73
  - README.md
73
74
  - Rakefile
74
75
  - lib/solidity.rb
76
+ - lib/solidity/lexer.rb
75
77
  - lib/solidity/parser.rb
76
78
  - lib/solidity/version.rb
77
79
  homepage: https://github.com/rubycocos/blockchain
@@ -98,5 +100,5 @@ requirements: []
98
100
  rubygems_version: 3.3.7
99
101
  signing_key:
100
102
  specification_version: 4
101
- summary: solidity - (fuzzy) parser for (crypto) contracts for ethereum & co.
103
+ summary: solidity - (fuzzy) lexer & parser for (crypto) contracts for ethereum & co.
102
104
  test_files: []