solidity 0.1.4 → 0.2.0

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: 3920e32ab53156b256507811437d64f62f38bd42472aecb5c51a4fd3eb2f57e1
4
- data.tar.gz: 4a5c36c583ba102881417af5d184c6351ef9d6a1f20154ab6096fb4722694bc6
3
+ metadata.gz: 92328b174c85612323db86d1d50654934da8b46d878831b99d49086673cda0df
4
+ data.tar.gz: 487298452cd42474065d694a87ef23f8425371dfd8ce29742c38b38227beaade
5
5
  SHA512:
6
- metadata.gz: b7227cdec56deceba0230c0f8946ea0182e2e144919bb2b0227d52a19c4085d89a0b2f3a62c796b162c9fba59880d5ee1cb154bfc0f5de1455cb4bd353d4602d
7
- data.tar.gz: 9840c43aade93aaec0b0222c2db7dc4f50246565da9e52c69363fe599e43bed8e0e800ac31349a846ab7cfeb4e28126bde9fcfd8d6a85b884d9d26240b1fc35b
6
+ metadata.gz: 18ee1772f0ea6d2c5579d955301140bf7930e3f9b94810682da34d5929c9c93c7b10f62e7781d01abe16527f54502837cd2424c773b0177c3fc767ba43734706
7
+ data.tar.gz: 1dcd402d83754b2bee56794fe465f02f7f874770188dffb971ff3fe34ea7aa0f084416f6a0f64508e90132d2ea03795e2f364c29f023b7f767e62d0d450a682d
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
 
@@ -95,24 +60,24 @@ Note: The outline includes:
95
60
 
96
61
  1. contract definitions e.g.
97
62
 
98
- contract NounsDescriptor is INounsDescriptor, Ownable
63
+ contract NounsDescriptor is INounsDescriptor, Ownable
99
64
 
100
65
  2. abstract contract definitions e.g.
101
66
 
102
- abstract contract Ownable is Context
103
- abstract contract Context
67
+ abstract contract Ownable is Context
68
+ abstract contract Context
104
69
 
105
70
  3. library definitions e.g.
106
71
 
107
- library Strings
108
- library NFTDescriptor
109
- library MultiPartRLEToSVG
110
- library Base64
72
+ library Strings
73
+ library NFTDescriptor
74
+ library MultiPartRLEToSVG
75
+ library Base64
111
76
 
112
77
  4. interface definitions e.g.
113
78
 
114
- interface INounsDescriptor
115
- interface INounsSeeder
79
+ interface INounsDescriptor
80
+ interface INounsSeeder
116
81
 
117
82
 
118
83
 
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,187 @@
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
+ DOUBLE_QUOTE = %r{"
47
+ ( \\\\. | [^"\r\n\\] )*
48
+ "}x
49
+
50
+ SINGLE_QUOTE = %r{'
51
+ ( \\\\. | [^'\r\n\\] )*
52
+ '}x
53
+
54
+
55
+ ## from the solidity grammar
56
+ ## > An identifier in solidity has to start with a letter,
57
+ ## > a dollar-sign or an underscore and
58
+ ## > may additionally contain numbers after the first symbol.
59
+ ##
60
+ ## Identifier
61
+ ## : IdentifierStart IdentifierPart* ;
62
+ ##
63
+ ## fragment
64
+ ## IdentifierStart
65
+ ## : [a-zA-Z$_] ;
66
+ ##
67
+ ## fragment
68
+ ## IdentifierPart
69
+ ## : [a-zA-Z0-9$_] ;
70
+
71
+ NAME = /[a-zA-Z$_][a-zA-Z0-9$_]*/
72
+
73
+
74
+ ## from the solidity grammar
75
+ ##
76
+ ## COMMENT
77
+ ## : '/*' .*? '*/' ;
78
+ ## LINE_COMMENT
79
+ ## : '//' ~[\r\n]* ;
80
+
81
+ COMMENT = %r{/\*
82
+ .*?
83
+ \*/}x
84
+
85
+ LINE_COMMENT = %r{//
86
+ [^\r\n]*}x
87
+
88
+ def tokenize
89
+ t = []
90
+ s = StringScanner.new( @txt )
91
+
92
+ until s.eos? ## loop until hitting end-of-string (file)
93
+ if s.scan( /[ \t]+/ ) ## one or more spaces
94
+ ## note: (auto-)convert tab to space - why? why not?
95
+ t << [:sp, s.matched.gsub( /[\t]/, ' ') ]
96
+ elsif s.scan( /\r?\n/ ) ## check for (windows) carriage return (\r) - why? why not?
97
+ t << [:nl, "\n" ]
98
+ elsif s.scan( COMMENT )
99
+ t << [:comment, s.matched]
100
+ elsif s.scan( LINE_COMMENT )
101
+ t << [:comment, s.matched]
102
+ elsif s.scan( DOUBLE_QUOTE ) ## double-quoted string
103
+ t << [:string, s.matched]
104
+ elsif s.scan( SINGLE_QUOTE ) ## single-quoted string
105
+ t << [:string, s.matched]
106
+ elsif s.scan( NAME )
107
+ name = s.matched
108
+ case name
109
+ when 'pragma' then t << [:pragma, name]
110
+ when 'contract' then t << [:contract, name]
111
+ when 'abstract' then t << [:abstract, name]
112
+ when 'library' then t << [:library, name]
113
+ when 'interface' then t << [:interface, name]
114
+ when 'function' then t << [:function, name]
115
+ when 'struct' then t << [:struct, name]
116
+ when 'enum' then t << [:enum, name]
117
+ when 'event' then t << [:event, name]
118
+ else
119
+ t << [:ident, name]
120
+ end
121
+ elsif s.scan( /;/ ) then t << [:';', ';']
122
+ elsif s.scan( /\{/ ) then t << [:'{', '{']
123
+ elsif s.scan( /\}/ ) then t << [:'}', '}']
124
+ else ## slurp until hitting a "tracked" token again
125
+ last = t[-1]
126
+ if last.is_a?( String )
127
+ last << s.getch ## append char to last chunk
128
+ else
129
+ t << s.getch ## start a new chunk
130
+ end
131
+ end
132
+ end
133
+ t
134
+ end
135
+
136
+
137
+
138
+ def reset() @pos = 0; end
139
+ def pos() @pos; end
140
+ def peek
141
+ ## note: returns token type for now (e.g. :string, :sp, etc.)
142
+ ## and NOT token struct for now - why? why not?
143
+ t = @tokens[@pos]
144
+ t.nil? || t.is_a?( String ) ? t : t[0]
145
+ end
146
+ def next
147
+ ## note: returns type lexeme (string content) for now
148
+ ## and NOT token struct for now - why? why not?
149
+ t = @tokens[@pos]
150
+ str = t.nil? || t.is_a?( String ) ? t : t[1]
151
+ @pos += 1 unless t.nil?
152
+ str
153
+ end
154
+ def eos?() peek().nil?; end
155
+
156
+
157
+
158
+
159
+ #################################################
160
+ # "higher-level" helpers
161
+ def scan_until( tt, include: false )
162
+ code = String.new('')
163
+ while (peek=self.peek) != tt do
164
+ ## note: turn inline comments into a single space
165
+ code << if peek == :comment
166
+ self.next ## note: next (w/o self) is parsed as keyword
167
+ ' '
168
+ else
169
+ self.next ## note: next (w/o self) is parsed as keyword
170
+ end
171
+ end
172
+ code << self.next if include ## include ';' too - why? why not?
173
+ code = _norm_whitespace( code )
174
+ code
175
+ end
176
+
177
+ def _norm_whitespace( str )
178
+ ## change newlines to spaces and
179
+ ## all multiple spaces to one
180
+ str = str.gsub( /[ \t\n\r]+/, ' ' )
181
+ str.strip
182
+ end
183
+
184
+
185
+
186
+ end # class Lexer
187
+ end # module Solidity
@@ -14,168 +14,62 @@ 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
-
23
- ## => \\\\. -- allow backslash escapes e.g. \n \t \\ etc.
24
- ## => [^`] -- everything except backquote
25
-
26
- ## todo/fix - check if [^`] includes/matches newline too (yes)? -- add \n for multi-line!
27
-
28
-
29
- ## from the solidity grammar
30
- ##
31
- ## StringLiteralFragment
32
- ## : 'unicode'? '"' DoubleQuotedStringCharacter* '"'
33
- ## | 'unicode'? '\'' SingleQuotedStringCharacter* '\'' ;
34
- ##
35
- ## fragment
36
- ## DoubleQuotedStringCharacter
37
- ## : ~["\r\n\\] | ('\\' .) ;
38
- ##
39
- ## fragment
40
- ## SingleQuotedStringCharacter
41
- ## : ~['\r\n\\] | ('\\' .) ;
42
-
43
-
44
- SINGLE_QUOTE = %r{'
45
- ( \\\\. | [^'] )*
46
- '}x
47
-
48
- DOUBLE_QUOTE = %r{"
49
- ( \\\\. | [^"] )*
50
- "}x
51
-
52
-
53
- ## from the solidity grammar
54
- ## > An identifier in solidity has to start with a letter,
55
- ## > a dollar-sign or an underscore and
56
- ## > may additionally contain numbers after the first symbol.
57
- ##
58
- ## Identifier
59
- ## : IdentifierStart IdentifierPart* ;
60
- ##
61
- ## fragment
62
- ## IdentifierStart
63
- ## : [a-zA-Z$_] ;
64
- ##
65
- ## fragment
66
- ## IdentifierPart
67
- ## : [a-zA-Z0-9$_] ;
68
-
69
- NAME = /[a-zA-Z$_][a-zA-Z0-9$_]*/
70
-
71
-
72
- END_OF_LINE = /\n|$/
73
- ## inline comments (multi- or end-of-line)
74
- END_OF_LINE_OR_COMMENT_OR_KEYWORD_OR_QUOTE = / \n
75
- | $
76
- | (?=['"])
77
- | (?=\/(\/|\*))
78
- | (?=\bpragma\b)
79
- | (?=\bcontract\b)
80
- | (?=\babstract\b)
81
- | (?=\blibrary\b)
82
- | (?=\binterface\b)
83
- /x
84
-
85
-
86
- ## from the solidity grammar
87
- ##
88
- ## COMMENT
89
- ## : '/*' .*? '*/' ;
90
- ##
91
- ## LINE_COMMENT
92
- ## : '//' ~[\r\n]* ;
93
-
94
-
95
-
96
- def _norm_whitespace( str )
97
- ## change newlines to spaces and
98
- ## all multiple spaces to one
99
- str = str.gsub( /[ \t\n\r]+/, ' ' )
100
- str.strip
101
- end
102
17
 
103
- def _quick_pass_one
104
- ## note: CANNOT handle inline comments
105
- ## in pragma, contract, etc. (get "silently" slurped)
106
- ## report a parse error - if comments slurped - why? why not?
107
- ##
108
18
 
109
19
 
20
+ def _quick_pass_one
110
21
  tree = []
111
22
 
112
- s = StringScanner.new( @txt )
113
-
114
- loop do
115
- s.skip( /[ \t]+/ ) ## note: do NOT skip newlines here; pass along blank/empty lines for now - why? why not?
116
- if s.check( "'" ) ## single-quoted string
117
- str = s.scan( SINGLE_QUOTE )
118
- tree << [:string, str]
119
- elsif s.check( '"' ) ## double-quoted string
120
- str = s.scan( DOUBLE_QUOTE )
121
- tree << [:string, str]
122
- elsif s.check( '/*' )
123
- comment = s.scan_until( /\*\// )
124
- ## print "multi-line comment:"
125
- ## pp comment
126
- tree << [:comment, comment]
127
- elsif s.check( '//' )
128
- comment = s.scan_until( END_OF_LINE ).rstrip
129
- ## print "comment:"
130
- ## pp comment
131
- tree << [:comment, comment]
132
- else
133
- name = s.check( NAME )
134
- case name
135
- when 'pragma'
136
- code = s.scan_until( /;/ )
137
- code = _norm_whitespace( code )
23
+ lex = Lexer.new( @txt )
24
+
25
+ until lex.eos?
26
+ case lex.peek
27
+ when :comment ## single or multi-line comment
28
+ tree << [:comment, lex.next]
29
+ ## note: if next token is newline - slurp / ignore
30
+ lex.next if lex.peek == :nl
31
+ when :pragma
32
+ code = lex.scan_until( :';',
33
+ include: true )
138
34
  ## print "pragma:"
139
35
  ## pp code
140
36
  tree << [:pragma, code]
141
- when 'contract'
142
- code = s.scan_until( /(?=\{)/ )
143
- code = _norm_whitespace( code )
37
+ when :contract
38
+ code = lex.scan_until( :'{' )
144
39
  ## print "contract:"
145
40
  ## pp code
146
41
  tree << [:contract, code]
147
- when 'abstract'
148
- code = s.scan_until( /(?=\{)/ )
149
- code = _norm_whitespace( code )
150
- ## print "abstract contract:"
151
- ## pp code
152
- tree << [:abstract_contract, code]
153
- when 'library'
154
- code = s.scan_until( /(?=\{)/ )
155
- code = _norm_whitespace( code )
156
- ## print "library:"
157
- ## pp code
158
- tree << [:library, code]
159
- when 'interface'
160
- code = s.scan_until( /(?=\{)/ )
161
- code = _norm_whitespace( code )
162
- ## print "interface:"
163
- ## pp code
164
- tree << [:interface, code]
165
- else
42
+ when :abstract
43
+ code = lex.scan_until( :'{' )
44
+ ## print "abstract contract:"
45
+ ## pp code
46
+ tree << [:abstract_contract, code]
47
+ when :library
48
+ code = lex.scan_until( :'{' )
49
+ ## print "library:"
50
+ ## pp code
51
+ tree << [:library, code]
52
+ when :interface
53
+ code = lex.scan_until( :'{' )
54
+ ## print "interface:"
55
+ ## pp code
56
+ tree << [:interface, code]
57
+ else
166
58
  ## slurp chunk ,that is, until newline or comment or tracked keyword
167
- chunk = s.scan_until( END_OF_LINE_OR_COMMENT_OR_KEYWORD_OR_QUOTE ).rstrip
168
- ## puts "chunk: >#{chunk.inspect}<"
169
- tree << chunk
170
- end
59
+ last = tree[-1]
60
+ if last.is_a?( String )
61
+ last << lex.next ## append lexeme to last chunk
62
+ else
63
+ tree << lex.next ## start a new chunk
64
+ end
171
65
  end
172
- break if s.eos?
173
- end
66
+ end
174
67
 
175
68
  tree
176
69
  end
177
70
 
178
71
 
72
+
179
73
  def outline
180
74
  buf = String.new( '' )
181
75
  tree = _quick_pass_one
@@ -1,8 +1,8 @@
1
1
 
2
2
  module Solidity
3
3
  MAJOR = 0
4
- MINOR = 1
5
- PATCH = 4
4
+ MINOR = 2
5
+ PATCH = 0
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.4
4
+ version: 0.2.0
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-07 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: []