solidity 0.1.4 → 0.2.0

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: 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: []