solidity 0.1.3 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
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: []