solidity 0.1.1 → 0.1.2

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: e72e223ba2202849d7dbb405a56b1edf7345b911813b3449bbf2059a9ebe87e5
4
- data.tar.gz: 2aa7d53cc55bc04929440cb3c49c99b85cc3efe0a151d24f9b887c2ac6297f09
3
+ metadata.gz: 2450cdadc297a615031d2a910fc70e39b6a29514ee4387e532bb3a7febec7fb4
4
+ data.tar.gz: 572f8c43f7cc641fc3d970b00287eec3e9adf7412ad046950d0bfa116930822c
5
5
  SHA512:
6
- metadata.gz: 25a530da83da24bbbf6ae85bc97a4ecac8d27eb0745d2952f3f43fda6ad3422021d798edffcafc9e03afcf6bd6d0c7985103fec52caa34987ffdb5d84a8699fd
7
- data.tar.gz: '09339328d15e47d6d9a6345f000cbc1dee7fce14dee04e14765f82add73824dbce6fa41ba0dfe1a190059b5aeef93b6c27dc3acf759f67bb0348556098f127e5'
6
+ metadata.gz: 2cdb28abe2cafb57f53df2d07af8a61c0f4c80177b0267bd7de2fa1afb96d423ff2399d628f11f34edd6896eaaeb4af3ebed5aa2b3489817c49c20560a536818
7
+ data.tar.gz: bcef0cdea7f22b7960db8269738d612d6a51f46626560762e8e85ffd52dc343e8a3d652de74b1d4c6ca89ee98fe7a1066a4de85535b5c704e1d6aa732bef7033
data/README.md CHANGED
@@ -24,9 +24,7 @@ Get / generate outline from source in the solidity (`.sol`) contract programming
24
24
  ].each do |addr|
25
25
 
26
26
  path = "awesome-contracts/address/#{addr}/contract.sol"
27
- txt = read_text( path )
28
-
29
- parser = Solidity::Parser.new( txt )
27
+ parser = Solidity::Parser.read( path )
30
28
 
31
29
  puts "---"
32
30
  puts "outline:"
@@ -67,6 +65,7 @@ library Address
67
65
  library Base64
68
66
  abstract contract Context
69
67
  library MerkleProof
68
+ interface ERC721A__IERC721Receiver
70
69
  contract ERC721A is IERC721A
71
70
  interface IERC721A
72
71
  ```
@@ -3,7 +3,7 @@ module Solidity
3
3
 
4
4
  MAJOR = 0
5
5
  MINOR = 1
6
- PATCH = 1
6
+ PATCH = 2
7
7
  VERSION = [MAJOR,MINOR,PATCH].join('.')
8
8
 
9
9
  def self.version
data/lib/solidity.rb CHANGED
@@ -10,74 +10,132 @@ require_relative 'solidity/version' # note: let version always go first
10
10
  module Solidity
11
11
 
12
12
  class Parser
13
+
14
+ def self.read( path )
15
+ txt = read_text( path )
16
+ new( txt )
17
+ end
18
+
19
+
20
+
13
21
  def initialize( txt )
14
22
  @txt = txt
15
23
  end
16
24
 
17
25
 
18
- SINGLE_COMMENT_RX = %r{^[ ]*//}
19
- MULTI_COMMENT_BEGIN_RX = %r{^[ ]*/\*}
20
- MULTI_COMMENT_END_RX = %r{\*/[ ]*$}
26
+ ###############
27
+ ## quotes
28
+ ##
29
+ ## note: regex pattern \\ needs to get escaped twice, thus, \\.
30
+ ## and for literal \\ use \\\\\.
31
+
32
+ ## => \\\\. -- allow backslash escapes e.g. \n \t \\ etc.
33
+ ## => [^`] -- everything except backquote
34
+
35
+ ## todo/fix - check if [^`] includes/matches newline too (yes)? -- add \n for multi-line!
36
+
37
+ SINGLE_QUOTE = %r{'
38
+ ( \\\\. | [^'] )*
39
+ '}x
21
40
 
22
- ID = '[a-zA-Z][a-zA-Z0-9]*'
41
+ DOUBLE_QUOTE = %r{"
42
+ ( \\\\. | [^"] )*
43
+ "}x
23
44
 
24
- PRAGMA_RX = %r{^[ ]*pragma}
25
- LIBRARY_RX = %r{^[ ]*library[ ]+(?<id>#{ID})[ \{]}
26
- ABSTRACT_CONTRACT_RX = %r{^[ ]*abstract[ ]+contract[ ]+(?<id>#{ID})[ \{]}
27
- CONTRACT_RX = %r{^[ ]*contract[ ]+(?<id>#{ID})[ \{]}
28
- INTERFACE_RX = %r{^[ ]*interface[ ]+(?<id>#{ID})[ \{]}
29
45
 
46
+ NAME = /[a-zA-Z][a-zA-Z0-9_]*/
47
+ END_OF_LINE = /\n|$/
48
+ ## inline comments (multi- or end-of-line)
49
+ END_OF_LINE_OR_COMMENT_OR_KEYWORD_OR_QUOTE = / \n
50
+ | $
51
+ | (?=['"])
52
+ | (?=\/(\/|\*))
53
+ | (?=pragma\b)
54
+ | (?=contract\b)
55
+ | (?=abstract\b)
56
+ | (?=library\b)
57
+ | (?=interface\b)
58
+ /x
59
+
60
+
61
+ def _norm_whitespace( str )
62
+ ## change newlines to spaces and
63
+ ## all multiple spaces to one
64
+ str = str.gsub( /[ \t\n\r]+/, ' ' )
65
+ str.strip
66
+ end
30
67
 
31
68
  def _quick_pass_one
32
- tree = []
33
- node = nil
69
+ ## note: CANNOT handle inline comments
70
+ ## in pragma, contract, etc. (get "silently" slurped)
71
+ ## report a parse error - if comments slurped - why? why not?
72
+ ##
34
73
 
35
- inside_comment = false
36
74
 
37
- @txt.each_line do |line|
38
- line = line.chomp ## remove trailing newline
39
- ## pp line
75
+ tree = []
40
76
 
41
- if inside_comment
42
- node[1] << line
43
- if MULTI_COMMENT_END_RX.match( line )
44
- tree << node
45
- inside_comment = false
46
- end
47
- else
48
- if SINGLE_COMMENT_RX.match( line ) # end-of-line comments
49
- line = line.strip ## remove leading & trailing spaces
50
- ## note: fold end-of-line comments into a block (if not separated by newline)
51
- node = tree[-1]
52
- if node.is_a?( Array ) &&
53
- node[0] == :comment && node[1][0].start_with?( '//' )
54
- node[1] << line
55
- else
56
- tree << [:comment, [line]]
57
- end
58
- elsif MULTI_COMMENT_BEGIN_RX.match( line )
59
- inside_comment = true
60
- node = [:comment, [line]]
61
- elsif PRAGMA_RX.match( line )
62
- line = line.strip
63
- tree << [:pragma, line]
64
- elsif LIBRARY_RX.match( line )
65
- line = line.strip
66
- tree << [:library, line]
67
- elsif ABSTRACT_CONTRACT_RX.match( line )
68
- line = line.strip
69
- tree << [:abstract_contract, line]
70
- elsif CONTRACT_RX.match( line )
71
- line = line.strip
72
- tree << [:contract, line]
73
- elsif INTERFACE_RX.match( line )
74
- line = line.strip
75
- tree << [:interface, line]
76
- else
77
- tree << line
78
- end
79
- end
80
- end # each_line
77
+ s = StringScanner.new( @txt )
78
+
79
+ loop do
80
+ s.skip( /[ \t]+/ ) ## note: do NOT skip newlines here; pass along blank/empty lines for now - why? why not?
81
+ if s.check( "'" ) ## single-quoted string
82
+ str = s.scan( SINGLE_QUOTE )
83
+ tree << [:string, str]
84
+ elsif s.check( '"' ) ## double-quoted string
85
+ str = s.scan( DOUBLE_QUOTE )
86
+ tree << [:string, str]
87
+ elsif s.check( '/*' )
88
+ comment = s.scan_until( /\*\// )
89
+ ## print "multi-line comment:"
90
+ ## pp comment
91
+ tree << [:comment, comment]
92
+ elsif s.check( '//' )
93
+ comment = s.scan_until( END_OF_LINE ).rstrip
94
+ ## print "comment:"
95
+ ## pp comment
96
+ tree << [:comment, comment]
97
+ else
98
+ name = s.check( NAME )
99
+ case name
100
+ when 'pragma'
101
+ code = s.scan_until( /;/ )
102
+ code = _norm_whitespace( code )
103
+ ## print "pragma:"
104
+ ## pp code
105
+ tree << [:pragma, code]
106
+ when 'contract'
107
+ code = s.scan_until( /(?=\{)/ )
108
+ code = _norm_whitespace( code )
109
+ ## print "contract:"
110
+ ## pp code
111
+ tree << [:contract, code]
112
+ when 'abstract'
113
+ code = s.scan_until( /(?=\{)/ )
114
+ code = _norm_whitespace( code )
115
+ ## print "abstract contract:"
116
+ ## pp code
117
+ tree << [:abstract_contract, code]
118
+ when 'library'
119
+ code = s.scan_until( /(?=\{)/ )
120
+ code = _norm_whitespace( code )
121
+ ## print "library:"
122
+ ## pp code
123
+ tree << [:library, code]
124
+ when 'interface'
125
+ code = s.scan_until( /(?=\{)/ )
126
+ code = _norm_whitespace( code )
127
+ ## print "interface:"
128
+ ## pp code
129
+ tree << [:interface, code]
130
+ else
131
+ ## slurp chunk ,that is, until newline or comment or tracked keyword
132
+ chunk = s.scan_until( END_OF_LINE_OR_COMMENT_OR_KEYWORD_OR_QUOTE ).rstrip
133
+ ## puts "chunk: >#{chunk.inspect}<"
134
+ tree << chunk
135
+ end
136
+ end
137
+ break if s.eos?
138
+ end
81
139
 
82
140
  tree
83
141
  end
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.1
4
+ version: 0.1.2
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-01-29 00:00:00.000000000 Z
11
+ date: 2023-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cocos