├── .gitignore ├── LICENSE ├── Readme.md ├── build └── parser.js ├── compiler.js ├── grammar └── solidityx.pegjs ├── index.js ├── main.js ├── package-lock.json ├── package.json └── test ├── default.js ├── voting.solx └── voting_orig.sol /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | 61 | # build files 62 | out.sol 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Loom Network 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | ## SolidityX 2 | 3 | SolidityX is an opinionated version of Solidity. Currently it works as a source to source compiler. In future we are adding extensions to the Ethereum Virtual Machine (EVM). 4 | 5 | *** Beta software, changing daily. Don't use for production workloads yet *** 6 | 7 | 8 | ## To run 9 | 10 | ``` 11 | node solx test/voting.solx voting.sol 12 | ``` 13 | 14 | ## Setup 15 | 16 | ``` 17 | npm install 18 | ``` 19 | 20 | 21 | ## Features (Beta) 22 | 23 | ``` 24 | String manipulation 25 | Swarm Integration 26 | IPFS Integration 27 | Cross blockchain communication 28 | ``` 29 | 30 | 31 | ### References 32 | 33 | Builds on the PegJs Parser from ConsenSys -------------------------------------------------------------------------------- /compiler.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | var path = require("path"); 3 | 4 | module.exports = { 5 | compileToSolidityToFile: function(originalSrc, astResult, outputFile) { 6 | var data = this.compileToSolidity(astResult, originalSrc) 7 | if(outputFile == null || outputFile =='') { 8 | //ouput to stdout, 9 | return console.log(data) 10 | } 11 | var fs = require('fs'); 12 | fs.writeFile(path.resolve(outputFile), data, function(err) { 13 | if(err) { 14 | return console.log(err); 15 | } 16 | 17 | console.log("The file was saved!"); 18 | }); 19 | }, 20 | 21 | compileToSolidity: function(ast, originalSrc) { 22 | //Compiler is really stupid right now 23 | //it replaces lines in the origin source file 24 | //later one we will have a more stringent compiler 25 | //this is for prototyping 26 | 27 | //let newAst = transformer(ast); 28 | let output = this.codeGenerator(ast, originalSrc); 29 | 30 | console.log(JSON.stringify(ast, null, 2)); 31 | return output 32 | }, 33 | 34 | codeGenerator: function(node, originalSrc) { 35 | var outputData = ""; 36 | 37 | if(node instanceof Array) { 38 | console.log("looping array") 39 | out = "" 40 | for (let item of node) { 41 | console.log("array item-" + item) 42 | out = out + this.codeGenerator(item, originalSrc) 43 | } 44 | return out 45 | } 46 | if(node == undefined) { 47 | console.log("undefined-" + node) 48 | return 49 | } 50 | 51 | console.log("node-" + node.type + ' start-' + node.start + ' end-' + node.end) 52 | 53 | switch (node.type) { 54 | 55 | case 'PragmaXStatement': 56 | return ( 57 | '// pragmax solidityX ' + node.start_version.operator + node.start_version.version + '\n' 58 | ); 59 | 60 | case 'FunctionDeclaration' : 61 | //TODO for now we wont traverse FunctionDeclaration 62 | return originalSrc.slice(node.start, node.end) + '\n' 63 | case 'BlockStatement' : 64 | //TODO for now we wont traverse blockstatements 65 | return originalSrc.slice(node.start, node.end) + '\n' 66 | case 'ContractStatement': 67 | return ( 68 | 'contract ' + node.name + ' { \n' + 69 | this.codeGenerator(node.body, originalSrc) + 70 | '\n } \n' 71 | ); 72 | 73 | case 'Program': 74 | return ( 75 | this.codeGenerator(node.body, originalSrc) + 76 | '\n //Generated with SolidityX compiler, http://solidityx.org for more information' 77 | ); 78 | // And if we haven't recognized the node, we'll throw an error. 79 | default: 80 | console.log("unknown type- " + node.type + " start-" + node.start ) 81 | var ret = originalSrc.slice(node.start, node.end) + '\n' 82 | 83 | if(node.body != undefined) { 84 | return ret + this.codeGenerator(node.body, originalSrc) 85 | } 86 | return ret 87 | //throw new TypeError(node.type); 88 | } 89 | 90 | output = originalSrc 91 | return outputData 92 | } 93 | }; 94 | -------------------------------------------------------------------------------- /grammar/solidityx.pegjs: -------------------------------------------------------------------------------- 1 | /* 2 | * Solidity Grammar, based on Javascript grammar. 3 | * The following comment is from that grammar: 4 | * ================== 5 | * 6 | * Based on grammar from ECMA-262, 5.1 Edition [1]. Generated parser builds a 7 | * syntax tree compatible with Mozilla SpiderMonkey Parser API [2]. Properties 8 | * and node types reflecting features not present in ECMA-262 are not included. 9 | * 10 | * Limitations: 11 | * 12 | * * Non-BMP characters are completely ignored to avoid surrogate pair 13 | * handling. 14 | * 15 | * * One can create identifiers containing illegal characters using Unicode 16 | * escape sequences. For example, "abcd\u0020efgh" is not a valid 17 | * identifier, but it is accepted by the parser. 18 | * 19 | * * Strict mode is not recognized. This means that within strict mode code, 20 | * "implements", "interface", "let", "package", "private", "protected", 21 | * "public", "static" and "yield" can be used as names. Many other 22 | * restrictions and exceptions from Annex C are also not applied. 23 | * 24 | * All the limitations could be resolved, but the costs would likely outweigh 25 | * the benefits. 26 | * 27 | * Many thanks to inimino [3] for his grammar [4] which helped me to solve some 28 | * problems (such as automatic semicolon insertion) and also served to double 29 | * check that I converted the original grammar correctly. 30 | * 31 | * [1] http://www.ecma-international.org/publications/standards/Ecma-262.htm 32 | * [2] https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API 33 | * [3] http://inimino.org/~inimino/blog/ 34 | * [4] http://boshi.inimino.org/3box/asof/1270029991384/PEG/ECMAScript_unified.peg 35 | */ 36 | 37 | { 38 | var TYPES_TO_PROPERTY_NAMES = { 39 | CallExpression: "callee", 40 | MemberExpression: "object", 41 | }; 42 | 43 | function filledArray(count, value) { 44 | var result = new Array(count), i; 45 | 46 | for (i = 0; i < count; i++) { 47 | result[i] = value; 48 | } 49 | 50 | return result; 51 | } 52 | 53 | function extractOptional(optional, index) { 54 | return optional ? optional[index] : null; 55 | } 56 | 57 | function extractList(list, index) { 58 | var result = new Array(list.length), i; 59 | 60 | for (i = 0; i < list.length; i++) { 61 | result[i] = list[i][index]; 62 | } 63 | 64 | return result; 65 | } 66 | 67 | function buildList(head, tail, index) { 68 | return [head].concat(extractList(tail, index)); 69 | } 70 | 71 | function buildTree(head, tail, builder) { 72 | var result = head, i; 73 | 74 | for (i = 0; i < tail.length; i++) { 75 | result = builder(result, tail[i]); 76 | } 77 | 78 | return result; 79 | } 80 | 81 | function buildBinaryExpression(head, tail) { 82 | return buildTree(head, tail, function(result, element) { 83 | return { 84 | type: "BinaryExpression", 85 | operator: element[1], 86 | left: result, 87 | right: element[3], 88 | start: location().start.offset, 89 | end: location().end.offset 90 | }; 91 | }); 92 | } 93 | 94 | function buildLogicalExpression(head, tail) { 95 | return buildTree(head, tail, function(result, element) { 96 | return { 97 | type: "LogicalExpression", 98 | operator: element[1], 99 | left: result, 100 | right: element[3], 101 | start: location().start.offset, 102 | end: location().end.offset 103 | }; 104 | }); 105 | } 106 | 107 | function optionalList(value) { 108 | return value !== null ? value : []; 109 | } 110 | 111 | function normalizeVersionLiteral(item) { 112 | if (item.constructor.name === 'Array') { 113 | item [1] = item [1].join (''); 114 | item = item.join (''); 115 | } 116 | 117 | return item; 118 | } 119 | } 120 | 121 | Start 122 | = __ program:Program __ { return program; } 123 | 124 | /* ----- A.1 Lexical Grammar ----- */ 125 | 126 | SourceCharacter 127 | = . 128 | 129 | WhiteSpace "whitespace" 130 | = "\t" 131 | / "\v" 132 | / "\f" 133 | / " " 134 | / "\u00A0" 135 | / "\uFEFF" 136 | / Zs 137 | 138 | LineTerminator 139 | = [\n\r\u2028\u2029] 140 | 141 | LineTerminatorSequence "end of line" 142 | = "\n" 143 | / "\r\n" 144 | / "\r" 145 | / "\u2028" 146 | / "\u2029" 147 | 148 | Comment "comment" 149 | = MultiLineComment 150 | / SingleLineComment 151 | 152 | MultiLineComment 153 | = "/*" (!"*/" SourceCharacter)* "*/" 154 | 155 | MultiLineCommentNoLineTerminator 156 | = "/*" (!("*/" / LineTerminator) SourceCharacter)* "*/" 157 | 158 | SingleLineComment 159 | = "//" (!LineTerminator SourceCharacter)* 160 | 161 | Identifier 162 | = !ReservedWord name:IdentifierName { return name; } 163 | 164 | IdentifierName "identifier" 165 | = head:IdentifierStart tail:IdentifierPart* { 166 | return { 167 | type: "Identifier", 168 | name: head + tail.join(""), 169 | start: location().start.offset, 170 | end: location().end.offset 171 | }; 172 | } 173 | 174 | IdentifierStart 175 | = UnicodeLetter 176 | / "$" 177 | / "_" 178 | 179 | IdentifierPart 180 | = IdentifierStart 181 | / UnicodeDigit 182 | 183 | UnicodeLetter 184 | = Lu 185 | / Ll 186 | / Lt 187 | / Lm 188 | / Lo 189 | / Nl 190 | 191 | UnicodeCombiningMark 192 | = Mn 193 | / Mc 194 | 195 | UnicodeDigit 196 | = Nd 197 | 198 | UnicodeConnectorPunctuation 199 | = Pc 200 | 201 | ReservedWord 202 | = Keyword 203 | / FutureReservedWord 204 | / NullToken 205 | / BooleanLiteral 206 | 207 | Keyword 208 | = BreakToken 209 | / ContinueToken 210 | / ContractToken 211 | / InterfaceToken 212 | / DeleteToken 213 | / DoToken 214 | / ElseToken 215 | / ForToken 216 | / FunctionToken 217 | / HexToken 218 | / IfToken 219 | / ImportToken 220 | / NewToken 221 | / PragmaToken 222 | / PragmaXToken 223 | / ReturnToken 224 | / ReturnsToken 225 | / ThisToken 226 | / ThrowToken 227 | / VarToken 228 | / WhileToken 229 | 230 | FutureReservedWord 231 | = ClassToken 232 | / ExportToken 233 | / ExtendsToken 234 | 235 | Literal 236 | = BooleanLiteral 237 | / DenominationLiteral 238 | / NumericLiteral 239 | / HexStringLiteral 240 | / StringLiteral 241 | / VersionLiteral 242 | 243 | BooleanLiteral 244 | = TrueToken { return { type: "Literal", value: true, start: location().start.offset, end: location().end.offset }; } 245 | / FalseToken { return { type: "Literal", value: false, start: location().start.offset, end: location().end.offset }; } 246 | 247 | /* 248 | * The "!(IdentifierStart / DecimalDigit)" predicate is not part of the official 249 | * grammar, it comes from text in section 7.8.3. 250 | */ 251 | NumericLiteral "number" 252 | = literal:HexIntegerLiteral !(IdentifierStart / DecimalDigit) { 253 | return literal; 254 | } 255 | / literal:DecimalLiteral !(IdentifierStart / DecimalDigit) { 256 | return literal; 257 | } 258 | 259 | Denomination 260 | = token:(WeiToken 261 | / SzaboToken 262 | / FinneyToken 263 | / EtherToken 264 | / SecondsToken 265 | / MinutesToken 266 | / HoursToken 267 | / DaysToken 268 | / WeeksToken 269 | / YearsToken) 270 | { 271 | return token[0]; 272 | } 273 | 274 | DenominationLiteral 275 | = literal:NumericLiteral __ denomination:Denomination 276 | { 277 | return { 278 | type: "DenominationLiteral", 279 | literal: literal.value, 280 | denomination: denomination, 281 | start: location().start.offset, 282 | end: location().end.offset 283 | } 284 | } 285 | 286 | DecimalLiteral 287 | = DecimalIntegerLiteral "." DecimalDigit* ExponentPart? { 288 | return { type: "Literal", value: parseFloat(text()), start: location().start.offset, end: location().end.offset }; 289 | } 290 | / "." DecimalDigit+ ExponentPart? { 291 | return { type: "Literal", value: parseFloat(text()), start: location().start.offset, end: location().end.offset }; 292 | } 293 | / DecimalIntegerLiteral ExponentPart? { 294 | return { type: "Literal", value: parseFloat(text()), start: location().start.offset, end: location().end.offset }; 295 | } 296 | 297 | DecimalIntegerLiteral 298 | = "0" 299 | / NonZeroDigit DecimalDigit* 300 | 301 | DecimalDigit 302 | = [0-9] 303 | 304 | NonZeroDigit 305 | = [1-9] 306 | 307 | ExponentPart 308 | = ExponentIndicator SignedInteger 309 | 310 | ExponentIndicator 311 | = "e"i 312 | 313 | SignedInteger 314 | = [+-]? DecimalDigit+ 315 | 316 | HexIntegerLiteral 317 | = "0x"i digits:$HexDigit+ { 318 | return { type: "Literal", value: "0x" + digits, start: location().start.offset, end: location().end.offset }; 319 | } 320 | 321 | HexDigit 322 | = [0-9a-f]i 323 | 324 | StringLiteral "string" 325 | = '"' chars:DoubleStringCharacter* '"' { 326 | return { type: "Literal", value: chars.join(""), start: location().start.offset, end: location().end.offset }; 327 | } 328 | / "'" chars:SingleStringCharacter* "'" { 329 | return { type: "Literal", value: chars.join(""), start: location().start.offset, end: location().end.offset }; 330 | } 331 | 332 | HexStringLiteral 333 | = HexToken StringLiteral 334 | 335 | DoubleStringCharacter 336 | = !('"' / "\\" / LineTerminator) SourceCharacter { return text(); } 337 | / "\\" sequence:EscapeSequence { return sequence; } 338 | / LineContinuation 339 | 340 | SingleStringCharacter 341 | = !("'" / "\\" / LineTerminator) SourceCharacter { return text(); } 342 | / "\\" sequence:EscapeSequence { return sequence; } 343 | / LineContinuation 344 | 345 | LineContinuation 346 | = "\\" LineTerminatorSequence { return ""; } 347 | 348 | EscapeSequence 349 | = CharacterEscapeSequence 350 | / "0" !DecimalDigit { return "\0"; } 351 | / HexEscapeSequence 352 | / UnicodeEscapeSequence 353 | 354 | CharacterEscapeSequence 355 | = SingleEscapeCharacter 356 | / NonEscapeCharacter 357 | 358 | SingleEscapeCharacter 359 | = "'" 360 | / '"' 361 | / "\\" 362 | / "b" { return "\b"; } 363 | / "f" { return "\f"; } 364 | / "n" { return "\n"; } 365 | / "r" { return "\r"; } 366 | / "t" { return "\t"; } 367 | / "v" { return "\x0B"; } // IE does not recognize "\v". 368 | 369 | NonEscapeCharacter 370 | = !(EscapeCharacter / LineTerminator) SourceCharacter { return text(); } 371 | 372 | EscapeCharacter 373 | = SingleEscapeCharacter 374 | / DecimalDigit 375 | / "x" 376 | / "u" 377 | 378 | HexEscapeSequence 379 | = "x" digits:$(HexDigit HexDigit) { 380 | return String.fromCharCode(parseInt(digits, 16)); 381 | } 382 | 383 | UnicodeEscapeSequence 384 | = "u" digits:$(HexDigit HexDigit HexDigit HexDigit) { 385 | return String.fromCharCode(parseInt(digits, 16)); 386 | } 387 | 388 | VersionLiteral 389 | = operator:(RelationalOperator / EqualityOperator / BitwiseXOROperator)? __ ("v")? major:DecimalIntegerLiteral "." minor:DecimalIntegerLiteral "." patch:DecimalIntegerLiteral { 390 | return { 391 | type: "VersionLiteral", 392 | operator: operator, 393 | version: (normalizeVersionLiteral(major) + "." + normalizeVersionLiteral(minor) + "." + normalizeVersionLiteral(patch)) 394 | }; 395 | } 396 | 397 | /* 398 | * Unicode Character Categories 399 | * 400 | * Extracted from the following Unicode Character Database file: 401 | * 402 | * http://www.unicode.org/Public/8.0.0/ucd/extracted/DerivedGeneralCategory.txt 403 | * 404 | * Unix magic used: 405 | * 406 | * grep "; $CATEGORY" DerivedGeneralCategory.txt | # Filter characters 407 | * cut -f1 -d " " | # Extract code points 408 | * grep -v '[0-9a-fA-F]\{5\}' | # Exclude non-BMP characters 409 | * sed -e 's/\.\./-/' | # Adjust formatting 410 | * sed -e 's/\([0-9a-fA-F]\{4\}\)/\\u\1/g' | # Adjust formatting 411 | * tr -d '\n' # Join lines 412 | * 413 | * ECMA-262 allows using Unicode 3.0 or later, version 8.0.0 was the latest one 414 | * at the time of writing. 415 | * 416 | * Non-BMP characters are completely ignored to avoid surrogate pair handling 417 | * (detecting surrogate pairs isn't possible with a simple character class and 418 | * other methods would degrade performance). I don't consider it a big deal as 419 | * even parsers in JavaScript engines of common browsers seem to ignore them. 420 | */ 421 | 422 | // Letter, Lowercase 423 | Ll = [\u0061-\u007A\u00B5\u00DF-\u00F6\u00F8-\u00FF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137-\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148-\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E-\u0180\u0183\u0185\u0188\u018C-\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA-\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9-\u01BA\u01BD-\u01BF\u01C6\u01C9\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC-\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF-\u01F0\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F-\u0240\u0242\u0247\u0249\u024B\u024D\u024F-\u0293\u0295-\u02AF\u0371\u0373\u0377\u037B-\u037D\u0390\u03AC-\u03CE\u03D0-\u03D1\u03D5-\u03D7\u03D9\u03DB\u03DD\u03DF\u03E1\u03E3\u03E5\u03E7\u03E9\u03EB\u03ED\u03EF-\u03F3\u03F5\u03F8\u03FB-\u03FC\u0430-\u045F\u0461\u0463\u0465\u0467\u0469\u046B\u046D\u046F\u0471\u0473\u0475\u0477\u0479\u047B\u047D\u047F\u0481\u048B\u048D\u048F\u0491\u0493\u0495\u0497\u0499\u049B\u049D\u049F\u04A1\u04A3\u04A5\u04A7\u04A9\u04AB\u04AD\u04AF\u04B1\u04B3\u04B5\u04B7\u04B9\u04BB\u04BD\u04BF\u04C2\u04C4\u04C6\u04C8\u04CA\u04CC\u04CE-\u04CF\u04D1\u04D3\u04D5\u04D7\u04D9\u04DB\u04DD\u04DF\u04E1\u04E3\u04E5\u04E7\u04E9\u04EB\u04ED\u04EF\u04F1\u04F3\u04F5\u04F7\u04F9\u04FB\u04FD\u04FF\u0501\u0503\u0505\u0507\u0509\u050B\u050D\u050F\u0511\u0513\u0515\u0517\u0519\u051B\u051D\u051F\u0521\u0523\u0525\u0527\u0529\u052B\u052D\u052F\u0561-\u0587\u13F8-\u13FD\u1D00-\u1D2B\u1D6B-\u1D77\u1D79-\u1D9A\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFF-\u1F07\u1F10-\u1F15\u1F20-\u1F27\u1F30-\u1F37\u1F40-\u1F45\u1F50-\u1F57\u1F60-\u1F67\u1F70-\u1F7D\u1F80-\u1F87\u1F90-\u1F97\u1FA0-\u1FA7\u1FB0-\u1FB4\u1FB6-\u1FB7\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FC7\u1FD0-\u1FD3\u1FD6-\u1FD7\u1FE0-\u1FE7\u1FF2-\u1FF4\u1FF6-\u1FF7\u210A\u210E-\u210F\u2113\u212F\u2134\u2139\u213C-\u213D\u2146-\u2149\u214E\u2184\u2C30-\u2C5E\u2C61\u2C65-\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73-\u2C74\u2C76-\u2C7B\u2C81\u2C83\u2C85\u2C87\u2C89\u2C8B\u2C8D\u2C8F\u2C91\u2C93\u2C95\u2C97\u2C99\u2C9B\u2C9D\u2C9F\u2CA1\u2CA3\u2CA5\u2CA7\u2CA9\u2CAB\u2CAD\u2CAF\u2CB1\u2CB3\u2CB5\u2CB7\u2CB9\u2CBB\u2CBD\u2CBF\u2CC1\u2CC3\u2CC5\u2CC7\u2CC9\u2CCB\u2CCD\u2CCF\u2CD1\u2CD3\u2CD5\u2CD7\u2CD9\u2CDB\u2CDD\u2CDF\u2CE1\u2CE3-\u2CE4\u2CEC\u2CEE\u2CF3\u2D00-\u2D25\u2D27\u2D2D\uA641\uA643\uA645\uA647\uA649\uA64B\uA64D\uA64F\uA651\uA653\uA655\uA657\uA659\uA65B\uA65D\uA65F\uA661\uA663\uA665\uA667\uA669\uA66B\uA66D\uA681\uA683\uA685\uA687\uA689\uA68B\uA68D\uA68F\uA691\uA693\uA695\uA697\uA699\uA69B\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F\uA771-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787\uA78C\uA78E\uA791\uA793-\uA795\uA797\uA799\uA79B\uA79D\uA79F\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7B5\uA7B7\uA7FA\uAB30-\uAB5A\uAB60-\uAB65\uAB70-\uABBF\uFB00-\uFB06\uFB13-\uFB17\uFF41-\uFF5A] 424 | 425 | // Letter, Modifier 426 | Lm = [\u02B0-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0374\u037A\u0559\u0640\u06E5-\u06E6\u07F4-\u07F5\u07FA\u081A\u0824\u0828\u0971\u0E46\u0EC6\u10FC\u17D7\u1843\u1AA7\u1C78-\u1C7D\u1D2C-\u1D6A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\u2D6F\u2E2F\u3005\u3031-\u3035\u303B\u309D-\u309E\u30FC-\u30FE\uA015\uA4F8-\uA4FD\uA60C\uA67F\uA69C-\uA69D\uA717-\uA71F\uA770\uA788\uA7F8-\uA7F9\uA9CF\uA9E6\uAA70\uAADD\uAAF3-\uAAF4\uAB5C-\uAB5F\uFF70\uFF9E-\uFF9F] 427 | 428 | // Letter, Other 429 | Lo = [\u00AA\u00BA\u01BB\u01C0-\u01C3\u0294\u05D0-\u05EA\u05F0-\u05F2\u0620-\u063F\u0641-\u064A\u066E-\u066F\u0671-\u06D3\u06D5\u06EE-\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u0800-\u0815\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0972-\u0980\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0-\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B35-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0-\u0CE1\u0CF1-\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32-\u0E33\u0E40-\u0E45\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065-\u1066\u106E-\u1070\u1075-\u1081\u108E\u10D0-\u10FA\u10FD-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17DC\u1820-\u1842\u1844-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE-\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C77\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5-\u1CF6\u2135-\u2138\u2D30-\u2D67\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3006\u303C\u3041-\u3096\u309F\u30A1-\u30FA\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA014\uA016-\uA48C\uA4D0-\uA4F7\uA500-\uA60B\uA610-\uA61F\uA62A-\uA62B\uA66E\uA6A0-\uA6E5\uA78F\uA7F7\uA7FB-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9E0-\uA9E4\uA9E7-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA6F\uAA71-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5-\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADC\uAAE0-\uAAEA\uAAF2\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40-\uFB41\uFB43-\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF66-\uFF6F\uFF71-\uFF9D\uFFA0-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC] 430 | 431 | // Letter, Titlecase 432 | Lt = [\u01C5\u01C8\u01CB\u01F2\u1F88-\u1F8F\u1F98-\u1F9F\u1FA8-\u1FAF\u1FBC\u1FCC\u1FFC] 433 | 434 | // Letter, Uppercase 435 | Lu = [\u0041-\u005A\u00C0-\u00D6\u00D8-\u00DE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178-\u0179\u017B\u017D\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018B\u018E-\u0191\u0193-\u0194\u0196-\u0198\u019C-\u019D\u019F-\u01A0\u01A2\u01A4\u01A6-\u01A7\u01A9\u01AC\u01AE-\u01AF\u01B1-\u01B3\u01B5\u01B7-\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A-\u023B\u023D-\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u0370\u0372\u0376\u037F\u0386\u0388-\u038A\u038C\u038E-\u038F\u0391-\u03A1\u03A3-\u03AB\u03CF\u03D2-\u03D4\u03D8\u03DA\u03DC\u03DE\u03E0\u03E2\u03E4\u03E6\u03E8\u03EA\u03EC\u03EE\u03F4\u03F7\u03F9-\u03FA\u03FD-\u042F\u0460\u0462\u0464\u0466\u0468\u046A\u046C\u046E\u0470\u0472\u0474\u0476\u0478\u047A\u047C\u047E\u0480\u048A\u048C\u048E\u0490\u0492\u0494\u0496\u0498\u049A\u049C\u049E\u04A0\u04A2\u04A4\u04A6\u04A8\u04AA\u04AC\u04AE\u04B0\u04B2\u04B4\u04B6\u04B8\u04BA\u04BC\u04BE\u04C0-\u04C1\u04C3\u04C5\u04C7\u04C9\u04CB\u04CD\u04D0\u04D2\u04D4\u04D6\u04D8\u04DA\u04DC\u04DE\u04E0\u04E2\u04E4\u04E6\u04E8\u04EA\u04EC\u04EE\u04F0\u04F2\u04F4\u04F6\u04F8\u04FA\u04FC\u04FE\u0500\u0502\u0504\u0506\u0508\u050A\u050C\u050E\u0510\u0512\u0514\u0516\u0518\u051A\u051C\u051E\u0520\u0522\u0524\u0526\u0528\u052A\u052C\u052E\u0531-\u0556\u10A0-\u10C5\u10C7\u10CD\u13A0-\u13F5\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFE\u1F08-\u1F0F\u1F18-\u1F1D\u1F28-\u1F2F\u1F38-\u1F3F\u1F48-\u1F4D\u1F59\u1F5B\u1F5D\u1F5F\u1F68-\u1F6F\u1FB8-\u1FBB\u1FC8-\u1FCB\u1FD8-\u1FDB\u1FE8-\u1FEC\u1FF8-\u1FFB\u2102\u2107\u210B-\u210D\u2110-\u2112\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u2130-\u2133\u213E-\u213F\u2145\u2183\u2C00-\u2C2E\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E-\u2C80\u2C82\u2C84\u2C86\u2C88\u2C8A\u2C8C\u2C8E\u2C90\u2C92\u2C94\u2C96\u2C98\u2C9A\u2C9C\u2C9E\u2CA0\u2CA2\u2CA4\u2CA6\u2CA8\u2CAA\u2CAC\u2CAE\u2CB0\u2CB2\u2CB4\u2CB6\u2CB8\u2CBA\u2CBC\u2CBE\u2CC0\u2CC2\u2CC4\u2CC6\u2CC8\u2CCA\u2CCC\u2CCE\u2CD0\u2CD2\u2CD4\u2CD6\u2CD8\u2CDA\u2CDC\u2CDE\u2CE0\u2CE2\u2CEB\u2CED\u2CF2\uA640\uA642\uA644\uA646\uA648\uA64A\uA64C\uA64E\uA650\uA652\uA654\uA656\uA658\uA65A\uA65C\uA65E\uA660\uA662\uA664\uA666\uA668\uA66A\uA66C\uA680\uA682\uA684\uA686\uA688\uA68A\uA68C\uA68E\uA690\uA692\uA694\uA696\uA698\uA69A\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D-\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA796\uA798\uA79A\uA79C\uA79E\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA-\uA7AD\uA7B0-\uA7B4\uA7B6\uFF21-\uFF3A] 436 | 437 | // Mark, Spacing Combining 438 | Mc = [\u0903\u093B\u093E-\u0940\u0949-\u094C\u094E-\u094F\u0982-\u0983\u09BE-\u09C0\u09C7-\u09C8\u09CB-\u09CC\u09D7\u0A03\u0A3E-\u0A40\u0A83\u0ABE-\u0AC0\u0AC9\u0ACB-\u0ACC\u0B02-\u0B03\u0B3E\u0B40\u0B47-\u0B48\u0B4B-\u0B4C\u0B57\u0BBE-\u0BBF\u0BC1-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCC\u0BD7\u0C01-\u0C03\u0C41-\u0C44\u0C82-\u0C83\u0CBE\u0CC0-\u0CC4\u0CC7-\u0CC8\u0CCA-\u0CCB\u0CD5-\u0CD6\u0D02-\u0D03\u0D3E-\u0D40\u0D46-\u0D48\u0D4A-\u0D4C\u0D57\u0D82-\u0D83\u0DCF-\u0DD1\u0DD8-\u0DDF\u0DF2-\u0DF3\u0F3E-\u0F3F\u0F7F\u102B-\u102C\u1031\u1038\u103B-\u103C\u1056-\u1057\u1062-\u1064\u1067-\u106D\u1083-\u1084\u1087-\u108C\u108F\u109A-\u109C\u17B6\u17BE-\u17C5\u17C7-\u17C8\u1923-\u1926\u1929-\u192B\u1930-\u1931\u1933-\u1938\u1A19-\u1A1A\u1A55\u1A57\u1A61\u1A63-\u1A64\u1A6D-\u1A72\u1B04\u1B35\u1B3B\u1B3D-\u1B41\u1B43-\u1B44\u1B82\u1BA1\u1BA6-\u1BA7\u1BAA\u1BE7\u1BEA-\u1BEC\u1BEE\u1BF2-\u1BF3\u1C24-\u1C2B\u1C34-\u1C35\u1CE1\u1CF2-\u1CF3\u302E-\u302F\uA823-\uA824\uA827\uA880-\uA881\uA8B4-\uA8C3\uA952-\uA953\uA983\uA9B4-\uA9B5\uA9BA-\uA9BB\uA9BD-\uA9C0\uAA2F-\uAA30\uAA33-\uAA34\uAA4D\uAA7B\uAA7D\uAAEB\uAAEE-\uAAEF\uAAF5\uABE3-\uABE4\uABE6-\uABE7\uABE9-\uABEA\uABEC] 439 | 440 | // Mark, Nonspacing 441 | Mn = [\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E3-\u0902\u093A\u093C\u0941-\u0948\u094D\u0951-\u0957\u0962-\u0963\u0981\u09BC\u09C1-\u09C4\u09CD\u09E2-\u09E3\u0A01-\u0A02\u0A3C\u0A41-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A51\u0A70-\u0A71\u0A75\u0A81-\u0A82\u0ABC\u0AC1-\u0AC5\u0AC7-\u0AC8\u0ACD\u0AE2-\u0AE3\u0B01\u0B3C\u0B3F\u0B41-\u0B44\u0B4D\u0B56\u0B62-\u0B63\u0B82\u0BC0\u0BCD\u0C00\u0C3E-\u0C40\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56\u0C62-\u0C63\u0C81\u0CBC\u0CBF\u0CC6\u0CCC-\u0CCD\u0CE2-\u0CE3\u0D01\u0D41-\u0D44\u0D4D\u0D62-\u0D63\u0DCA\u0DD2-\u0DD4\u0DD6\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19\u0F35\u0F37\u0F39\u0F71-\u0F7E\u0F80-\u0F84\u0F86-\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102D-\u1030\u1032-\u1037\u1039-\u103A\u103D-\u103E\u1058-\u1059\u105E-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108D\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17B4-\u17B5\u17B7-\u17BD\u17C6\u17C9-\u17D3\u17DD\u180B-\u180D\u18A9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193B\u1A17-\u1A18\u1A1B\u1A56\u1A58-\u1A5E\u1A60\u1A62\u1A65-\u1A6C\u1A73-\u1A7C\u1A7F\u1AB0-\u1ABD\u1B00-\u1B03\u1B34\u1B36-\u1B3A\u1B3C\u1B42\u1B6B-\u1B73\u1B80-\u1B81\u1BA2-\u1BA5\u1BA8-\u1BA9\u1BAB-\u1BAD\u1BE6\u1BE8-\u1BE9\u1BED\u1BEF-\u1BF1\u1C2C-\u1C33\u1C36-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE0\u1CE2-\u1CE8\u1CED\u1CF4\u1CF8-\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302D\u3099-\u309A\uA66F\uA674-\uA67D\uA69E-\uA69F\uA6F0-\uA6F1\uA802\uA806\uA80B\uA825-\uA826\uA8C4\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA951\uA980-\uA982\uA9B3\uA9B6-\uA9B9\uA9BC\uA9E5\uAA29-\uAA2E\uAA31-\uAA32\uAA35-\uAA36\uAA43\uAA4C\uAA7C\uAAB0\uAAB2-\uAAB4\uAAB7-\uAAB8\uAABE-\uAABF\uAAC1\uAAEC-\uAAED\uAAF6\uABE5\uABE8\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F] 442 | 443 | // Number, Decimal Digit 444 | Nd = [\u0030-\u0039\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0DE6-\u0DEF\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uA9F0-\uA9F9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19] 445 | 446 | // Number, Letter 447 | Nl = [\u16EE-\u16F0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303A\uA6E6-\uA6EF] 448 | 449 | // Punctuation, Connector 450 | Pc = [\u005F\u203F-\u2040\u2054\uFE33-\uFE34\uFE4D-\uFE4F\uFF3F] 451 | 452 | // Separator, Space 453 | Zs = [\u0020\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000] 454 | 455 | /* Tokens */ 456 | 457 | AnonymousToken = "anonymous" !IdentifierPart 458 | AsToken = "as" !IdentifierPart 459 | BreakToken = "break" !IdentifierPart 460 | ClassToken = "class" !IdentifierPart 461 | ConstantToken = "constant" !IdentifierPart 462 | ContinueToken = "continue" !IdentifierPart 463 | ContractToken = "contract" !IdentifierPart 464 | DaysToken = "days" !IdentifierPart 465 | DeleteToken = "delete" !IdentifierPart 466 | DoToken = "do" !IdentifierPart 467 | ElseToken = "else" !IdentifierPart 468 | EnumToken = "enum" !IdentifierPart 469 | EtherToken = "ether" !IdentifierPart 470 | EventToken = "event" !IdentifierPart 471 | ExportToken = "export" !IdentifierPart 472 | ExtendsToken = "extends" !IdentifierPart 473 | FalseToken = "false" !IdentifierPart 474 | FinneyToken = "finney" !IdentifierPart 475 | ForToken = "for" !IdentifierPart 476 | FromToken = "from" !IdentifierPart 477 | FunctionToken = "function" !IdentifierPart 478 | GetToken = "get" !IdentifierPart 479 | HexToken = "hex" !IdentifierPart 480 | HoursToken = "hours" !IdentifierPart 481 | IfToken = "if" !IdentifierPart 482 | IsToken = "is" !IdentifierPart 483 | IndexedToken = "indexed" !IdentifierPart 484 | ImportToken = "import" !IdentifierPart 485 | InterfaceToken = "interface" !IdentifierPart 486 | InternalToken = "internal" !IdentifierPart 487 | LibraryToken = "library" !IdentifierPart 488 | MappingToken = "mapping" !IdentifierPart 489 | MemoryToken = "memory" !IdentifierPart 490 | MinutesToken = "minutes" !IdentifierPart 491 | ModifierToken = "modifier" !IdentifierPart 492 | NewToken = "new" !IdentifierPart 493 | NullToken = "null" !IdentifierPart 494 | PrivateToken = "private" !IdentifierPart 495 | PragmaToken = "pragma" !IdentifierPart 496 | PragmaXToken = "pragmax" !IdentifierPart 497 | PublicToken = "public" !IdentifierPart 498 | ReturnToken = "return" !IdentifierPart 499 | ReturnsToken = "returns" !IdentifierPart 500 | SecondsToken = "seconds" !IdentifierPart 501 | SetToken = "set" !IdentifierPart 502 | SolidityToken = "solidity" !IdentifierPart 503 | SolidityXToken = "solidityx" !IdentifierPart 504 | StorageToken = "storage" !IdentifierPart 505 | StructToken = "struct" !IdentifierPart 506 | SuperToken = "super" !IdentifierPart 507 | SzaboToken = "szabo" !IdentifierPart 508 | ThisToken = "this" !IdentifierPart 509 | ThrowToken = "throw" !IdentifierPart 510 | TrueToken = "true" !IdentifierPart 511 | UsingToken = "using" !IdentifierPart 512 | VarToken = "var" !IdentifierPart 513 | WeeksToken = "weeks" !IdentifierPart 514 | WeiToken = "wei" !IdentifierPart 515 | WhileToken = "while" !IdentifierPart 516 | YearsToken = "years" !IdentifierPart 517 | 518 | /* Skipped */ 519 | 520 | __ 521 | = (WhiteSpace / LineTerminatorSequence / Comment)* 522 | 523 | _ 524 | = (WhiteSpace / MultiLineCommentNoLineTerminator)* 525 | 526 | EOS = __ ";" 527 | 528 | EOF 529 | = !. 530 | 531 | Comma 532 | = __ "," __ 533 | 534 | /* ----- A.2 Number Conversions ----- */ 535 | 536 | /* Irrelevant. */ 537 | 538 | /* ----- A.3 Expressions ----- */ 539 | 540 | PrimaryExpression 541 | = ThisToken { return { type: "ThisExpression", start: location().start.offset, end: location().end.offset }; } 542 | / Identifier 543 | / Literal 544 | / ArrayLiteral 545 | / "(" __ expression:Expression __ ")" { return expression; } 546 | 547 | ArrayLiteral 548 | = "[" __ elision:(Elision __)? "]" { 549 | return { 550 | type: "ArrayExpression", 551 | elements: optionalList(extractOptional(elision, 0)), 552 | start: location().start.offset, 553 | end: location().end.offset 554 | }; 555 | } 556 | / "[" __ elements:ElementList __ "]" { 557 | return { 558 | type: "ArrayExpression", 559 | elements: elements, 560 | start: location().start.offset, 561 | end: location().end.offset 562 | }; 563 | } 564 | / "[" __ elements:ElementList __ "," __ elision:(Elision __)? "]" { 565 | return { 566 | type: "ArrayExpression", 567 | elements: elements.concat(optionalList(extractOptional(elision, 0))), 568 | start: location().start.offset, 569 | end: location().end.offset 570 | }; 571 | } 572 | 573 | ElementList 574 | = head:( 575 | elision:(Elision __)? element:AssignmentExpression { 576 | return optionalList(extractOptional(elision, 0)).concat(element); 577 | } 578 | ) 579 | tail:( 580 | __ "," __ elision:(Elision __)? element:AssignmentExpression { 581 | return optionalList(extractOptional(elision, 0)).concat(element); 582 | } 583 | )* 584 | { return Array.prototype.concat.apply(head, tail); } 585 | 586 | Elision 587 | = "," commas:(__ ",")* { return filledArray(commas.length + 1, null); } 588 | 589 | MemberExpression 590 | = head:( 591 | PrimaryExpression 592 | / NewToken __ callee:Type __ args:Arguments { 593 | return { type: "NewExpression", callee: callee, arguments: args, start: location().start.offset, end: location().end.offset }; 594 | } 595 | ) 596 | tail:( 597 | __ "[" __ property:Expression __ "]" { 598 | return { property: property, computed: true, start: location().start.offset, end: location().end.offset }; 599 | } 600 | / __ "." __ property:IdentifierName { 601 | return { property: property, computed: false, start: location().start.offset, end: location().end.offset }; 602 | } 603 | )* 604 | { 605 | return buildTree(head, tail, function(result, element) { 606 | return { 607 | type: "MemberExpression", 608 | object: result, 609 | property: element.property, 610 | computed: element.computed, 611 | start: location().start.offset, 612 | end: location().end.offset 613 | }; 614 | }); 615 | } 616 | 617 | NewExpression 618 | = MemberExpression 619 | / NewToken __ callee:NewExpression { 620 | return { type: "NewExpression", callee: callee, arguments: [], start: location().start.offset, end: location().end.offset }; 621 | } 622 | 623 | CallExpression 624 | = head:( 625 | callee:MemberExpression __ args:Arguments { 626 | return { type: "CallExpression", callee: callee, arguments: args, start: location().start.offset, end: location().end.offset }; 627 | } 628 | ) 629 | tail:( 630 | __ args:Arguments { 631 | return { type: "CallExpression", arguments: args, start: location().start.offset, end: location().end.offset }; 632 | } 633 | / __ "[" __ property:Expression __ "]" { 634 | return { 635 | type: "MemberExpression", 636 | property: property, 637 | computed: true, 638 | start: location().start.offset, 639 | end: location().end.offset 640 | }; 641 | } 642 | / __ "." __ property:IdentifierName { 643 | return { 644 | type: "MemberExpression", 645 | property: property, 646 | computed: false, 647 | start: location().start.offset, 648 | end: location().end.offset 649 | }; 650 | } 651 | )* 652 | { 653 | return buildTree(head, tail, function(result, element) { 654 | element[TYPES_TO_PROPERTY_NAMES[element.type]] = result; 655 | 656 | return element; 657 | }); 658 | } 659 | 660 | Arguments 661 | = "(" __ args:(ArgumentList __)? ")" { 662 | return optionalList(extractOptional(args, 0)); 663 | } 664 | / "(" __ "{" __ args:(NameValueList (__ ",")? )? __ "}" __ ")" { 665 | return optionalList(extractOptional(args, 0)); 666 | } 667 | 668 | ArgumentList 669 | = head:AssignmentExpression tail:(__ "," __ AssignmentExpression)* { 670 | return buildList(head, tail, 3); 671 | } 672 | 673 | NameValueList 674 | = head:NameValueAssignment tail:(__ "," __ NameValueAssignment)* { 675 | return buildList(head, tail, 3); 676 | } 677 | 678 | NameValueAssignment 679 | = name:Identifier __ ":" __ value:AssignmentExpression __ { 680 | return { 681 | type: "NameValueAssignment", 682 | name: name, 683 | value: value, 684 | start: location().start.offset, 685 | end: location().end.offset 686 | }; 687 | } 688 | 689 | LeftHandSideExpression 690 | = DeclarativeExpression 691 | / CallExpression 692 | / NewExpression 693 | 694 | Type 695 | = literal:(Mapping / Identifier) members:("." Identifier)* parts:(__"[" __ (Expression)? __ "]")* 696 | { 697 | return { 698 | type: "Type", 699 | literal: literal.type == "Identifier" ? literal.name : literal, 700 | members: optionalList(members).map(function(m) {return m[1].name;}), 701 | array_parts: optionalList(parts).map(function(p) {return p[3] != null ? p[3].value : null}), 702 | start: location().start.offset, 703 | end: location().end.offset 704 | } 705 | } 706 | 707 | VisibilitySpecifier 708 | = PublicToken 709 | / PrivateToken 710 | / InternalToken 711 | 712 | StorageLocationSpecifier 713 | = StorageToken 714 | / MemoryToken 715 | 716 | StateVariableSpecifiers 717 | = specifiers:(VisibilitySpecifier __ ConstantToken?){ 718 | return { 719 | visibility: specifiers[0][0], 720 | isconstant: specifiers[2] ? true: false 721 | } 722 | } 723 | / specifiers:(ConstantToken __ VisibilitySpecifier?){ 724 | return { 725 | visibility: specifiers[2] ? specifiers[2][0] : null, 726 | isconstant: true 727 | } 728 | } 729 | 730 | StateVariableValue 731 | = "=" __ expression:Expression { 732 | return expression; 733 | } 734 | 735 | StateVariableDeclaration 736 | = type:Type __ specifiers:StateVariableSpecifiers? __ id:Identifier __ value:StateVariableValue? __ EOS 737 | { 738 | return { 739 | type: "StateVariableDeclaration", 740 | name: id.name, 741 | literal: type, 742 | visibility: specifiers? specifiers.visibility : null, 743 | is_constant: specifiers? specifiers.isconstant : false, 744 | value: value, 745 | start: location().start.offset, 746 | end: location().end.offset 747 | } 748 | } 749 | 750 | DeclarativeExpression 751 | = type:Type __ storage:StorageLocationSpecifier? __ id:Identifier 752 | { 753 | return { 754 | type: "DeclarativeExpression", 755 | name: id.name, 756 | literal: type, 757 | storage_location: storage ? storage[0]: null, 758 | start: location().start.offset, 759 | end: location().end.offset 760 | } 761 | } 762 | 763 | Mapping 764 | = MappingToken __ "(" __ from:Type __ "=>" __ to:Type __ ")" 765 | { 766 | return { 767 | type: "MappingExpression", 768 | from: from, 769 | to: to, 770 | start: location().start.offset, 771 | end: location().end.offset 772 | } 773 | } 774 | 775 | PostfixExpression 776 | = argument:LeftHandSideExpression _ operator:PostfixOperator { 777 | return { 778 | type: "UpdateExpression", 779 | operator: operator, 780 | argument: argument, 781 | prefix: false, 782 | start: location().start.offset, 783 | end: location().end.offset 784 | }; 785 | } 786 | / LeftHandSideExpression 787 | 788 | PostfixOperator 789 | = "++" 790 | / "--" 791 | 792 | UnaryExpression 793 | = PostfixExpression 794 | / operator:UnaryOperator __ argument:UnaryExpression { 795 | var type = (operator === "++" || operator === "--") 796 | ? "UpdateExpression" 797 | : "UnaryExpression"; 798 | 799 | return { 800 | type: type, 801 | operator: operator, 802 | argument: argument, 803 | prefix: true, 804 | start: location().start.offset, 805 | end: location().end.offset 806 | }; 807 | } 808 | 809 | UnaryOperator 810 | = $DeleteToken 811 | / "++" 812 | / "--" 813 | / $("+" !"=") 814 | / $("-" !"=") 815 | / "~" 816 | / "!" 817 | 818 | MultiplicativeExpression 819 | = head:UnaryExpression 820 | tail:(__ MultiplicativeOperator __ UnaryExpression)* 821 | { return buildBinaryExpression(head, tail); } 822 | 823 | MultiplicativeOperator 824 | = $("*""*"? !"=") 825 | / $("/" !"=") 826 | / $("%" !"=") 827 | 828 | AdditiveExpression 829 | = head:MultiplicativeExpression 830 | tail:(__ AdditiveOperator __ MultiplicativeExpression)* 831 | { return buildBinaryExpression(head, tail); } 832 | 833 | AdditiveOperator 834 | = $("+" ![+=]) 835 | / $("-" ![-=]) 836 | 837 | ShiftExpression 838 | = head:AdditiveExpression 839 | tail:(__ ShiftOperator __ AdditiveExpression)* 840 | { return buildBinaryExpression(head, tail); } 841 | 842 | ShiftOperator 843 | = $("<<" !"=") 844 | / $(">>>" !"=") 845 | / $(">>" !"=") 846 | 847 | RelationalExpression 848 | = head:ShiftExpression 849 | tail:(__ RelationalOperator __ ShiftExpression)* 850 | { return buildBinaryExpression(head, tail); } 851 | 852 | RelationalOperator 853 | = "<=" 854 | / ">=" 855 | / $("<" !"<") 856 | / $(">" !">") 857 | 858 | EqualityExpression 859 | = head:RelationalExpression 860 | tail:(__ EqualityOperator __ RelationalExpression)* 861 | { return buildBinaryExpression(head, tail); } 862 | 863 | EqualityOperator 864 | = "==" 865 | / "!=" 866 | 867 | BitwiseANDExpression 868 | = head:EqualityExpression 869 | tail:(__ BitwiseANDOperator __ EqualityExpression)* 870 | { return buildBinaryExpression(head, tail); } 871 | 872 | BitwiseANDOperator 873 | = $("&" ![&=]) 874 | 875 | BitwiseXORExpression 876 | = head:BitwiseANDExpression 877 | tail:(__ BitwiseXOROperator __ BitwiseANDExpression)* 878 | { return buildBinaryExpression(head, tail); } 879 | 880 | BitwiseXOROperator 881 | = $("^" !"=") 882 | 883 | BitwiseORExpression 884 | = head:BitwiseXORExpression 885 | tail:(__ BitwiseOROperator __ BitwiseXORExpression)* 886 | { return buildBinaryExpression(head, tail); } 887 | 888 | BitwiseOROperator 889 | = $("|" ![|=]) 890 | 891 | LogicalANDExpression 892 | = head:BitwiseORExpression 893 | tail:(__ LogicalANDOperator __ BitwiseORExpression)* 894 | { return buildBinaryExpression(head, tail); } 895 | 896 | LogicalANDOperator 897 | = "&&" 898 | 899 | LogicalORExpression 900 | = head:LogicalANDExpression 901 | tail:(__ LogicalOROperator __ LogicalANDExpression)* 902 | { return buildBinaryExpression(head, tail); } 903 | 904 | LogicalOROperator 905 | = "||" 906 | 907 | ConditionalExpression 908 | = test:LogicalORExpression __ 909 | "?" __ consequent:AssignmentExpression __ 910 | ":" __ alternate:AssignmentExpression 911 | { 912 | return { 913 | type: "ConditionalExpression", 914 | test: test, 915 | consequent: consequent, 916 | alternate: alternate, 917 | start: location().start.offset, 918 | end: location().end.offset 919 | }; 920 | } 921 | / LogicalORExpression 922 | 923 | AssignmentExpression 924 | = left:LeftHandSideExpression __ 925 | "=" !"=" __ 926 | right:AssignmentExpression 927 | { 928 | return { 929 | type: "AssignmentExpression", 930 | operator: "=", 931 | left: left, 932 | right: right, 933 | start: location().start.offset, 934 | end: location().end.offset 935 | }; 936 | } 937 | / left:LeftHandSideExpression __ 938 | operator:AssignmentOperator __ 939 | right:AssignmentExpression 940 | { 941 | return { 942 | type: "AssignmentExpression", 943 | operator: operator, 944 | left: left, 945 | right: right, 946 | start: location().start.offset, 947 | end: location().end.offset 948 | }; 949 | } 950 | / ConditionalExpression 951 | 952 | AssignmentOperator 953 | = "*=" 954 | / "/=" 955 | / "%=" 956 | / "+=" 957 | / "-=" 958 | / "<<=" 959 | / ">>=" 960 | / "&=" 961 | / "^=" 962 | / "|=" 963 | 964 | Expression 965 | = head:AssignmentExpression tail:(__ "," __ AssignmentExpression)* { 966 | return tail.length > 0 967 | ? { type: "SequenceExpression", expressions: buildList(head, tail, 3) } 968 | : head; 969 | } 970 | 971 | /* ----- A.4 Statements ----- */ 972 | 973 | Statements 974 | = head:Statement tail:(__ Statement)* { 975 | return buildList(head, tail, 1); 976 | } 977 | 978 | Statement 979 | = Block 980 | / VariableStatement 981 | / EmptyStatement 982 | / PlaceholderStatement 983 | / ExpressionStatement 984 | / IfStatement 985 | / IterationStatement 986 | / InlineAssemblyStatement 987 | / ContinueStatement 988 | / BreakStatement 989 | / ReturnStatement 990 | / ThrowStatement 991 | / UsingStatement 992 | 993 | Block 994 | = "{" __ body:(StatementList __)? "}" { 995 | return { 996 | type: "BlockStatement", 997 | body: optionalList(extractOptional(body, 0)), 998 | start: location().start.offset, 999 | end: location().end.offset 1000 | }; 1001 | } 1002 | 1003 | StatementList 1004 | = head:Statement tail:(__ Statement)* { return buildList(head, tail, 1); } 1005 | 1006 | VariableStatement 1007 | = VarToken __ declarations:VariableDeclarationList EOS { 1008 | return { 1009 | type: "VariableDeclaration", 1010 | declarations: declarations, 1011 | start: location().start.offset, 1012 | end: location().end.offset 1013 | }; 1014 | } 1015 | / VarToken __ tuple:VariableDeclarationTuple EOS { 1016 | return { 1017 | type: "VariableDeclarationTuple", 1018 | declarations: tuple.declarations, 1019 | init: tuple.init, 1020 | start: location().start.offset, 1021 | end: location().end.offset 1022 | }; 1023 | } 1024 | 1025 | VariableDeclarationTuple 1026 | = "("Comma* __ head:VariableDeclarationNoInit tail:(Comma+ VariableDeclarationNoInit)* __ Comma* ")" init:(__ Initialiser) { 1027 | return { 1028 | declarations: buildList(head, tail, 1), 1029 | init: extractOptional(init, 1) 1030 | } 1031 | } 1032 | 1033 | VariableDeclarationNoInit 1034 | = id:Identifier { 1035 | return { 1036 | type: "VariableDeclarator", 1037 | id: id.constructor === Array ? id [1] : id, 1038 | init: null, 1039 | start: location().start.offset, 1040 | end: location().end.offset 1041 | }; 1042 | } 1043 | 1044 | 1045 | VariableDeclarationList 1046 | = head:VariableDeclaration tail:(__ "," __ VariableDeclaration)* { 1047 | return buildList(head, tail, 3); 1048 | } 1049 | 1050 | VariableDeclaration 1051 | = id:(Identifier / "(" Identifier ")") init:(__ Initialiser)? { 1052 | return { 1053 | type: "VariableDeclarator", 1054 | id: id.constructor === Array ? id [1] : id, 1055 | init: extractOptional(init, 1), 1056 | start: location().start.offset, 1057 | end: location().end.offset 1058 | }; 1059 | } 1060 | 1061 | Initialiser 1062 | = "=" !"=" __ expression:AssignmentExpression { return expression; } 1063 | 1064 | EmptyStatement 1065 | = ";" { return { type: "EmptyStatement", start: location().start.offset, end: location().end.offset }; } 1066 | 1067 | ExpressionStatement 1068 | = !("{" / FunctionToken / ContractToken / InterfaceToken / LibraryToken / StructToken / EnumToken) expression:Expression EOS { 1069 | return { 1070 | type: "ExpressionStatement", 1071 | expression: expression, 1072 | start: location().start.offset, 1073 | end: location().end.offset 1074 | }; 1075 | } 1076 | 1077 | IfStatement 1078 | = IfToken __ "(" __ test:Expression __ ")" __ 1079 | consequent:Statement __ 1080 | ElseToken __ 1081 | alternate:Statement 1082 | { 1083 | return { 1084 | type: "IfStatement", 1085 | test: test, 1086 | consequent: consequent, 1087 | alternate: alternate, 1088 | start: location().start.offset, 1089 | end: location().end.offset 1090 | }; 1091 | } 1092 | / IfToken __ "(" __ test:Expression __ ")" __ 1093 | consequent:Statement { 1094 | return { 1095 | type: "IfStatement", 1096 | test: test, 1097 | consequent: consequent, 1098 | alternate: null, 1099 | start: location().start.offset, 1100 | end: location().end.offset 1101 | }; 1102 | } 1103 | 1104 | PragmaStatement 1105 | = PragmaToken __ SolidityToken __ start_version:VersionLiteral __ end_version:(VersionLiteral?) EOS { 1106 | return { 1107 | type: "PragmaStatement", 1108 | start_version: start_version, 1109 | end_version: end_version, 1110 | start: location().start.offset, 1111 | end: location().end.offset 1112 | } 1113 | } 1114 | 1115 | //SolidityX specific 1116 | PragmaXStatement 1117 | = PragmaXToken __ SolidityXToken __ start_version:VersionLiteral __ end_version:(VersionLiteral?) EOS { 1118 | return { 1119 | type: "PragmaXStatement", 1120 | start_version: start_version, 1121 | end_version: end_version, 1122 | start: location().start.offset, 1123 | end: location().end.offset 1124 | } 1125 | } 1126 | //---- 1127 | 1128 | ImportStatement 1129 | = ImportToken __ from:StringLiteral __ alias:(AsToken __ Identifier)? __ EOS 1130 | { 1131 | return { 1132 | type: "ImportStatement", 1133 | from: from.value, 1134 | symbols: [], 1135 | alias: alias != null ? alias[2].name : null, 1136 | start: location().start.offset, 1137 | end: location().end.offset 1138 | } 1139 | } 1140 | / ImportToken __ "*" __ AsToken __ alias:Identifier __ FromToken __ from:StringLiteral __ EOS 1141 | { 1142 | return { 1143 | type: "ImportStatement", 1144 | from: from.value, 1145 | symbols: [{ 1146 | type: "Symbol", 1147 | name: "*", 1148 | alias: alias.name 1149 | }], 1150 | start: location().start.offset, 1151 | end: location().end.offset 1152 | } 1153 | } 1154 | / ImportToken __ "{" __ symbols:SymbolList __ "}" __ FromToken __ from:StringLiteral __ EOS 1155 | { 1156 | return { 1157 | type: "ImportStatement", 1158 | from: from.value, 1159 | symbols: symbols, 1160 | start: location().start.offset, 1161 | end: location().end.offset 1162 | } 1163 | } 1164 | 1165 | UsingStatement 1166 | = UsingToken __ library:Identifier __ ForToken __ type:Type __ EOS 1167 | { 1168 | return { 1169 | type: "UsingStatement", 1170 | library: library.name, 1171 | for: type, 1172 | start: location().start.offset, 1173 | end: location().end.offset 1174 | } 1175 | } 1176 | / UsingToken __ library:Identifier __ ForToken __ "*" __ EOS 1177 | { 1178 | return { 1179 | type: "UsingStatement", 1180 | library: library.name, 1181 | for: "*", 1182 | start: location().start.offset, 1183 | end: location().end.offset 1184 | } 1185 | } 1186 | 1187 | SymbolList 1188 | = head:Symbol tail:( __ "," __ Symbol)* { 1189 | return buildList(head, tail, 3); 1190 | } 1191 | 1192 | Symbol 1193 | = name:Identifier __ alias:(AsToken __ Identifier)? 1194 | { 1195 | return { 1196 | type: "Symbol", 1197 | name: name.name, 1198 | alias: alias != null ? alias[2].name : name.name, 1199 | start: location().start.offset, 1200 | end: location().end.offset 1201 | }; 1202 | } 1203 | 1204 | IterationStatement 1205 | = DoToken __ 1206 | body:Statement __ 1207 | WhileToken __ "(" __ test:Expression __ ")" EOS 1208 | { return { type: "DoWhileStatement", body: body, test: test, start: location().start.offset, end: location().end.offset }; } 1209 | / WhileToken __ "(" __ test:Expression __ ")" __ 1210 | body:Statement 1211 | { return { type: "WhileStatement", test: test, body: body, start: location().start.offset, end: location().end.offset }; } 1212 | / ForToken __ 1213 | "(" __ 1214 | init:(Expression __)? ";" __ 1215 | test:(Expression __)? ";" __ 1216 | update:(Expression __)? 1217 | ")" __ 1218 | body:Statement 1219 | { 1220 | return { 1221 | type: "ForStatement", 1222 | init: extractOptional(init, 0), 1223 | test: extractOptional(test, 0), 1224 | update: extractOptional(update, 0), 1225 | body: body, 1226 | start: location().start.offset, 1227 | end: location().end.offset 1228 | }; 1229 | } 1230 | / ForToken __ 1231 | "(" __ 1232 | VarToken __ declarations:VariableDeclarationList __ ";" __ 1233 | test:(Expression __)? ";" __ 1234 | update:(Expression __)? 1235 | ")" __ 1236 | body:Statement 1237 | { 1238 | return { 1239 | type: "ForStatement", 1240 | init: { 1241 | type: "VariableDeclaration", 1242 | declarations: declarations 1243 | }, 1244 | test: extractOptional(test, 0), 1245 | update: extractOptional(update, 0), 1246 | body: body, 1247 | start: location().start.offset, 1248 | end: location().end.offset 1249 | }; 1250 | } 1251 | 1252 | InlineAssemblyStatement 1253 | = 'assembly' __ body:InlineAssemblyBlock { 1254 | return { 1255 | type: "InlineAssemblyStatement", 1256 | body: body, 1257 | start: location().start.offset, 1258 | end: location().end.offset 1259 | }; 1260 | } 1261 | 1262 | PlaceholderStatement 1263 | = "_" __ EOS { 1264 | return { 1265 | type: "PlaceholderStatement", 1266 | start: location().start.offset, 1267 | end: location().end.offset 1268 | } 1269 | } 1270 | 1271 | ContinueStatement 1272 | = ContinueToken EOS { 1273 | return { type: "ContinueStatement", label: null, start: location().start.offset, end: location().end.offset }; 1274 | } 1275 | / ContinueToken _ label:Identifier EOS { 1276 | return { type: "ContinueStatement", label: label, start: location().start.offset, end: location().end.offset }; 1277 | } 1278 | 1279 | BreakStatement 1280 | = BreakToken EOS { 1281 | return { type: "BreakStatement", label: null, start: location().start.offset, end: location().end.offset }; 1282 | } 1283 | / BreakToken _ label:Identifier EOS { 1284 | return { type: "BreakStatement", label: label, start: location().start.offset, end: location().end.offset }; 1285 | } 1286 | 1287 | ReturnStatement 1288 | = ReturnToken EOS { 1289 | return { type: "ReturnStatement", argument: null, start: location().start.offset, end: location().end.offset }; 1290 | } 1291 | / ReturnToken __ argument:Expression EOS { 1292 | return { type: "ReturnStatement", argument: argument, start: location().start.offset, end: location().end.offset }; 1293 | } 1294 | 1295 | ThrowStatement 1296 | = ThrowToken EOS { 1297 | return { type: "ThrowStatement", start: location().start.offset, end: location().end.offset }; 1298 | } 1299 | 1300 | ContractStatement 1301 | = ContractToken __ id:Identifier __ is:IsStatement? __ 1302 | "{" __ body:SourceElements? __ "}" 1303 | { 1304 | return { 1305 | type: "ContractStatement", 1306 | name: id.name, 1307 | is: is != null ? is.names : [], 1308 | body: optionalList(body), 1309 | start: location().start.offset, 1310 | end: location().end.offset 1311 | } 1312 | } 1313 | 1314 | InterfaceStatement 1315 | = InterfaceToken __ id:Identifier __ 1316 | "{" __ body:SourceElements? __ "}" 1317 | { 1318 | return { 1319 | type: "InterfaceStatement", 1320 | name: id.name, 1321 | is: [], 1322 | body: optionalList(body), 1323 | start: location().start.offset, 1324 | end: location().end.offset 1325 | } 1326 | } 1327 | 1328 | 1329 | LibraryStatement 1330 | = LibraryToken __ id:Identifier __ is:IsStatement? __ 1331 | "{" __ body:SourceElements? __ "}" 1332 | { 1333 | return { 1334 | type: "LibraryStatement", 1335 | name: id.name, 1336 | is: is != null ? is.names : [], 1337 | body: optionalList(body), 1338 | start: location().start.offset, 1339 | end: location().end.offset 1340 | } 1341 | } 1342 | 1343 | IsStatement 1344 | = IsToken __ modifiers:CommaSeparatedModifierNameList 1345 | { 1346 | return { 1347 | type: "IsStatement", 1348 | names: modifiers, 1349 | start: location().start.offset, 1350 | end: location().end.offset 1351 | } 1352 | } 1353 | 1354 | /* ----- A.5 Functions and Programs ----- */ 1355 | 1356 | EventDeclaration 1357 | = EventToken __ fnname:FunctionName __ isanonymous:AnonymousToken? __ EOS 1358 | { 1359 | return { 1360 | type: "EventDeclaration", 1361 | name: fnname.name, 1362 | params: fnname.params, 1363 | is_anonymous: isanonymous != null, 1364 | start: location().start.offset, 1365 | end: location().end.offset 1366 | } 1367 | } 1368 | 1369 | ModifierDeclaration 1370 | = ModifierToken __ fnname:ModifierName __ names:ModifierNameList? __ body:FunctionBody 1371 | { 1372 | return { 1373 | type: "ModifierDeclaration", 1374 | name: fnname.name, 1375 | params: fnname.params, 1376 | modifiers: names, 1377 | body: body, 1378 | start: location().start.offset, 1379 | end: location().end.offset 1380 | }; 1381 | } 1382 | 1383 | FunctionDeclaration 1384 | = FunctionToken __ fnname:FunctionName __ args:ModifierArgumentList? __ returns:ReturnsDeclaration? __ body:FunctionBody 1385 | { 1386 | return { 1387 | type: "FunctionDeclaration", 1388 | name: fnname.name, 1389 | params: fnname.params, 1390 | modifiers: args, 1391 | returnParams: returns, 1392 | body: body, 1393 | is_abstract: false, 1394 | start: location().start.offset, 1395 | end: location().end.offset 1396 | }; 1397 | } 1398 | / FunctionToken __ fnname:FunctionName __ args:ModifierArgumentList? __ returns:ReturnsDeclaration? __ EOS 1399 | { 1400 | return { 1401 | type: "FunctionDeclaration", 1402 | name: fnname.name, 1403 | params: fnname.params, 1404 | modifiers: args, 1405 | returnParams: returns, 1406 | body: null, 1407 | is_abstract: true, 1408 | start: location().start.offset, 1409 | end: location().end.offset 1410 | }; 1411 | } 1412 | 1413 | ReturnsDeclaration 1414 | = ReturnsToken __ params:("(" __ InformalParameterList __ ")") 1415 | { 1416 | return params != null ? params [2] : null; 1417 | } 1418 | 1419 | 1420 | FunctionName 1421 | = id:Identifier? __ params:("(" __ InformalParameterList? __ ")") 1422 | { 1423 | return { 1424 | type: "FunctionName", 1425 | name: id != null ? id.name : null, 1426 | params: params != null ? params[2] : [], 1427 | start: location().start.offset, 1428 | end: location().end.offset 1429 | }; 1430 | } 1431 | 1432 | ModifierName 1433 | = id:Identifier __ params:("(" __ InformalParameterList? __ ")")? 1434 | { 1435 | return { 1436 | type: "ModifierName", 1437 | name: id != null ? id.name : null, 1438 | params: params != null ? params[2] : [], 1439 | start: location().start.offset, 1440 | end: location().end.offset 1441 | }; 1442 | } 1443 | 1444 | ModifierArgument 1445 | = id:Identifier __ params:("(" __ ArgumentList? __ ")")? 1446 | { 1447 | return { 1448 | type: "ModifierArgument", 1449 | name: id != null ? id.name : null, 1450 | params: params != null ? params[2] : [], 1451 | start: location().start.offset, 1452 | end: location().end.offset 1453 | }; 1454 | } 1455 | 1456 | FunctionNameList 1457 | = head:FunctionName tail:( __ FunctionName)* { 1458 | return buildList(head, tail, 1); 1459 | } 1460 | 1461 | ModifierNameList 1462 | = head:ModifierName tail:( __ ModifierName)* { 1463 | return buildList(head, tail, 1); 1464 | } 1465 | 1466 | ModifierArgumentList 1467 | = head:ModifierArgument tail:( __ ModifierArgument)* { 1468 | return buildList(head, tail, 1); 1469 | } 1470 | 1471 | CommaSeparatedModifierNameList 1472 | = head:ModifierName tail:( __ "," __ ModifierName)* { 1473 | return buildList(head, tail, 3); 1474 | } 1475 | 1476 | InformalParameter 1477 | = type:Type __ isindexed:IndexedToken? __ isconstant:ConstantToken? __ isstorage:StorageToken? __ ismemory:MemoryToken? __ id:Identifier? 1478 | { 1479 | return { 1480 | type: "InformalParameter", 1481 | literal: type, 1482 | id: (id || {}).name, 1483 | is_indexed: isindexed != null, 1484 | is_storage: isconstant != null, 1485 | is_storage: isstorage != null, 1486 | is_memory: ismemory != null, 1487 | start: location().start.offset, 1488 | end: location().end.offset 1489 | }; 1490 | } 1491 | 1492 | InformalParameterList 1493 | = head:(InformalParameter / Literal) tail:( __ "," __ (InformalParameter / Literal))* { 1494 | return buildList(head, tail, 3); 1495 | } 1496 | 1497 | 1498 | FunctionBody 1499 | = "{" __ body:Statements? __ "}" { 1500 | return { 1501 | type: "BlockStatement", 1502 | body: optionalList(body), 1503 | start: location().start.offset, 1504 | end: location().end.offset 1505 | }; 1506 | } 1507 | 1508 | EnumDeclaration 1509 | = EnumToken __ id:Identifier __ "{" __ head:Identifier tail:( __ "," __ Identifier)* __ "}" 1510 | { 1511 | return { 1512 | type: "EnumDeclaration", 1513 | name: id.name, 1514 | members: buildList(head, tail, 3).map(function(i) {return i.name;}), 1515 | start: location().start.offset, 1516 | end: location().end.offset 1517 | } 1518 | } 1519 | 1520 | StructDeclaration 1521 | = StructToken __ id:Identifier __ "{" __ body:DeclarativeExpressionList? __ "}" 1522 | { 1523 | return { 1524 | type: "StructDeclaration", 1525 | name: id.name, 1526 | body: body != null ? body.declarations : null, 1527 | start: location().start.offset, 1528 | end: location().end.offset 1529 | } 1530 | } 1531 | 1532 | DeclarativeExpressionList 1533 | = head:DeclarativeExpression __ EOS tail:( __ DeclarativeExpression __ EOS )* 1534 | { 1535 | return { 1536 | type: "DeclarativeExpressionList", 1537 | declarations: buildList(head, tail, 1), 1538 | start: location().start.offset, 1539 | end: location().end.offset 1540 | } 1541 | } 1542 | 1543 | Program 1544 | = body:SourceUnits? { 1545 | return { 1546 | type: "Program", 1547 | body: optionalList(body), 1548 | start: location().start.offset, 1549 | end: location().end.offset 1550 | }; 1551 | } 1552 | 1553 | SourceUnits 1554 | = head:SourceUnit tail:(__ SourceUnit)* { 1555 | return buildList(head, tail, 1); 1556 | } 1557 | 1558 | SourceUnit 1559 | = PragmaStatement 1560 | / PragmaXStatement 1561 | / ImportStatement 1562 | / ContractStatement 1563 | / InterfaceStatement 1564 | / LibraryStatement 1565 | 1566 | SourceElements 1567 | = head:SourceElement tail:(__ SourceElement)* { 1568 | return buildList(head, tail, 1); 1569 | } 1570 | 1571 | SourceElement 1572 | = StateVariableDeclaration 1573 | / EnumDeclaration 1574 | / EventDeclaration 1575 | / StructDeclaration 1576 | / ModifierDeclaration 1577 | / FunctionDeclaration 1578 | / UsingStatement 1579 | 1580 | InlineAssemblyBlock 1581 | = '{' __ items:(AssemblyItem __)* __ '}' { 1582 | return { 1583 | type: "InlineAssemblyBlock", 1584 | items: optionalList(extractList(items, 0)), 1585 | start: location().start.offset, 1586 | end: location().end.offset 1587 | } 1588 | } 1589 | 1590 | AssemblyItem 1591 | = FunctionalAssemblyInstruction 1592 | / InlineAssemblyBlock 1593 | / AssemblyLocalBinding 1594 | / AssemblyAssignment 1595 | / NumericLiteral 1596 | / StringLiteral 1597 | / HexStringLiteral 1598 | / Identifier 1599 | 1600 | AssemblyExpression 1601 | = FunctionalAssemblyInstruction 1602 | / ElementaryAssemblyOperation 1603 | 1604 | ElementaryAssemblyOperation 1605 | = NumericLiteral 1606 | / StringLiteral 1607 | / Identifier 1608 | 1609 | AssemblyLocalBinding 1610 | = 'let' __ name:Identifier __ ':=' __ expression:AssemblyExpression { 1611 | return { 1612 | type: "AssemblyLocalBinding", 1613 | name: name, 1614 | expression: expression, 1615 | start: location().start.offset, 1616 | end: location().end.offset 1617 | } 1618 | } 1619 | 1620 | AssemblyAssignment 1621 | = name:Identifier __ ':=' __ expression:FunctionalAssemblyInstruction { 1622 | return { 1623 | type: "AssemblyAssignment", 1624 | name: name, 1625 | expression: expression, 1626 | start: location().start.offset, 1627 | end: location().end.offset 1628 | } 1629 | } 1630 | / '=:' __ name:Identifier { 1631 | return { 1632 | type: "AssemblyAssignment", 1633 | name: name, 1634 | start: location().start.offset, 1635 | end: location().end.offset 1636 | } 1637 | } 1638 | 1639 | ReturnOpCode 1640 | = 'return' { 1641 | return { 1642 | type: "Identifier", 1643 | name: "return", 1644 | start: location().start.offset, 1645 | end: location().end.offset 1646 | } 1647 | } 1648 | 1649 | FunctionalAssemblyInstruction 1650 | = name:(Identifier / ReturnOpCode) __ '(' __ head:AssemblyItem? __ tail:( ',' __ AssemblyItem )* __ ')' { 1651 | return { 1652 | type: "FunctionalAssemblyInstruction", 1653 | name: name, 1654 | arguments: buildList(head, tail, 2), 1655 | start: location().start.offset, 1656 | end: location().end.offset 1657 | } 1658 | } 1659 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var PEG = require("pegjs"); 2 | var fs = require("fs"); 3 | var path = require("path"); 4 | 5 | var builtParsers = { 6 | "solidityX": require("./build/parser"), 7 | }; 8 | 9 | // TODO: Make all this async. 10 | module.exports = { 11 | getParser: function(parser_name, rebuild) { 12 | if (rebuild == true) { 13 | var parserfile = fs.readFileSync(path.resolve("./grammar/" + parser_name + ".pegjs"), {encoding: "utf8"}); 14 | return PEG.generate(parserfile); 15 | } else { 16 | return builtParsers[parser_name]; 17 | } 18 | }, 19 | parse: function(source, parser_name, rebuild) { 20 | if (typeof parser_name == "boolean") { 21 | rebuild = parser_name; 22 | parser_name = null; 23 | } 24 | 25 | if (parser_name == null) { 26 | parser_name = "solidityX"; 27 | } 28 | 29 | var parser = this.getParser( parser_name, rebuild); 30 | 31 | var result; 32 | try { 33 | result = parser.parse(source); 34 | } catch (e) { 35 | if (e instanceof parser.SyntaxError) { 36 | e.message += " Line: " + e.location.start.line + ", Column: " + e.location.start.column; 37 | } 38 | throw e; 39 | } 40 | 41 | return result; 42 | }, 43 | parseFile: function(file, parser_name, rebuild) { 44 | return this.parse(fs.readFileSync(path.resolve(file), {encoding: "utf8"}), parser_name, rebuild); 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /* eslint no-console: 0 */ 4 | 5 | 6 | var argv = require("yargs").argv; 7 | var SolidityXParser = require("./index.js"); 8 | var SolidityXCompiler = require("./compiler.js"); 9 | var fs = require("fs"); 10 | var path = require("path"); 11 | 12 | var result; 13 | var outputFile = ""; 14 | var originalSrc = ""; 15 | try { 16 | 17 | if (argv.e) { 18 | result = SolidityXParser.parse(argv.e || argv.expression); 19 | originalSrc = argv.e || argv.expression 20 | } else { 21 | var filePath = argv.f || argv.file || argv._[0] 22 | originalSrc = fs.readFileSync(path.resolve(filePath), {encoding: "utf8"}) 23 | result = SolidityXParser.parse(originalSrc); 24 | outputFile = argv._[1] || argv.outputfile 25 | } 26 | SolidityXCompiler.compileToSolidityToFile(originalSrc, result, outputFile) 27 | 28 | } catch (e) { 29 | console.error(e.message) 30 | process.exit(1); 31 | } 32 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solidityx-js", 3 | "version": "0.4.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ansi-regex": { 8 | "version": "2.1.1", 9 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 10 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 11 | }, 12 | "builtin-modules": { 13 | "version": "1.1.1", 14 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 15 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" 16 | }, 17 | "camelcase": { 18 | "version": "3.0.0", 19 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", 20 | "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" 21 | }, 22 | "cliui": { 23 | "version": "3.2.0", 24 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", 25 | "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", 26 | "requires": { 27 | "string-width": "1.0.2", 28 | "strip-ansi": "3.0.1", 29 | "wrap-ansi": "2.1.0" 30 | } 31 | }, 32 | "code-point-at": { 33 | "version": "1.1.0", 34 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 35 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" 36 | }, 37 | "commander": { 38 | "version": "2.3.0", 39 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", 40 | "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=" 41 | }, 42 | "debug": { 43 | "version": "2.2.0", 44 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", 45 | "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", 46 | "requires": { 47 | "ms": "0.7.1" 48 | } 49 | }, 50 | "decamelize": { 51 | "version": "1.2.0", 52 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 53 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 54 | }, 55 | "diff": { 56 | "version": "1.4.0", 57 | "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", 58 | "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=" 59 | }, 60 | "error-ex": { 61 | "version": "1.3.1", 62 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", 63 | "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", 64 | "requires": { 65 | "is-arrayish": "0.2.1" 66 | } 67 | }, 68 | "escape-string-regexp": { 69 | "version": "1.0.2", 70 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", 71 | "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=" 72 | }, 73 | "find-up": { 74 | "version": "1.1.2", 75 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", 76 | "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", 77 | "requires": { 78 | "path-exists": "2.1.0", 79 | "pinkie-promise": "2.0.1" 80 | } 81 | }, 82 | "get-caller-file": { 83 | "version": "1.0.2", 84 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", 85 | "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" 86 | }, 87 | "glob": { 88 | "version": "3.2.11", 89 | "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", 90 | "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", 91 | "requires": { 92 | "inherits": "2.0.3", 93 | "minimatch": "0.3.0" 94 | } 95 | }, 96 | "graceful-fs": { 97 | "version": "4.1.11", 98 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", 99 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" 100 | }, 101 | "growl": { 102 | "version": "1.9.2", 103 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", 104 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=" 105 | }, 106 | "hosted-git-info": { 107 | "version": "2.5.0", 108 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", 109 | "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==" 110 | }, 111 | "inherits": { 112 | "version": "2.0.3", 113 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 114 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 115 | }, 116 | "invert-kv": { 117 | "version": "1.0.0", 118 | "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", 119 | "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" 120 | }, 121 | "is-arrayish": { 122 | "version": "0.2.1", 123 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 124 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" 125 | }, 126 | "is-builtin-module": { 127 | "version": "1.0.0", 128 | "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", 129 | "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", 130 | "requires": { 131 | "builtin-modules": "1.1.1" 132 | } 133 | }, 134 | "is-fullwidth-code-point": { 135 | "version": "1.0.0", 136 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 137 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 138 | "requires": { 139 | "number-is-nan": "1.0.1" 140 | } 141 | }, 142 | "is-utf8": { 143 | "version": "0.2.1", 144 | "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", 145 | "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" 146 | }, 147 | "jade": { 148 | "version": "0.26.3", 149 | "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", 150 | "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", 151 | "requires": { 152 | "commander": "0.6.1", 153 | "mkdirp": "0.3.0" 154 | }, 155 | "dependencies": { 156 | "commander": { 157 | "version": "0.6.1", 158 | "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", 159 | "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=" 160 | }, 161 | "mkdirp": { 162 | "version": "0.3.0", 163 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", 164 | "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=" 165 | } 166 | } 167 | }, 168 | "lcid": { 169 | "version": "1.0.0", 170 | "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", 171 | "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", 172 | "requires": { 173 | "invert-kv": "1.0.0" 174 | } 175 | }, 176 | "load-json-file": { 177 | "version": "1.1.0", 178 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", 179 | "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", 180 | "requires": { 181 | "graceful-fs": "4.1.11", 182 | "parse-json": "2.2.0", 183 | "pify": "2.3.0", 184 | "pinkie-promise": "2.0.1", 185 | "strip-bom": "2.0.0" 186 | } 187 | }, 188 | "lodash.assign": { 189 | "version": "4.2.0", 190 | "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", 191 | "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" 192 | }, 193 | "lru-cache": { 194 | "version": "2.7.3", 195 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", 196 | "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" 197 | }, 198 | "minimatch": { 199 | "version": "0.3.0", 200 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", 201 | "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", 202 | "requires": { 203 | "lru-cache": "2.7.3", 204 | "sigmund": "1.0.1" 205 | } 206 | }, 207 | "minimist": { 208 | "version": "0.0.8", 209 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 210 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 211 | }, 212 | "mkdirp": { 213 | "version": "0.5.1", 214 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 215 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 216 | "requires": { 217 | "minimist": "0.0.8" 218 | } 219 | }, 220 | "mocha": { 221 | "version": "2.5.3", 222 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", 223 | "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", 224 | "requires": { 225 | "commander": "2.3.0", 226 | "debug": "2.2.0", 227 | "diff": "1.4.0", 228 | "escape-string-regexp": "1.0.2", 229 | "glob": "3.2.11", 230 | "growl": "1.9.2", 231 | "jade": "0.26.3", 232 | "mkdirp": "0.5.1", 233 | "supports-color": "1.2.0", 234 | "to-iso-string": "0.0.2" 235 | } 236 | }, 237 | "ms": { 238 | "version": "0.7.1", 239 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", 240 | "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" 241 | }, 242 | "normalize-package-data": { 243 | "version": "2.4.0", 244 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", 245 | "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", 246 | "requires": { 247 | "hosted-git-info": "2.5.0", 248 | "is-builtin-module": "1.0.0", 249 | "semver": "5.4.1", 250 | "validate-npm-package-license": "3.0.1" 251 | } 252 | }, 253 | "number-is-nan": { 254 | "version": "1.0.1", 255 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 256 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" 257 | }, 258 | "os-locale": { 259 | "version": "1.4.0", 260 | "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", 261 | "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", 262 | "requires": { 263 | "lcid": "1.0.0" 264 | } 265 | }, 266 | "parse-json": { 267 | "version": "2.2.0", 268 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", 269 | "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", 270 | "requires": { 271 | "error-ex": "1.3.1" 272 | } 273 | }, 274 | "path-exists": { 275 | "version": "2.1.0", 276 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", 277 | "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", 278 | "requires": { 279 | "pinkie-promise": "2.0.1" 280 | } 281 | }, 282 | "path-type": { 283 | "version": "1.1.0", 284 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", 285 | "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", 286 | "requires": { 287 | "graceful-fs": "4.1.11", 288 | "pify": "2.3.0", 289 | "pinkie-promise": "2.0.1" 290 | } 291 | }, 292 | "pegjs": { 293 | "version": "0.10.0", 294 | "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", 295 | "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=" 296 | }, 297 | "pify": { 298 | "version": "2.3.0", 299 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 300 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" 301 | }, 302 | "pinkie": { 303 | "version": "2.0.4", 304 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 305 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" 306 | }, 307 | "pinkie-promise": { 308 | "version": "2.0.1", 309 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 310 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 311 | "requires": { 312 | "pinkie": "2.0.4" 313 | } 314 | }, 315 | "read-pkg": { 316 | "version": "1.1.0", 317 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", 318 | "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", 319 | "requires": { 320 | "load-json-file": "1.1.0", 321 | "normalize-package-data": "2.4.0", 322 | "path-type": "1.1.0" 323 | } 324 | }, 325 | "read-pkg-up": { 326 | "version": "1.0.1", 327 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", 328 | "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", 329 | "requires": { 330 | "find-up": "1.1.2", 331 | "read-pkg": "1.1.0" 332 | } 333 | }, 334 | "require-directory": { 335 | "version": "2.1.1", 336 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 337 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" 338 | }, 339 | "require-main-filename": { 340 | "version": "1.0.1", 341 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", 342 | "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" 343 | }, 344 | "semver": { 345 | "version": "5.4.1", 346 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", 347 | "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" 348 | }, 349 | "set-blocking": { 350 | "version": "2.0.0", 351 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 352 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" 353 | }, 354 | "sigmund": { 355 | "version": "1.0.1", 356 | "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", 357 | "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" 358 | }, 359 | "spdx-correct": { 360 | "version": "1.0.2", 361 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", 362 | "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", 363 | "requires": { 364 | "spdx-license-ids": "1.2.2" 365 | } 366 | }, 367 | "spdx-expression-parse": { 368 | "version": "1.0.4", 369 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", 370 | "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" 371 | }, 372 | "spdx-license-ids": { 373 | "version": "1.2.2", 374 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", 375 | "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" 376 | }, 377 | "string-width": { 378 | "version": "1.0.2", 379 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 380 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 381 | "requires": { 382 | "code-point-at": "1.1.0", 383 | "is-fullwidth-code-point": "1.0.0", 384 | "strip-ansi": "3.0.1" 385 | } 386 | }, 387 | "strip-ansi": { 388 | "version": "3.0.1", 389 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 390 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 391 | "requires": { 392 | "ansi-regex": "2.1.1" 393 | } 394 | }, 395 | "strip-bom": { 396 | "version": "2.0.0", 397 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", 398 | "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", 399 | "requires": { 400 | "is-utf8": "0.2.1" 401 | } 402 | }, 403 | "supports-color": { 404 | "version": "1.2.0", 405 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", 406 | "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=" 407 | }, 408 | "to-iso-string": { 409 | "version": "0.0.2", 410 | "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", 411 | "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=" 412 | }, 413 | "validate-npm-package-license": { 414 | "version": "3.0.1", 415 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", 416 | "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", 417 | "requires": { 418 | "spdx-correct": "1.0.2", 419 | "spdx-expression-parse": "1.0.4" 420 | } 421 | }, 422 | "which-module": { 423 | "version": "1.0.0", 424 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", 425 | "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" 426 | }, 427 | "window-size": { 428 | "version": "0.2.0", 429 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", 430 | "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" 431 | }, 432 | "wrap-ansi": { 433 | "version": "2.1.0", 434 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", 435 | "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", 436 | "requires": { 437 | "string-width": "1.0.2", 438 | "strip-ansi": "3.0.1" 439 | } 440 | }, 441 | "y18n": { 442 | "version": "3.2.1", 443 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", 444 | "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" 445 | }, 446 | "yargs": { 447 | "version": "4.8.1", 448 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", 449 | "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", 450 | "requires": { 451 | "cliui": "3.2.0", 452 | "decamelize": "1.2.0", 453 | "get-caller-file": "1.0.2", 454 | "lodash.assign": "4.2.0", 455 | "os-locale": "1.4.0", 456 | "read-pkg-up": "1.0.1", 457 | "require-directory": "2.1.1", 458 | "require-main-filename": "1.0.1", 459 | "set-blocking": "2.0.0", 460 | "string-width": "1.0.2", 461 | "which-module": "1.0.0", 462 | "window-size": "0.2.0", 463 | "y18n": "3.2.1", 464 | "yargs-parser": "2.4.1" 465 | } 466 | }, 467 | "yargs-parser": { 468 | "version": "2.4.1", 469 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", 470 | "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", 471 | "requires": { 472 | "camelcase": "3.0.0", 473 | "lodash.assign": "4.2.0" 474 | } 475 | } 476 | } 477 | } 478 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solidityx-js", 3 | "version": "0.4.0", 4 | "description": "SolidityX to Solidity compiler for Javascript", 5 | "main": "index.js", 6 | "scripts": { 7 | "prepublish": "npm run build", 8 | "build": "mkdirp ./build && pegjs -o ./build/parser.js ./grammar/solidityx.pegjs", 9 | "test": "mocha --timeout 5000 --reporter spec", 10 | "lint": "eslint ." 11 | }, 12 | "bin": { 13 | "solidityX": "./main.js" 14 | }, 15 | "contributors": [ 16 | { 17 | "name": "Matthew Campbell", 18 | "email": "matt@loomx.io", 19 | "url": "https://loomx.io" 20 | } 21 | ], 22 | "license": "MIT", 23 | "dependencies": { 24 | "mocha": "^2.4.5", 25 | "pegjs": "^0.10.0", 26 | "yargs": "^4.6.0" 27 | }, 28 | "devDependencies": { 29 | "mkdirp": "^0.5.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/default.js: -------------------------------------------------------------------------------- 1 | var SolidityParser = require("../index.js"); 2 | 3 | describe("Parser", function() { 4 | it("parses soliditX examples without throwing an error", function() { 5 | SolidityParser.parseFile("./test/voting.solx", true); 6 | }); 7 | }); 8 | 9 | describe("Built Parser", function() { 10 | it("parses soliditX examples without throwing an error", function() { 11 | SolidityParser.parseFile("./test/voting.solx", false); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/voting.solx: -------------------------------------------------------------------------------- 1 | //Random sample code, modified to solidityX 2 | 3 | pragmax solidityX ^0.1.1; 4 | pragma solidity ^0.4.11; 5 | // We have to specify what version of compiler this code will compile with 6 | 7 | contract Voting { 8 | /* mapping field below is equivalent to an associative array or hash. 9 | The key of the mapping is candidate name stored as type bytes32 and value is 10 | an unsigned integer to store the vote count 11 | */ 12 | 13 | mapping (bytes32 => uint8) public votesReceived; 14 | 15 | /* Solidity doesn't let you pass in an array of strings in the constructor (yet). 16 | We will use an array of bytes32 instead to store the list of candidates 17 | */ 18 | 19 | bytes32[] public candidateList; 20 | 21 | /* This is the constructor which will be called once when you 22 | deploy the contract to the blockchain. When we deploy the contract, 23 | we will pass an array of candidates who will be contesting in the election 24 | */ 25 | function Voting(bytes32[] candidateNames) { 26 | candidateList = candidateNames; 27 | } 28 | 29 | // This function returns the total votes a candidate has received so far 30 | function totalVotesFor(bytes32 candidate) returns (uint8) { 31 | if (candidate.exists? == false) throw; 32 | return votesReceived[candidate]; 33 | } 34 | 35 | // This function increments the vote count for the specified candidate. This 36 | // is equivalent to casting a vote 37 | function voteForCandidate(bytes32 candidate) { 38 | if (candidate.exists? == false) throw; 39 | votesReceived[candidate] += 1; 40 | } 41 | } -------------------------------------------------------------------------------- /test/voting_orig.sol: -------------------------------------------------------------------------------- 1 | //Random sample code, modified to solidityX 2 | 3 | pragmax solidityx ^0.1.1; 4 | pragma solidity ^0.4.11; 5 | // We have to specify what version of compiler this code will compile with 6 | 7 | contract Voting { 8 | /* mapping field below is equivalent to an associative array or hash. 9 | The key of the mapping is candidate name stored as type bytes32 and value is 10 | an unsigned integer to store the vote count 11 | */ 12 | 13 | mapping (bytes32 => uint8) public votesReceived; 14 | 15 | /* Solidity doesn't let you pass in an array of strings in the constructor (yet). 16 | We will use an array of bytes32 instead to store the list of candidates 17 | */ 18 | 19 | bytes32[] public candidateList; 20 | 21 | /* This is the constructor which will be called once when you 22 | deploy the contract to the blockchain. When we deploy the contract, 23 | we will pass an array of candidates who will be contesting in the election 24 | */ 25 | function Voting(bytes32[] candidateNames) { 26 | candidateList = candidateNames; 27 | } 28 | 29 | // This function returns the total votes a candidate has received so far 30 | function totalVotesFor(bytes32 candidate) returns (uint8) { 31 | if (validCandidate(candidate) == false) throw; 32 | return votesReceived[candidate]; 33 | } 34 | 35 | // This function increments the vote count for the specified candidate. This 36 | // is equivalent to casting a vote 37 | function voteForCandidate(bytes32 candidate) { 38 | if (validCandidate(candidate) == false) throw; 39 | votesReceived[candidate] += 1; 40 | } 41 | 42 | function validCandidate(bytes32 candidate) returns (bool) { 43 | for(uint i = 0; i < candidateList.length; i++) { 44 | if (candidateList[i] == candidate) { 45 | return true; 46 | } 47 | } 48 | return false; 49 | } 50 | } --------------------------------------------------------------------------------