├── testData ├── ide │ ├── formatter │ │ ├── ifElse.rho │ │ ├── parens.rho │ │ ├── mapMethods.rho │ │ ├── ifElseFormatted.rho │ │ ├── parensFormatted.rho │ │ ├── URI.rho │ │ ├── URIFormatted.rho │ │ ├── mapMethodsFormatted.rho │ │ ├── complex.rho │ │ └── complexFormatted.rho │ └── folding │ │ └── procedure.rho ├── parser │ ├── token.rho │ └── token.txt └── lexer │ ├── token.rho │ └── token.txt ├── docs ├── settings-page.png └── beta-0.1.0.svg ├── src ├── coop │ └── rchain │ │ └── lang │ │ ├── formatter │ │ ├── RholangWrappingProcessor.kt │ │ ├── RholangBlockContext.kt │ │ ├── settings │ │ │ └── RholangCodeStyleSettingsProvider.kt │ │ ├── RholangFormattingModelBuilder.kt │ │ ├── RholangSpaceProcessor.kt │ │ ├── RholangIndentProcessor.kt │ │ └── RholangBlock.kt │ │ ├── icons │ │ └── rholang-red-16.png │ │ ├── RhoIcons.kt │ │ ├── RhoLanguage.kt │ │ ├── psi │ │ ├── RhoFile.kt │ │ └── RhoElements.kt │ │ ├── RhoCommenter.kt │ │ ├── RhoFileType.kt │ │ ├── util │ │ └── PsiTreeHelpUtil.kt │ │ ├── RhoHighlightingAnnotator.kt │ │ ├── RhoColors.kt │ │ ├── folding │ │ └── RholangFoldingBuilder.kt │ │ ├── RhoParserDefinition.kt │ │ ├── RhoColorSettingsPage.kt │ │ ├── Rho.flex │ │ ├── RhoSyntaxHighlighter.kt │ │ └── Rho.bnf ├── rholang.cf └── rholang-mercury.cf ├── .idea ├── codeStyles │ ├── codeStyleConfig.xml │ └── Project.xml ├── vcs.xml ├── modules.xml ├── misc.xml ├── codeStyleSettings.xml └── rholang-idea.iml ├── test └── coop │ └── rchain │ ├── RholangTestUtil.kt │ ├── lang │ ├── parser │ │ └── RholangParserTest.kt │ └── lexer │ │ └── RholangLexTest.kt │ └── ide │ └── folding │ └── RholangCodeInsightTest.kt ├── .editorconfig ├── CONTRIBUTING.md ├── LICENSE ├── .gitignore ├── resources └── META-INF │ └── plugin.xml └── README.md /testData/ide/formatter/ifElse.rho: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /testData/ide/formatter/parens.rho: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /testData/ide/formatter/mapMethods.rho: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /testData/ide/formatter/ifElseFormatted.rho: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /testData/ide/formatter/parensFormatted.rho: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/settings-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tgrospic/rholang-idea/HEAD/docs/settings-page.png -------------------------------------------------------------------------------- /src/coop/rchain/lang/formatter/RholangWrappingProcessor.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang.formatter 2 | 3 | class RholangWrappingProcessor 4 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/icons/rholang-red-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tgrospic/rholang-idea/HEAD/src/coop/rchain/lang/icons/rholang-red-16.png -------------------------------------------------------------------------------- /testData/ide/formatter/URI.rho: -------------------------------------------------------------------------------- 1 | new ack, stdout(`rho:io:stdout`), stdoutAck(`rho:io:stdoutAck`) in { stdoutAck!("hello, world!", *ack) | for (_ <- ack) { stdout!("received") } } 2 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testData/ide/folding/procedure.rho: -------------------------------------------------------------------------------- 1 | new time_contract in { 2 | contract time_contract(stream) = { 3 | log-time(stream) 4 | } | 5 | time_contract!(ostream-new("test.txt")) | 6 | time_contract!(ostream-new("test2.txt")) 7 | } 8 | -------------------------------------------------------------------------------- /test/coop/rchain/RholangTestUtil.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain 2 | 3 | import java.io.File 4 | 5 | object RholangTestUtil { 6 | val testDataPath = File("testData").absolutePath 7 | val baseTestDataPath: String 8 | get() = testDataPath 9 | } 10 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/RhoIcons.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang 2 | 3 | import com.intellij.openapi.util.IconLoader 4 | 5 | object RhoIcons { 6 | val RED_EDITION = IconLoader.getIcon("/coop/rchain/lang/icons/rholang-red-16.png") 7 | 8 | val DEFAULT = RED_EDITION 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.{md}] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /testData/ide/formatter/URIFormatted.rho: -------------------------------------------------------------------------------- 1 | // A simple Hello World contract 2 | new helloworld in { 3 | contract helloworld( world ) = { 4 | for( msg <- world ) { 5 | print(msg) 6 | } 7 | } | 8 | new world in { 9 | helloworld!(world) | 10 | world!("Hello World") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/RhoLanguage.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang 2 | 3 | import com.intellij.lang.Language 4 | 5 | class RhoLanguage private constructor() : Language("Rholang") { 6 | override fun isCaseSensitive() = true 7 | 8 | override fun getDisplayName() = "Rholang" 9 | 10 | companion object { 11 | val INSTANCE = RhoLanguage() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /testData/parser/token.rho: -------------------------------------------------------------------------------- 1 | new testResult, philosopher1, philosopher2 in { 2 | new north, south, knife, spoon in { 3 | north!(*knife) | 4 | south!(*spoon) | 5 | for (@knf <- north; @spn <- south) { 6 | philosopher1!(true) | 7 | north!(knf) | 8 | south!(spn) 9 | } | 10 | for (@spn <- south; @knf <- north) { 11 | philosopher2!(true) | 12 | north!(knf) | 13 | south!(spn) 14 | } 15 | } | 16 | for(_ <- philosopher1; _ <- philosopher2) { 17 | testResult!(true) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/coop/rchain/lang/parser/RholangParserTest.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang.parser 2 | 3 | import com.intellij.testFramework.ParsingTestCase 4 | import coop.rchain.RholangTestUtil 5 | import coop.rchain.lang.RhoParserDefinition 6 | import java.nio.file.Paths 7 | 8 | class RholangParserTest : ParsingTestCase("", "rho", RhoParserDefinition()) { 9 | 10 | override fun getTestDataPath(): String { 11 | return Paths.get(RholangTestUtil.baseTestDataPath, "parser").toString() 12 | } 13 | 14 | fun testtoken() { 15 | doTest(true) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/formatter/RholangBlockContext.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang.formatter 2 | 3 | import com.intellij.formatting.FormattingMode 4 | import com.intellij.psi.codeStyle.CodeStyleSettings 5 | import com.intellij.psi.codeStyle.CommonCodeStyleSettings 6 | import coop.rchain.lang.RhoLanguage 7 | 8 | class RholangBlockContext(val settings: CodeStyleSettings, val mode: FormattingMode) { 9 | val rholangSettings: CommonCodeStyleSettings 10 | 11 | init { 12 | rholangSettings = settings.getCommonSettings(RhoLanguage.INSTANCE) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.idea/codeStyleSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 17 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/psi/RhoFile.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang.psi 2 | 3 | import com.intellij.extapi.psi.PsiFileBase 4 | import com.intellij.openapi.fileTypes.FileType 5 | import com.intellij.psi.FileViewProvider 6 | import coop.rchain.lang.RhoFileType 7 | import coop.rchain.lang.RhoLanguage 8 | 9 | import javax.swing.* 10 | 11 | class RhoFile(viewProvider: FileViewProvider) : PsiFileBase(viewProvider, RhoLanguage.Companion.INSTANCE) { 12 | 13 | override fun getFileType(): FileType { 14 | return RhoFileType.Companion.INSTANCE 15 | } 16 | 17 | override fun toString(): String { 18 | return "Rholang File" 19 | } 20 | 21 | override fun getIcon(flags: Int): Icon? { 22 | return super.getIcon(flags) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/coop/rchain/lang/lexer/RholangLexTest.kt: -------------------------------------------------------------------------------- 1 | //package coop.rchain.lang.lexer 2 | // 3 | //import com.intellij.lexer.Lexer 4 | //import com.intellij.testFramework.LexerTestCase 5 | //import coop.rchain.RholangTestUtil 6 | //import coop.rchain.lang.RhoLexerAdapter 7 | // 8 | //import java.nio.file.Paths 9 | // 10 | //class RholangLexTest : LexerTestCase() { 11 | // 12 | // override fun createLexer(): Lexer { 13 | // return RhoLexerAdapter() 14 | // } 15 | // 16 | // override fun getDirPath(): String = 17 | // Paths.get(RholangTestUtil.baseTestDataPath, "lexer").toString() 18 | // 19 | // override fun getPathToTestDataFile(extension: String): String = 20 | // this.getDirPath() + "/" + this.getTestName(true) + extension 21 | // 22 | // fun testToken() { 23 | // doFileTest("rho") 24 | // } 25 | //} 26 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Any suggestions, bugs, testing, pull-requests, issues are very welcome. 4 | 5 | ## Development setup 6 | 7 | More info on [README##development](./README.md##development) page section. 8 | 9 | ## TODO 10 | 11 | - write more tests and configure CI 12 | - write [Completion Contributor][idea-completion] 13 | - write [Reference Contributor][idea-reference] 14 | - add [plugin actions][idea-plugin-actions] 15 | - connect with the compiler (get semantic info) 16 | - ... 17 | 18 | [idea-completion]: https://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support/completion_contributor.html 19 | [idea-reference]: https://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support/reference_contributor.html 20 | [idea-plugin-actions]: https://www.jetbrains.org/intellij/sdk/docs/basics/action_system.html 21 | -------------------------------------------------------------------------------- /docs/beta-0.1.0.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | beta 16 | beta 17 | v0.1.0 18 | v0.1.0 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/RhoCommenter.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang 2 | 3 | import com.intellij.lang.Commenter 4 | import com.intellij.psi.tree.IElementType 5 | import coop.rchain.lang.psi.RhoTypes 6 | 7 | class RhoCommenter : Commenter { 8 | override fun getLineCommentPrefix(): String? { 9 | return "//" 10 | } 11 | 12 | override fun getBlockCommentPrefix(): String? { 13 | return "/*" 14 | } 15 | 16 | override fun getBlockCommentSuffix(): String? { 17 | return "*/" 18 | } 19 | 20 | override fun getCommentedBlockCommentPrefix(): String? { 21 | return null 22 | } 23 | 24 | override fun getCommentedBlockCommentSuffix(): String? { 25 | return null 26 | } 27 | 28 | val lineCommentTokenType: IElementType? 29 | get() = RhoTypes.LINE_COMMENT 30 | 31 | val blockCommentTokenType: IElementType? 32 | get() = RhoTypes.BLOCK_COMMENT 33 | } 34 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/psi/RhoElements.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang.psi 2 | 3 | import com.intellij.extapi.psi.ASTWrapperPsiElement 4 | import com.intellij.lang.ASTNode 5 | import com.intellij.psi.PsiElement 6 | import com.intellij.psi.tree.IElementType 7 | import coop.rchain.lang.RhoLanguage 8 | import org.jetbrains.annotations.NonNls 9 | 10 | class RhoElementType(@NonNls debugName: String) : IElementType(debugName, RhoLanguage.INSTANCE) 11 | 12 | class RhoTokenType(@NonNls debugName: String) : IElementType(debugName, RhoLanguage.INSTANCE) 13 | 14 | // Named element 15 | interface RhoNamedElement : RhoCompositeElement 16 | 17 | abstract class RhoNamedElementImpl(node: ASTNode) : RhoCompositeElementImpl(node), RhoNamedElement 18 | 19 | interface RhoCompositeElement : PsiElement 20 | 21 | abstract class RhoCompositeElementImpl(node: ASTNode) : ASTWrapperPsiElement(node), RhoCompositeElement 22 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/RhoFileType.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang 2 | 3 | import com.intellij.openapi.fileTypes.FileTypeConsumer 4 | import com.intellij.openapi.fileTypes.FileTypeFactory 5 | import com.intellij.openapi.fileTypes.LanguageFileType 6 | 7 | import javax.swing.* 8 | 9 | class RhoFileTypeFactory : FileTypeFactory() { 10 | override fun createFileTypes(fileTypeConsumer: FileTypeConsumer) { 11 | fileTypeConsumer.consume(RhoFileType.INSTANCE, "rho") 12 | } 13 | } 14 | 15 | class RhoFileType private constructor() : LanguageFileType(RhoLanguage.INSTANCE) { 16 | 17 | override fun getName(): String { 18 | return "Rholang file" 19 | } 20 | 21 | override fun getDescription(): String { 22 | return name 23 | } 24 | 25 | override fun getDefaultExtension(): String { 26 | return "rho" 27 | } 28 | 29 | override fun getIcon(): Icon? { 30 | return RhoIcons.DEFAULT 31 | } 32 | 33 | companion object { 34 | val INSTANCE = RhoFileType() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/formatter/settings/RholangCodeStyleSettingsProvider.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang.formatter.settings 2 | 3 | import com.intellij.lang.Language 4 | import com.intellij.psi.codeStyle.CommonCodeStyleSettings 5 | import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider 6 | import coop.rchain.lang.RhoLanguage 7 | 8 | class RholangCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvider() { 9 | override fun getLanguage(): Language { 10 | return RhoLanguage.INSTANCE 11 | } 12 | 13 | override fun getCodeSample(settingsType: LanguageCodeStyleSettingsProvider.SettingsType): String? { 14 | return null 15 | } 16 | 17 | override fun getDefaultCommonSettings(): CommonCodeStyleSettings? { 18 | val defaultSettings = CommonCodeStyleSettings(language) 19 | val indentOptions = defaultSettings.initIndentOptions() 20 | indentOptions.INDENT_SIZE = 2 21 | indentOptions.CONTINUATION_INDENT_SIZE = 2 22 | return defaultSettings 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.idea/rholang-idea.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /testData/ide/formatter/mapMethodsFormatted.rho: -------------------------------------------------------------------------------- 1 | // all methods modifying the underlying collection return new Map 2 | // prints 1 3 | new stdout in { stdout!({"one" : 2, "two" : 2, "three" : 3}.get("one")) | 4 | // if element is not present in the map will return Nil -- prints Nil 5 | stdout!({ 6 | "one" : 1, "two" : 2, "three" : 3}.get("four")) | 7 | // prints false 8 | stdout!({"one" : 1, "two" : 2, "three" : 3}.contains("four")) | 9 | // prints true 10 | stdout!({"one" : 1, "two" : 2, "three" : 3}.contains("three")) | 11 | // prints @{{"three" : 3, "two" : 2}} 12 | stdout!({"one" : 1, "two" : 2, "three" : 3}.delete("one")) | 13 | // doesn't change the collection, prints @{{"one" : 1, "three" : 3, "two" : 2}} 14 | stdout!({"one" : 1, "two" : 2, "three" : 3}.delete("four")) | 15 | // returns new map which is a result of subtracting elements of second map from the base map 16 | stdout!({"one" : 1, "two" : 2, "three" : 3}.diff({"one" : 1, "four": 4})) | 17 | // merges two maps -- returns @{{"four" : 4, "one" : 1, "three" : 3, "two" : 2}} 18 | stdout!({"one" : 1, "two" : 2, "three" : 3}.union({"one" : 1, "four": 4})) 19 | } 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-present RChain.coop (Tomislav Grospic) 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 | -------------------------------------------------------------------------------- /testData/ide/formatter/complex.rho: -------------------------------------------------------------------------------- 1 | new testResult, updateTestResult in { testResult!(true) | contract updateTestResult(@bool, return) = { for(@r <- testResult) { match [r, bool] { [true, true] => { testResult!(true) | return!(true) } _ => { testResult!(false) | return!(false) } } } } | contract @"CoatCheckDemo"(_) = { new MakeCoatCheck in { contract MakeCoatCheck(ret) = { new port, table in { ret!(*port) | for(@"new", @arg, ack <= port) { new ticket in { ack!(*ticket) | @{*ticket | *table}!(arg) } } | for(@"get", @arg, ack <= port) { for (@value <- @{arg | *table}) { @{arg | *table}!(value) | ack!(value) } } | for(@"set", @arg1, @arg2, ack <= port) { for (_ <- @{arg1 | *table}) { @{arg1 | *table}!(arg2) | ack!(true) } } } } | 2 | // Usage 3 | new ret, get, set in { MakeCoatCheck!(*ret) | for (cc <- ret) { 4 | // Creates new cell with initial value 0 5 | cc!("new", 0, *ret) | for (ticket <- ret) { contract get(return) = { cc!("get", *ticket, *return) } | contract set(@value, return) = { cc!("set", *ticket, value, *return) } | get!(*ret) | for(@r <- ret) { updateTestResult!(r == 0, *ret) | for(_ <- ret){ set!(1, *ret) | for(_ <- ret) { get!(*ret) | for(@r <- ret) { updateTestResult!(r == 1, *ret) } } } } } } } } } | @"CoatCheckDemo"!(Nil) } 6 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/util/PsiTreeHelpUtil.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang.util 2 | 3 | import com.intellij.lang.ASTNode 4 | import com.intellij.psi.PsiComment 5 | import com.intellij.psi.PsiElement 6 | import com.intellij.psi.PsiWhiteSpace 7 | import com.intellij.psi.util.PsiTreeUtil 8 | 9 | object PsiTreeHelpUtil { 10 | 11 | fun getPrevSiblingSkipWhiteSpacesAndComments(sibling: ASTNode?): ASTNode? { 12 | if (sibling == null) return null 13 | var treePrev: ASTNode? = sibling.treePrev 14 | while (treePrev != null && isWhitespaceOrComment(treePrev.psi)) { 15 | treePrev = treePrev.treePrev 16 | } 17 | return treePrev 18 | } 19 | 20 | /** 21 | * The difference of this method from getPrevSiblingSkipWhiteSpacesAndComments is that this one obtain the previous leaf node rather than sibling. 22 | * @param current 23 | * @return 24 | */ 25 | fun getPrevLeafSkipWhiteSpacesAndComments(current: ASTNode?): PsiElement? { 26 | if (current == null) return null 27 | var treePrev = PsiTreeUtil.prevLeaf(current.psi) 28 | while (treePrev != null && isWhitespaceOrComment(treePrev)) { 29 | treePrev = PsiTreeUtil.prevLeaf(treePrev) 30 | } 31 | return treePrev 32 | } 33 | 34 | private fun isWhitespaceOrComment(psi: PsiElement): Boolean { 35 | return psi is PsiWhiteSpace || psi is PsiComment 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 2 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 3 | 4 | # User-specific stuff: 5 | .idea/**/workspace.xml 6 | .idea/**/tasks.xml 7 | .idea/dictionaries 8 | 9 | # Sensitive or high-churn files: 10 | .idea/**/dataSources/ 11 | .idea/**/dataSources.ids 12 | .idea/**/dataSources.local.xml 13 | .idea/**/sqlDataSources.xml 14 | .idea/**/dynamic.xml 15 | .idea/**/uiDesigner.xml 16 | 17 | # Gradle: 18 | .idea/**/gradle.xml 19 | .idea/**/libraries 20 | 21 | # CMake 22 | cmake-build-debug/ 23 | cmake-build-release/ 24 | 25 | # Mongo Explorer plugin: 26 | .idea/**/mongoSettings.xml 27 | 28 | ## File-based project format: 29 | *.iws 30 | 31 | ## Plugin-specific files: 32 | 33 | # IntelliJ 34 | out/ 35 | 36 | # mpeltonen/sbt-idea plugin 37 | .idea_modules/ 38 | 39 | # JIRA plugin 40 | atlassian-ide-plugin.xml 41 | 42 | # Cursive Clojure plugin 43 | .idea/replstate.xml 44 | 45 | # Crashlytics plugin (for Android Studio and IntelliJ) 46 | com_crashlytics_export_strings.xml 47 | crashlytics.properties 48 | crashlytics-build.properties 49 | fabric.properties 50 | 51 | # Generated code from parser and lexer 52 | gen/ 53 | 54 | # Generated plugin 55 | .idea/rholang-idea.jar 56 | .idea/rholang-idea.zip 57 | 58 | *.java~ 59 | /*.jar 60 | 61 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/RhoHighlightingAnnotator.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang 2 | 3 | import com.intellij.lang.annotation.AnnotationHolder 4 | import com.intellij.lang.annotation.Annotator 5 | import com.intellij.psi.PsiElement 6 | import coop.rchain.lang.psi.* 7 | 8 | class RhoHighlightingAnnotator : Annotator { 9 | 10 | override fun annotate(element: PsiElement, holder: AnnotationHolder) { 11 | val (partToHighlight, color) = highlightElement(element) ?: return 12 | 13 | holder.createInfoAnnotation(partToHighlight, null).textAttributes = color.textAttributesKey 14 | } 15 | 16 | private fun highlightElement(element: PsiElement): Pair? = when (element) { 17 | is RhoNamedElement -> { 18 | val color = colorFor(element) 19 | val part = partToHighlight(element) 20 | if (color != null && part != null) 21 | part to color else null 22 | } 23 | else -> null 24 | } 25 | } 26 | 27 | private fun colorFor(element: RhoCompositeElement): RhoColor? = when (element) { 28 | // is RhoContractName -> RhoColor.FUNCTION 29 | // is RhoConstrName -> RhoColor.CONSTRUCTOR 30 | // is RhoChan -> RhoColor.PARAMETER 31 | // is RhoTypeTerm -> RhoColor.TYPE_PARAMETER 32 | is RhoNameVar-> RhoColor.RHO_NAME 33 | // is RhoFnName -> RhoColor.FUNCTION 34 | // is RhoCPattern_ -> RhoColor.BIND_PARAMETER 35 | // is RhoChanRefSymbol -> RhoColor.KEYWORD 36 | else -> null 37 | } 38 | 39 | private fun partToHighlight(element: RhoNamedElement): PsiElement? = when (element) { 40 | is RhoNamedElement -> element 41 | else -> null 42 | } 43 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/formatter/RholangFormattingModelBuilder.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang.formatter 2 | 3 | import com.intellij.formatting.FormatTextRanges 4 | import com.intellij.formatting.FormattingMode 5 | import com.intellij.formatting.FormattingModel 6 | import com.intellij.formatting.FormattingModelBuilderEx 7 | import com.intellij.lang.ASTNode 8 | import com.intellij.openapi.util.TextRange 9 | import com.intellij.psi.PsiElement 10 | import com.intellij.psi.PsiFile 11 | import com.intellij.psi.codeStyle.CodeStyleSettings 12 | import com.intellij.psi.codeStyle.CommonCodeStyleSettings 13 | import com.intellij.psi.formatter.DocumentBasedFormattingModel 14 | 15 | class RholangFormattingModelBuilder : FormattingModelBuilderEx { 16 | override fun createModel(element: PsiElement, settings: CodeStyleSettings, mode: FormattingMode): FormattingModel { 17 | val psiFile = element.containingFile 18 | val rootNode = psiFile.node 19 | val context = RholangBlockContext(settings, mode) 20 | val rootBlock = RholangBlock(rootNode, null, null, settings, context) 21 | return DocumentBasedFormattingModel(rootBlock, element.project, settings, psiFile.fileType, psiFile) 22 | } 23 | 24 | override fun getIndentOptionsToUse(file: PsiFile, ranges: FormatTextRanges, settings: CodeStyleSettings): CommonCodeStyleSettings.IndentOptions? { 25 | return null 26 | } 27 | 28 | override fun createModel(element: PsiElement, settings: CodeStyleSettings): FormattingModel { 29 | return createModel(element, settings, FormattingMode.REFORMAT) 30 | } 31 | 32 | override fun getRangeAffectingIndent(file: PsiFile, offset: Int, elementAtOffset: ASTNode): TextRange? { 33 | return null 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test/coop/rchain/ide/folding/RholangCodeInsightTest.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.ide.folding 2 | 3 | import com.intellij.openapi.command.WriteCommandAction 4 | import com.intellij.openapi.util.TextRange 5 | import com.intellij.psi.codeStyle.CodeStyleManager 6 | import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase 7 | import com.intellij.util.containers.ContainerUtil 8 | import coop.rchain.RholangTestUtil 9 | 10 | 11 | class RholangCodeInsightTest : LightCodeInsightFixtureTestCase() { 12 | override fun getTestDataPath(): String { 13 | return RholangTestUtil.baseTestDataPath 14 | } 15 | 16 | fun testFolding() { 17 | doTestFolding("blockDocComment") 18 | doTestFolding("procedure") 19 | } 20 | 21 | fun testFormatter() { 22 | object : WriteCommandAction.Simple(project) { 23 | @Throws(Throwable::class) 24 | override fun run() { 25 | myFixture.configureByFiles("./ide/formatter/token.rho") 26 | CodeStyleManager.getInstance(project).reformatText(myFixture.file, 27 | ContainerUtil.newArrayList(myFixture.file.textRange)) 28 | } 29 | }.execute() 30 | myFixture.checkResultByFile("./ide/formatter/tokenFormatted.rho") 31 | } 32 | 33 | fun testFormatter2() { 34 | object : WriteCommandAction.Simple(project) { 35 | @Throws(Throwable::class) 36 | override fun run() { 37 | myFixture.configureByFiles("./ide/formatter/simpleOne.rho") 38 | CodeStyleManager.getInstance(project).reformatText(myFixture.file, 39 | ContainerUtil.newArrayList(myFixture.file.textRange)) 40 | } 41 | }.execute() 42 | myFixture.checkResultByFile("./ide/formatter/simpleOneFormatted.rho") 43 | } 44 | 45 | private fun doTestFolding(testName: String) { 46 | myFixture.testFolding("$testDataPath/ide/folding/$testName.rho") 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/RhoColors.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang 2 | 3 | import com.intellij.openapi.editor.colors.TextAttributesKey 4 | import com.intellij.openapi.options.colors.AttributesDescriptor 5 | import com.intellij.openapi.editor.DefaultLanguageHighlighterColors as DefaultColor 6 | import com.intellij.ide.highlighter.JavaHighlightingColors 7 | import com.intellij.openapi.editor.HighlighterColors 8 | 9 | /** 10 | * See [RhoColorSettingsPage] and [RhoSyntaxHighlighter] 11 | */ 12 | enum class RhoColor(humanName: String, default: TextAttributesKey) { 13 | FUNCTION("Function declaration",DefaultColor.FUNCTION_DECLARATION), 14 | CONSTRUCTOR("Constructor", DefaultColor.FUNCTION_CALL), 15 | TYPE_PARAMETER("Type parameter", JavaHighlightingColors.TYPE_PARAMETER_NAME_ATTRIBUTES), 16 | BIND_PARAMETER("Bind parameter", JavaHighlightingColors.LOCAL_VARIABLE_ATTRIBUTES), 17 | PARAMETER("Parameter", JavaHighlightingColors.INSTANCE_FIELD_ATTRIBUTES), 18 | 19 | KEYWORD("Keyword", DefaultColor.KEYWORD), 20 | IDENTIFIER("Identifier", DefaultColor.IDENTIFIER), 21 | BLOCK_COMMENT("Comment block", DefaultColor.BLOCK_COMMENT), 22 | LINE_COMMENT("Comment line", DefaultColor.LINE_COMMENT), 23 | DOC_COMMENT("Comment documentation", DefaultColor.DOC_COMMENT), 24 | STRING("String", DefaultColor.STRING), 25 | NUMBER("Number", DefaultColor.NUMBER), 26 | BRACKETS("Brackets", DefaultColor.BRACKETS), 27 | BRACES("Braces", DefaultColor.BRACES), 28 | PARENTHESIS("Parenthesis", DefaultColor.PARENTHESES), 29 | COMMA("Comma", DefaultColor.COMMA), 30 | SEMICOLON("Semicolon", DefaultColor.SEMICOLON), 31 | OPERATORS("Operators", DefaultColor.OPERATION_SIGN), 32 | BAD_CHAR("Bad character", HighlighterColors.BAD_CHARACTER), 33 | RHO_NAME("RhoName", DefaultColor.CONSTANT), 34 | ; 35 | 36 | val textAttributesKey = TextAttributesKey.createTextAttributesKey("coop.rchain.rholang.$name", default) 37 | val attributesDescriptor = AttributesDescriptor(humanName, textAttributesKey) 38 | } 39 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/formatter/RholangSpaceProcessor.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang.formatter 2 | 3 | import com.intellij.formatting.Block 4 | import com.intellij.formatting.Spacing 5 | import com.intellij.lang.ASTNode 6 | import com.intellij.openapi.editor.Document 7 | import com.intellij.openapi.util.TextRange 8 | import com.intellij.psi.PsiElement 9 | import com.intellij.psi.codeStyle.CommonCodeStyleSettings 10 | import com.intellij.psi.formatter.common.AbstractBlock 11 | import com.intellij.psi.tree.IElementType 12 | import com.intellij.psi.util.PsiTreeUtil 13 | import coop.rchain.lang.psi.RhoTypes 14 | import coop.rchain.lang.util.PsiTreeHelpUtil 15 | 16 | class RholangSpaceProcessor(private val myNode: ASTNode, private val mySettings: CommonCodeStyleSettings) { 17 | 18 | fun getSpacing(child1: Block?, child2: Block): Spacing? { 19 | if (child1 !is AbstractBlock || child2 !is AbstractBlock) { 20 | return null 21 | } 22 | 23 | val elementType = myNode.elementType 24 | val parentType = if (myNode.treeParent == null) null else myNode.treeParent.elementType 25 | val node1 = child1.node 26 | val type1 = node1.elementType 27 | val node2 = child2.node 28 | val type2 = node2.elementType 29 | 30 | if (type1 === RhoTypes.OPEN_BRACE && (type2 === RhoTypes.PROC || type2 === RhoTypes.CASE)) { 31 | if(parentType !== RhoTypes.NAME_) { 32 | return Spacing.createSpacing(1, 1, 1, false, 0) 33 | } 34 | } 35 | if (type1 === RhoTypes.BITWISE_OR && myNode.treeParent?.treeParent?.elementType !== RhoTypes.NAME_) { 36 | return Spacing.createSpacing(1, 1, 1, false, 0) 37 | } 38 | 39 | if(type1 === RhoTypes.CASE_ || type2 === RhoTypes.CASE_){ 40 | return Spacing.createSpacing(1, 1, 1, false, 0) 41 | } 42 | 43 | if(type2 === RhoTypes.CLOSE_BRACE && parentType === RhoTypes.NAME_){ 44 | return null 45 | } 46 | 47 | return if (type2 === RhoTypes.CLOSE_BRACE) { 48 | Spacing.createSpacing(1, 1, 1, false, 0) 49 | } else null 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/folding/RholangFoldingBuilder.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang.folding 2 | 3 | import com.intellij.lang.ASTNode 4 | import com.intellij.lang.folding.FoldingBuilder 5 | import com.intellij.lang.folding.FoldingDescriptor 6 | import com.intellij.openapi.editor.Document 7 | import com.intellij.openapi.project.DumbAware 8 | import com.intellij.openapi.util.TextRange 9 | import com.intellij.psi.PsiElement 10 | import coop.rchain.lang.psi.RhoTypes 11 | import java.util.* 12 | 13 | class RholangFoldingBuilder : FoldingBuilder, DumbAware { 14 | 15 | override fun buildFoldRegions(node: ASTNode, document: Document): Array { 16 | val descriptors = ArrayList() 17 | appendDescriptors(node.psi, descriptors, document) 18 | 19 | return descriptors.toTypedArray() 20 | } 21 | 22 | private fun appendDescriptors(psi: PsiElement, descriptors: MutableList, document: Document) { 23 | if (isSingleLine(psi, document)) { // don't fold when text is single line 24 | return 25 | } 26 | 27 | val elementType = psi.node.elementType 28 | 29 | if (elementType === RhoTypes.PROC_BLOCK) { 30 | val textRange = psi.node.textRange 31 | val textRange1 = TextRange(textRange.startOffset + 1, textRange.endOffset - 1) 32 | descriptors.add(FoldingDescriptor(psi.node, textRange1)) 33 | } 34 | 35 | var child: PsiElement? = psi.firstChild 36 | while (child != null) { 37 | appendDescriptors(child, descriptors, document) 38 | child = child.nextSibling 39 | } 40 | } 41 | 42 | 43 | private fun isSingleLine(element: PsiElement, document: Document): Boolean { 44 | val textRange = element.textRange 45 | return document.getLineNumber(textRange.startOffset) == document.getLineNumber(textRange.endOffset) 46 | } 47 | 48 | override fun getPlaceholderText(node: ASTNode): String? { 49 | return "..." 50 | } 51 | 52 | override fun isCollapsedByDefault(node: ASTNode): Boolean { 53 | return false 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/RhoParserDefinition.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang 2 | 3 | import com.intellij.lang.ASTNode 4 | import com.intellij.lang.ParserDefinition 5 | import com.intellij.lang.PsiParser 6 | import com.intellij.lexer.FlexAdapter 7 | import com.intellij.lexer.Lexer 8 | import com.intellij.openapi.project.Project 9 | import com.intellij.psi.FileViewProvider 10 | import com.intellij.psi.PsiElement 11 | import com.intellij.psi.PsiFile 12 | import com.intellij.psi.TokenType 13 | import com.intellij.psi.tree.IFileElementType 14 | import com.intellij.psi.tree.TokenSet 15 | import coop.rchain.lang.RhoParser 16 | import coop.rchain.lang.psi.RhoFile 17 | import coop.rchain.lang.psi.RhoTypes 18 | 19 | import java.io.Reader 20 | 21 | class RhoParserDefinition : ParserDefinition { 22 | 23 | override fun createLexer(project: Project): Lexer { 24 | return FlexAdapter(RhoLexer(null as Reader?)) 25 | } 26 | 27 | override fun getWhitespaceTokens(): TokenSet { 28 | return WHITE_SPACES 29 | } 30 | 31 | override fun getCommentTokens(): TokenSet { 32 | return COMMENTS 33 | } 34 | 35 | override fun getStringLiteralElements(): TokenSet { 36 | return TokenSet.EMPTY 37 | } 38 | 39 | override fun createParser(project: Project): PsiParser { 40 | return RhoParser() 41 | } 42 | 43 | override fun getFileNodeType(): IFileElementType { 44 | return FILE 45 | } 46 | 47 | override fun createFile(viewProvider: FileViewProvider): PsiFile { 48 | return RhoFile(viewProvider) 49 | } 50 | 51 | override fun spaceExistanceTypeBetweenTokens(left: ASTNode, right: ASTNode): ParserDefinition.SpaceRequirements { 52 | return ParserDefinition.SpaceRequirements.MAY 53 | } 54 | 55 | override fun createElement(node: ASTNode): PsiElement { 56 | return RhoTypes.Factory.createElement(node) 57 | } 58 | 59 | companion object { 60 | val WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE) 61 | val COMMENTS = TokenSet.create(RhoTypes.LINE_COMMENT) 62 | val FILE = IFileElementType(RhoLanguage.Companion.INSTANCE) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/formatter/RholangIndentProcessor.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang.formatter 2 | 3 | import com.intellij.formatting.FormattingMode 4 | import com.intellij.formatting.Indent 5 | import com.intellij.lang.ASTNode 6 | import com.intellij.psi.codeStyle.CommonCodeStyleSettings 7 | import coop.rchain.lang.psi.RhoTypes 8 | import coop.rchain.lang.util.PsiTreeHelpUtil 9 | 10 | class RholangIndentProcessor(private val settings: CommonCodeStyleSettings) { 11 | 12 | fun getChildIndent(node: ASTNode, mode: FormattingMode): Indent { 13 | val elementType = node.elementType 14 | val parent = node.treeParent 15 | val parentType = parent?.elementType 16 | val grandParent = parent?.treeParent 17 | val grandParentType = grandParent?.elementType 18 | val prevSibling = PsiTreeHelpUtil.getPrevSiblingSkipWhiteSpacesAndComments(node) 19 | val prevSiblingType = prevSibling?.elementType 20 | if (parent == null || grandParent == null || grandParent.treeParent == null) { 21 | return Indent.getNoneIndent() 22 | } 23 | 24 | // if (grandParentType === RhoTypes.BIND_PAREN) { 25 | // return Indent.getContinuationIndent() 26 | // } 27 | 28 | // if (elementType === RhoTypes.PM_BRANCH) { 29 | // return Indent.getNormalIndent() 30 | // } 31 | 32 | if (parentType === RhoTypes.PROC_PAREN_OPTION ) { 33 | return if (elementType === RhoTypes.OPEN_PAREN || elementType === RhoTypes.CLOSE_PAREN) { 34 | Indent.getNoneIndent() 35 | } else Indent.getContinuationIndent() 36 | } 37 | 38 | if (parentType === RhoTypes.PROC_BLOCK || parentType === RhoTypes.PROC_BLOCK || parentType === RhoTypes.CASE_BLOCK ) { 39 | return if (elementType === RhoTypes.OPEN_BRACE || elementType === RhoTypes.CLOSE_BRACE) { 40 | Indent.getNoneIndent() 41 | } else Indent.getNormalIndent() 42 | } 43 | 44 | // return if (grandParentType === RhoTypes.QUANTITY_ && parentType === RhoTypes.PROC) { 45 | // Indent.getContinuationIndent() 46 | // } else Indent.getNoneIndent() 47 | return Indent.getNoneIndent() 48 | 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/RhoColorSettingsPage.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang 2 | 3 | import com.intellij.application.options.colors.InspectionColorSettingsPage 4 | import com.intellij.openapi.options.colors.ColorDescriptor 5 | import com.intellij.openapi.options.colors.ColorSettingsPage 6 | import com.intellij.psi.codeStyle.DisplayPriority 7 | import com.intellij.psi.codeStyle.DisplayPrioritySortable 8 | 9 | class RhoColorSettingsPage : ColorSettingsPage, InspectionColorSettingsPage, DisplayPrioritySortable { 10 | private val ATTRS = RhoColor.values().map { it.attributesDescriptor }.toTypedArray() 11 | 12 | private val ANNOTATOR_TAGS = RhoColor.values().associateBy({ it.name }, { it.textAttributesKey }) 13 | 14 | private val DEMO_TEXT by lazy { 15 | """/** 16 | * Rholang is a behaviorally typed, concurrent programming language, 17 | * with a focus on message-passing and formally modeled by the ρ-calculus, 18 | * a reflective, higher-order extension of the π-calculus. 19 | */ 20 | new helloworld in { 21 | contract helloworld( world ) = { 22 | for( msg <- world ) { 23 | // Hello from Rholang! 24 | print( msg ) 25 | } 26 | } | 27 | /* 28 | * It is designed to be used to implement protocols and "smart contracts" 29 | * on a general-purpose blockchain, but could be used in other settings as well. 30 | */ 31 | new world in { 32 | helloworld!( world ) | 33 | world!( "Hello World" ) 34 | } 35 | } 36 | """ 37 | } 38 | 39 | override fun getDisplayName() = "Rholang" 40 | override fun getIcon() = RhoIcons.DEFAULT 41 | override fun getAttributeDescriptors() = ATTRS 42 | override fun getColorDescriptors(): Array = ColorDescriptor.EMPTY_ARRAY 43 | override fun getHighlighter() = RhoSyntaxHighlighter() 44 | override fun getAdditionalHighlightingTagToDescriptorMap() = ANNOTATOR_TAGS 45 | override fun getDemoText() = DEMO_TEXT 46 | override fun getPriority(): DisplayPriority = DisplayPriority.KEY_LANGUAGE_SETTINGS 47 | } 48 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/formatter/RholangBlock.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang.formatter 2 | 3 | import com.intellij.formatting.* 4 | import com.intellij.formatting.templateLanguages.BlockWithParent 5 | import com.intellij.lang.ASTNode 6 | import com.intellij.psi.codeStyle.CodeStyleSettings 7 | import com.intellij.psi.formatter.FormatterUtil 8 | import com.intellij.psi.formatter.common.AbstractBlock 9 | 10 | import java.util.ArrayList 11 | 12 | class RholangBlock(node: ASTNode, wrap: Wrap?, alignment: Alignment?, private val mySettings: CodeStyleSettings, private val myContext: RholangBlockContext) : AbstractBlock(node, wrap, alignment), BlockWithParent { 13 | private val myIndentProcessor: RholangIndentProcessor 14 | private val myIndet: Indent 15 | private val mySpacingProcessor: RholangSpaceProcessor 16 | private var myParent: BlockWithParent? = null 17 | 18 | init { 19 | myIndentProcessor = RholangIndentProcessor(myContext.rholangSettings) 20 | myIndet = myIndentProcessor.getChildIndent(node, myContext.mode) 21 | mySpacingProcessor = RholangSpaceProcessor(node, myContext.rholangSettings) 22 | } 23 | 24 | override fun buildChildren(): List { 25 | if (isLeaf) { 26 | return AbstractBlock.EMPTY 27 | } 28 | 29 | val blockChildren = ArrayList() 30 | var childNode: ASTNode? = node.firstChildNode 31 | while (childNode != null) { 32 | if (!FormatterUtil.containsWhiteSpacesOnly(childNode)) { 33 | val childBlock = RholangBlock(childNode, Wrap.createWrap(WrapType.NONE, false), null, mySettings, myContext) 34 | childBlock.setParent(this) 35 | blockChildren.add(childBlock) 36 | } 37 | childNode = childNode.treeNext 38 | } 39 | return blockChildren 40 | } 41 | 42 | override fun getIndent(): Indent? { 43 | return myIndet 44 | } 45 | 46 | override fun getSpacing(child1: Block?, child2: Block): Spacing? { 47 | return mySpacingProcessor.getSpacing(child1, child2) 48 | } 49 | 50 | override fun isLeaf(): Boolean { 51 | return false 52 | } 53 | 54 | override fun getParent(): BlockWithParent? { 55 | return myParent 56 | } 57 | 58 | override fun setParent(newParent: BlockWithParent) { 59 | myParent = newParent 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /testData/ide/formatter/complexFormatted.rho: -------------------------------------------------------------------------------- 1 | new testResult, updateTestResult in { 2 | testResult!(true) | 3 | contract updateTestResult(@bool, return) = { 4 | for(@r <- testResult) { 5 | match [r, bool] { 6 | [true, true] => { 7 | testResult!(true) | 8 | return!(true) 9 | } 10 | _ => { 11 | testResult!(false) | 12 | return!(false) 13 | } 14 | } 15 | } 16 | } | 17 | contract @"CoatCheckDemo"(_) = { 18 | new MakeCoatCheck in { 19 | contract MakeCoatCheck(ret) = { 20 | new port, table in { 21 | ret!(*port) | 22 | for(@"new", @arg, ack <= port) { 23 | new ticket in { 24 | ack!(*ticket) | 25 | @{*ticket | *table}!(arg) 26 | } 27 | } | 28 | for(@"get", @arg, ack <= port) { 29 | for (@value <- @{arg | *table}) { 30 | @{arg | *table}!(value) | 31 | ack!(value) 32 | } 33 | } | 34 | for(@"set", @arg1, @arg2, ack <= port) { 35 | for (_ <- @{arg1 | *table}) { 36 | @{arg1 | *table}!(arg2) | 37 | ack!(true) 38 | } 39 | } 40 | } 41 | } | 42 | // Usage 43 | new ret, get, set in { 44 | MakeCoatCheck!(*ret) | 45 | for (cc <- ret) { 46 | // Creates new cell with initial value 0 47 | cc!("new", 0, *ret) | 48 | for (ticket <- ret) { 49 | contract get(return) = { 50 | cc!("get", *ticket, *return) 51 | } | 52 | contract set(@value, return) = { 53 | cc!("set", *ticket, value, *return) 54 | } | 55 | get!(*ret) | 56 | for(@r <- ret) { 57 | updateTestResult!(r == 0, *ret) | 58 | for(_ <- ret){ 59 | set!(1, *ret) | 60 | for(_ <- ret) { 61 | get!(*ret) | 62 | for(@r <- ret) { 63 | updateTestResult!(r == 1, *ret) 64 | } 65 | } 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } | 73 | @"CoatCheckDemo"!(Nil) 74 | } 75 | -------------------------------------------------------------------------------- /resources/META-INF/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | coop.rchain.lang 3 | Rholang 4 | 0.2.0 5 | RChain.coop 6 | 7 | Rholang. 9 | 10 | Official language for RChain distributed virtual machine.

11 | ]]>
12 | 13 | 15 |
  • 0.2.0 @AbnerZheng: 16 |
      17 |
    • Updated grammar for Rholang Mercury release.
    • 18 |
    19 |
  • 20 |
  • 0.1.0 @AbnerZheng: 21 |
      22 |
    • Implemented formatting feature.
    • 23 |
    • Updated grammar (quick fix before Mercury) @tgrospic
    • 24 |
    25 |
  • 26 |
  • 0.0.4 @AbnerZheng: 27 |
      28 |
    • Implemented folding feature.
    • 29 |
    • Added initial tests.
    • 30 |
    31 |
  • 32 |
  • 0.0.3: 33 |
      34 |
    • Syntax: Contracts as processes (recursive).
    • 35 |
    • Syntax: Fix arithmetic operators.
    • 36 |
    • New file icon.
    • 37 |
    38 |
  • 39 |
  • 0.0.2: Update plugin name.
  • 40 |
  • 0.0.1: Syntax highlighting and comments support. Initial version.
  • 41 | 42 | ]]> 43 |
    44 | 45 | 46 | 47 | 48 | 50 | com.intellij.modules.lang 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
    71 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/Rho.flex: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang; 2 | 3 | import com.intellij.lexer.FlexLexer; 4 | import com.intellij.psi.tree.IElementType; 5 | 6 | import static com.intellij.psi.TokenType.BAD_CHARACTER; 7 | import static com.intellij.psi.TokenType.WHITE_SPACE; 8 | import static coop.rchain.lang.psi.RhoTypes.*; 9 | %% 10 | 11 | %{ 12 | public RhoLexer() { 13 | this((java.io.Reader)null); 14 | } 15 | %} 16 | 17 | %public 18 | %class RhoLexer 19 | %implements FlexLexer 20 | %function advance 21 | %type IElementType 22 | %unicode 23 | 24 | EOL=\R 25 | WHITE_SPACE=\s+ 26 | 27 | SPACE=[ \t\n\x0B\f\r]+ 28 | LINE_COMMENT = "//".* 29 | INTEGER=[0-9]+(\.[0-9]*)? 30 | ID_NAME=([a-zA-Z'][a-zA-Z_0-9']*)|([_a-zA-Z0-9']+) 31 | StringLit=('([^'\\]|\\.)*'|\"([^\"\\]|\\.)*\") 32 | URI=`([^`\\]|\\[`\\])*` 33 | 34 | %% 35 | { 36 | {WHITE_SPACE} { return WHITE_SPACE; } 37 | 38 | "contract" { return CONTRACT; } 39 | "select" { return SELECT; } 40 | "match" { return MATCH; } 41 | "for" { return FOR; } 42 | "new" { return NEW; } 43 | "if" { return IF; } 44 | "else" { return ELSE; } 45 | "in" { return IN; } 46 | "false" { return FALSE; } 47 | "true" { return TRUE; } 48 | "Nil" { return NIL; } 49 | "=>" { return FAT_ARROW; } 50 | "->" { return THIN_ARROW; } 51 | "." { return DOT; } 52 | "&" { return BITWISE_AND; } 53 | "|" { return BITWISE_OR; } 54 | "^" { return BITWISE_XOR; } 55 | "..." { return TRIPLE_DOT; } 56 | ".." { return DOUBLE_DOT; } 57 | "::" { return DOUBLE_COLON; } 58 | ":" { return COLON; } 59 | "+" { return PLUS; } 60 | "-" { return MINUS; } 61 | "*" { return MULTIPLY; } 62 | "/" { return DIVIDE; } 63 | "%" { return REMAINDER; } 64 | "<<=" { return ASSIGN_LEFT_SHIFT; } 65 | ">>=" { return ASSIGN_RIGHT_SHIFT; } 66 | "==" { return EQUAL; } 67 | "=" { return ASSIGN; } 68 | "!=" { return NOT_EQUAL; } 69 | "<=" { return LESS_THAN_OR_EQUAL; } 70 | "<" { return LESS_THAN; } 71 | ">=" { return GREATER_THAN_OR_EQUAL; } 72 | ">" { return GREATER_THAN; } 73 | "!" { return NOT; } 74 | "~" { return BOX; } 75 | "@" { return AT; } 76 | "'" { return SINGLE_QUOTE; } 77 | "$" { return DOLLAR; } 78 | "#" { return HASH; } 79 | "[" { return OPEN_SQUARE_BRACKET; } 80 | "]" { return CLOSE_SQUARE_BRACKET; } 81 | "(" { return OPEN_PAREN; } 82 | ")" { return CLOSE_PAREN; } 83 | "{" { return OPEN_BRACE; } 84 | "}" { return CLOSE_BRACE; } 85 | "," { return COMMA; } 86 | ";" { return SEMICOLON; } 87 | "_" { return UNDERSCORE; } 88 | 89 | {SPACE} { return SPACE; } 90 | {LINE_COMMENT} { return LINE_COMMENT; } 91 | {INTEGER} { return INTEGER; } 92 | {ID_NAME} { return ID_NAME; } 93 | {StringLit} { return STRINGLIT; } 94 | {URI} { return URI; } 95 | 96 | } 97 | 98 | [^] { return BAD_CHARACTER; } 99 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/RhoSyntaxHighlighter.kt: -------------------------------------------------------------------------------- 1 | package coop.rchain.lang 2 | 3 | import com.intellij.lexer.FlexAdapter 4 | import com.intellij.lexer.Lexer 5 | import com.intellij.openapi.editor.colors.TextAttributesKey 6 | import com.intellij.openapi.fileTypes.SyntaxHighlighter 7 | import com.intellij.openapi.fileTypes.SyntaxHighlighterBase 8 | import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory 9 | import com.intellij.openapi.project.Project 10 | import com.intellij.openapi.vfs.VirtualFile 11 | import com.intellij.psi.tree.IElementType 12 | import coop.rchain.lang.psi.RhoTypes.* 13 | import java.io.Reader 14 | 15 | class RhoSyntaxHighlighterFactory : SyntaxHighlighterFactory() { 16 | override fun getSyntaxHighlighter(project: Project?, virtualFile: VirtualFile?): SyntaxHighlighter = RhoSyntaxHighlighter() 17 | } 18 | 19 | class RhoSyntaxHighlighter : SyntaxHighlighterBase() { 20 | 21 | override fun getHighlightingLexer(): Lexer = FlexAdapter(RhoLexer(null as Reader?)) 22 | 23 | override fun getTokenHighlights(tokenType: IElementType): Array = 24 | pack(map(tokenType)?.textAttributesKey) 25 | 26 | companion object { 27 | fun map(tokenType: IElementType?): RhoColor? = when (tokenType) { 28 | TRUE, FALSE, 29 | CONTRACT, MATCH, FOR, NIL, NEW, SELECT, 30 | IF, IN, ELSE, 31 | UNDERSCORE -> RhoColor.KEYWORD 32 | 33 | VAR -> RhoColor.IDENTIFIER 34 | 35 | STRINGLIT -> RhoColor.STRING 36 | URI -> RhoColor.NUMBER 37 | INTEGER -> RhoColor.NUMBER 38 | RHO_NAME -> RhoColor.RHO_NAME 39 | 40 | 41 | LINE_COMMENT -> RhoColor.LINE_COMMENT 42 | BLOCK_COMMENT -> RhoColor.BLOCK_COMMENT 43 | 44 | OPEN_PAREN, CLOSE_PAREN -> RhoColor.PARENTHESIS 45 | OPEN_BRACE, CLOSE_BRACE -> RhoColor.BRACES 46 | OPEN_SQUARE_BRACKET, CLOSE_SQUARE_BRACKET -> RhoColor.BRACKETS 47 | 48 | SEMICOLON -> RhoColor.SEMICOLON 49 | COMMA -> RhoColor.COMMA 50 | 51 | // Operators 52 | HASH, DOLLAR, AT -> RhoColor.OPERATORS 53 | TRIPLE_DOT -> RhoColor.OPERATORS 54 | DOUBLE_DOT -> RhoColor.OPERATORS 55 | ASSIGN_RIGHT_SHIFT -> RhoColor.OPERATORS 56 | ASSIGN_LEFT_SHIFT -> RhoColor.OPERATORS 57 | FAT_ARROW -> RhoColor.OPERATORS 58 | THIN_ARROW -> RhoColor.OPERATORS 59 | DOT -> RhoColor.OPERATORS 60 | BITWISE_AND -> RhoColor.OPERATORS 61 | BITWISE_OR -> RhoColor.OPERATORS 62 | BITWISE_XOR -> RhoColor.OPERATORS 63 | DOUBLE_COLON -> RhoColor.OPERATORS 64 | COLON -> RhoColor.OPERATORS 65 | PLUS -> RhoColor.OPERATORS 66 | MINUS -> RhoColor.OPERATORS 67 | MULTIPLY -> RhoColor.OPERATORS 68 | DIVIDE -> RhoColor.OPERATORS 69 | REMAINDER -> RhoColor.OPERATORS 70 | EQUAL -> RhoColor.OPERATORS 71 | ASSIGN -> RhoColor.OPERATORS 72 | NOT_EQUAL -> RhoColor.OPERATORS 73 | LESS_THAN_OR_EQUAL -> RhoColor.OPERATORS 74 | LESS_THAN -> RhoColor.OPERATORS 75 | GREATER_THAN_OR_EQUAL -> RhoColor.OPERATORS 76 | GREATER_THAN -> RhoColor.OPERATORS 77 | NOT -> RhoColor.OPERATORS 78 | BOX -> RhoColor.OPERATORS 79 | SINGLE_QUOTE -> RhoColor.OPERATORS 80 | OPEN_SQUARE_BRACKET -> RhoColor.OPERATORS 81 | CLOSE_SQUARE_BRACKET -> RhoColor.OPERATORS 82 | OPEN_PAREN -> RhoColor.OPERATORS 83 | CLOSE_PAREN -> RhoColor.OPERATORS 84 | OPEN_BRACE -> RhoColor.OPERATORS 85 | CLOSE_BRACE -> RhoColor.OPERATORS 86 | COMMA -> RhoColor.OPERATORS 87 | SEMICOLON -> RhoColor.OPERATORS 88 | 89 | else -> null 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/rholang.cf: -------------------------------------------------------------------------------- 1 | -- https://github.com/rchain/rchain/blob/1f5450e8e54b2bbce7d81206eb8d4fdd6bc96797/rholang/src/main/bnfc/rholang.cf 2 | 3 | -- Top level contract declaration 4 | DContr. Contr ::= Proc1 ; 5 | 6 | -- Processes 7 | PNil. Proc4 ::= "Nil" ; 8 | PValue. Proc4 ::= Value; 9 | PDrop. Proc3 ::= "*" Chan ; 10 | PLift. Proc2 ::= Chan "!" "(" [Proc] ")" ; 11 | PInput. Proc1 ::= "for" "(" [Bind] ")" "{" Proc "}" ; 12 | PChoice. Proc1 ::= "select" "{" [CBranch] "}" ; 13 | PMatch. Proc1 ::= "match" Proc "with" [PMBranch] ; 14 | PNew. Proc1 ::= "new" [Var] "in" Proc1 ; 15 | PConstr. Proc1 ::= Var "(" [Proc] ")" ; 16 | PContr. Proc1 ::= "contract" Var "(" [CPattern] ")" "=" "{" Proc "}" ; 17 | PPar. Proc ::= Proc "|" Proc1 ; 18 | separator Proc "," ; 19 | _. Proc ::= Proc1 ; 20 | _. Proc1 ::= Proc2 ; 21 | _. Proc2 ::= Proc3 ; 22 | _. Proc3 ::= Proc4 ; 23 | _. Proc4 ::= "{" Proc "}" ; 24 | 25 | -- Channels 26 | CVar. Chan ::= Var ; 27 | CQuote. Chan ::= "@" Proc3 ; 28 | 29 | -- Variable binding 30 | InputBind. Bind ::= CPattern "<-" Chan ; 31 | CondInputBind. Bind ::= CPattern "<-" Chan "if" Proc ; 32 | separator nonempty Bind ";" ; 33 | 34 | -- Pattern match branches 35 | PatternMatch. PMBranch ::= PPattern "=>" "{" Proc "}" ; 36 | separator nonempty PMBranch "" ; 37 | 38 | -- Choice branch 39 | Choice. CBranch ::= "case" [Bind] "=>" "{" Proc "}" ; 40 | separator nonempty CBranch "" ; 41 | 42 | -- Quantity 43 | QTrue. RhoBool ::= "true" ; 44 | QFalse. RhoBool ::= "false" ; 45 | QBool. Quantity7 ::= RhoBool ; 46 | QInt. Quantity7 ::= Integer ; 47 | QDouble. Quantity7 ::= Double ; 48 | QString. Quantity7 ::= String; 49 | QVar. Quantity7 ::= Var; 50 | QMap. Quantity7 ::= "Map()" ; 51 | QDot. Quantity6 ::= Quantity7 "." Var "(" [Quantity] ")" ; 52 | QNeg. Quantity5 ::= "-" Quantity6 ; 53 | QMult. Quantity4 ::= Quantity4 "*" Quantity5 ; 54 | QDiv. Quantity4 ::= Quantity4 "/" Quantity5 ; 55 | QAdd. Quantity3 ::= Quantity3 "+" Quantity4 ; 56 | QMinus. Quantity3 ::= Quantity3 "-" Quantity4 ; 57 | QLt. Quantity2 ::= Quantity2 "<" Quantity3 ; 58 | QLte. Quantity2 ::= Quantity2 "<=" Quantity3 ; 59 | QGt. Quantity2 ::= Quantity2 ">" Quantity3 ; 60 | QGte. Quantity2 ::= Quantity2 ">=" Quantity3 ; 61 | QEq. Quantity1 ::= Quantity1 "==" Quantity2 ; 62 | QNeq. Quantity1 ::= Quantity1 "!=" Quantity2 ; 63 | _. Quantity ::= Quantity1 ; 64 | _. Quantity1 ::= Quantity2 ; 65 | _. Quantity2 ::= Quantity3 ; 66 | _. Quantity3 ::= Quantity4 ; 67 | _. Quantity4 ::= Quantity5 ; 68 | _. Quantity5 ::= Quantity6 ; 69 | _. Quantity6 ::= Quantity7 ; 70 | _. Quantity7 ::= "(" Quantity ")" ; 71 | separator Quantity "," ; 72 | 73 | -- Values 74 | VQuant. Value ::= Quantity ; 75 | EChar. Value ::= Char ; 76 | ETuple. Value ::= "[" [Proc] "]" ; 77 | 78 | -- EStruct. Entity ::= Struct ; 79 | -- ECollect. Entity ::= Collect ; 80 | -- StructConstr. Struct ::= Var "{" [Proc] "}" ; 81 | -- CString. Collect ::= String ; 82 | -- EDate. Entity ::= Datetime ; 83 | -- CArray. Collect ::= Array ; 84 | -- CList. Collect ::= List ; 85 | 86 | -- Variable patterns 87 | VarPtVar. VarPattern ::= Var ; 88 | VarPtWild. VarPattern ::= "_" ; 89 | separator VarPattern "," ; 90 | 91 | -- Process patterns 92 | PPtVal. PPattern4 ::= ValPattern ; 93 | PPtVar. PPattern4 ::= VarPattern ; 94 | separator PPattern "," ; 95 | coercions PPattern 4 ; 96 | 97 | -- Channel patterns 98 | CPtVar. CPattern ::= VarPattern ; 99 | CValPtrn. CPattern ::= ValPattern ; 100 | CPtQuote. CPattern ::= "@" PPattern3 ; 101 | separator CPattern "," ; 102 | 103 | -- Value patterns 104 | 105 | -- We only allow for constants in pattern matches 106 | -- unlike for Procs which can have arbitrary operations 107 | VPtTuple. ValPattern ::= "[" [PPattern] "]" ; 108 | VPtTrue. ValPattern ::= "true" ; 109 | VPtFalse. ValPattern ::= "false" ; 110 | VPtInt. ValPattern ::= Integer ; 111 | VPtDbl. ValPattern ::= Double ; 112 | VPtNegInt. ValPattern ::= "-" Integer; 113 | VPtNegDbl. ValPattern ::= "-" Double; 114 | VPtStr. ValPattern ::= String ; 115 | 116 | -- Variables 117 | token Var ((letter | '_')(letter | digit | '_' | '\'')*) ; 118 | 119 | separator nonempty Var "," ; 120 | 121 | comment "//" ; 122 | comment "/*" "*/" ; 123 | -------------------------------------------------------------------------------- /src/rholang-mercury.cf: -------------------------------------------------------------------------------- 1 | -- A program is just a process. We put the coercions first, because that's what 2 | -- bnfc uses to determine the starting production. 3 | _. Proc ::= Proc1 ; 4 | _. Proc1 ::= Proc2 ; 5 | _. Proc2 ::= Proc3 ; 6 | _. Proc3 ::= Proc4 ; 7 | _. Proc4 ::= Proc5 ; 8 | _. Proc5 ::= Proc6 ; 9 | _. Proc6 ::= Proc7 ; 10 | _. Proc7 ::= Proc8 ; 11 | _. Proc8 ::= Proc9 ; 12 | _. Proc9 ::= Proc10 ; 13 | _. Proc10 ::= Proc11 ; 14 | _. Proc11 ::= Proc12 ; 15 | _. Proc12 ::= Proc13 ; 16 | _. Proc13 ::= Proc14 ; 17 | _. Proc14 ::= Proc15 ; 18 | _. Proc15 ::= Proc16 ; 19 | _. Proc16 ::= "{" Proc "}" ; 20 | 21 | -- Processes 22 | -- In general the expression style processes are higher precedence. 23 | -- Expression style is anything that necessary resolves to a single ground value 24 | -- or a collection. 25 | PGround. Proc16 ::= Ground ; 26 | PCollect. Proc16 ::= Collection ; 27 | PVar. Proc16 ::= ProcVar ; 28 | PVarRef. Proc13 ::= VarRefKind Var ; 29 | PNil. Proc16 ::= "Nil" ; 30 | PSimpleType. Proc16 ::= SimpleType ; 31 | PNegation. Proc15 ::= "~" Proc15 ; 32 | PConjunction. Proc14 ::= Proc14 "/\\" Proc15 ; 33 | PDisjunction. Proc13 ::= Proc13 "\\/" Proc14 ; 34 | PEval. Proc12 ::= "*" Name ; 35 | PMethod. Proc11 ::= Proc11 "." Var "(" [Proc] ")" ; 36 | PExprs. Proc11 ::= "(" Proc4 ")" ; 37 | PNot. Proc10 ::= "not" Proc10 ; 38 | PNeg. Proc10 ::= "-" Proc10 ; 39 | PMult. Proc9 ::= Proc9 "*" Proc10 ; 40 | PDiv. Proc9 ::= Proc9 "/" Proc10 ; 41 | PPercentPercent. Proc9 ::= Proc9 "%%" Proc10 ; 42 | PAdd. Proc8 ::= Proc8 "+" Proc9 ; 43 | PMinus. Proc8 ::= Proc8 "-" Proc9 ; 44 | PPlusPlus. Proc8 ::= Proc8 "++" Proc9 ; 45 | PMinusMinus. Proc8 ::= Proc8 "--" Proc9 ; 46 | PLt. Proc7 ::= Proc7 "<" Proc8 ; 47 | PLte. Proc7 ::= Proc7 "<=" Proc8 ; 48 | PGt. Proc7 ::= Proc7 ">" Proc8 ; 49 | PGte. Proc7 ::= Proc7 ">=" Proc8 ; 50 | PMatches. Proc6 ::= Proc7 "matches" Proc7 ; 51 | PEq. Proc6 ::= Proc6 "==" Proc7 ; 52 | PNeq. Proc6 ::= Proc6 "!=" Proc7 ; 53 | PAnd. Proc5 ::= Proc5 "and" Proc6 ; 54 | POr. Proc4 ::= Proc4 "or" Proc5 ; 55 | PSend. Proc3 ::= Name Send "(" [Proc] ")" ; 56 | PContr. Proc2 ::= "contract" Name "(" [Name] NameRemainder")" "=" "{" Proc "}" ; 57 | PInput. Proc2 ::= "for" "(" Receipt ")" "{" Proc "}" ; 58 | PChoice. Proc2 ::= "select" "{" [Branch] "}" ; 59 | PMatch. Proc2 ::= "match" Proc4 "{" [Case] "}" ; 60 | PBundle. Proc2 ::= Bundle "{" Proc "}" ; 61 | PIf. Proc1 ::= "if" "(" Proc ")" Proc2 ; 62 | -- Use precedence to force braces around an interior if. 63 | PIfElse. Proc1 ::= "if" "(" Proc ")" Proc2 "else" Proc1 ; 64 | PNew. Proc1 ::= "new" [NameDecl] "in" Proc1 ; 65 | PPar. Proc ::= Proc "|" Proc1 ; 66 | 67 | separator Proc "," ; 68 | 69 | -- Process variables 70 | ProcVarWildcard. ProcVar ::= "_" ; 71 | ProcVarVar. ProcVar ::= Var ; 72 | 73 | -- Names 74 | NameWildcard. Name ::= "_" ; 75 | NameVar. Name ::= Var ; 76 | NameQuote. Name ::= "@" Proc12 ; 77 | separator Name "," ; 78 | 79 | -- Bundle 80 | BundleWrite. Bundle ::= "bundle+" ; 81 | BundleRead. Bundle ::= "bundle-" ; 82 | BundleEquiv. Bundle ::= "bundle0" ; 83 | BundleReadWrite. Bundle ::= "bundle" ; 84 | 85 | -- Receipt 86 | ReceiptLinear. Receipt ::= ReceiptLinearImpl ; 87 | ReceiptRepeated. Receipt ::= ReceiptRepeatedImpl ; 88 | 89 | -- Linear Receipts 90 | LinearSimple. ReceiptLinearImpl ::= [LinearBind] ; 91 | -- Implementing this will be tricky. 92 | -- for (x <- a; y <- b if *x) 93 | -- LinearCond. Linear ::= [LinearBind] "if" Proc ; 94 | 95 | -- Single Linear Bind 96 | LinearBindImpl. LinearBind ::= [Name] NameRemainder "<-" Name ; 97 | separator nonempty LinearBind ";" ; 98 | 99 | -- Repeated Receipts 100 | RepeatedSimple. ReceiptRepeatedImpl ::= [RepeatedBind] ; 101 | -- Single Repeated Bind 102 | RepeatedBindImpl. RepeatedBind ::= [Name] NameRemainder "<=" Name ; 103 | separator nonempty RepeatedBind ";" ; 104 | 105 | -- Types of Send: 106 | SendSingle. Send ::= "!" ; 107 | SendMultiple. Send ::= "!!" ; 108 | 109 | -- Select Branches 110 | BranchImpl. Branch ::= ReceiptLinearImpl "=>" Proc3 ; 111 | separator nonempty Branch "" ; 112 | 113 | -- Match Cases 114 | CaseImpl. Case ::= Proc13 "=>" Proc3 ; 115 | separator nonempty Case "" ; 116 | 117 | -- Name Declarations. 118 | -- Eventually will have IOPairs. 119 | NameDeclSimpl. NameDecl ::= Var ; 120 | NameDeclUrn. NameDecl ::= Var "(" Uri ")" ; 121 | separator nonempty NameDecl "," ; 122 | 123 | -- Booleans: 124 | BoolTrue. Bool ::= "true" ; 125 | BoolFalse. Bool ::= "false" ; 126 | -- Ground types: 127 | GroundBool. Ground ::= Bool ; 128 | GroundInt. Ground ::= Integer ; 129 | GroundString. Ground ::= String ; 130 | GroundUri. Ground ::= Uri ; 131 | token Uri ('`' ((char - ["\\`"]) | ('\\' ["`\\"]))* '`') ; 132 | -- Collections: 133 | CollectList. Collection ::= "[" [Proc] ProcRemainder "]" ; 134 | CollectTuple. Collection ::= Tuple; 135 | CollectSet. Collection ::= "Set" "(" [Proc] ")" ; 136 | CollectMap. Collection ::= "{" [KeyValuePair] "}" ; 137 | KeyValuePairImpl. KeyValuePair ::= Proc ":" Proc ; 138 | separator KeyValuePair "," ; 139 | 140 | TupleSingle. Tuple ::= "(" Proc ",)" ; 141 | TupleMultiple. Tuple ::= "(" Proc "," [Proc] ")" ; 142 | 143 | -- Remainders: 144 | ProcRemainderVar. ProcRemainder ::= "..." ProcVar ; 145 | ProcRemainderEmpty. ProcRemainder ::= "" ; 146 | NameRemainderVar. NameRemainder ::= "..." "@" ProcVar ; 147 | NameRemainderEmpty. NameRemainder ::= "" ; 148 | 149 | -- VarRefKind: 150 | VarRefKindProc. VarRefKind ::= "=" ; 151 | VarRefKindName. VarRefKind ::= "=" "*" ; 152 | 153 | -- Simple Types: 154 | SimpleTypeBool. SimpleType ::= "Bool" ; 155 | SimpleTypeInt. SimpleType ::= "Int" ; 156 | SimpleTypeString. SimpleType ::= "String" ; 157 | SimpleTypeUri. SimpleType ::= "Uri" ; 158 | SimpleTypeByteArray. SimpleType ::= "ByteArray" ; 159 | 160 | 161 | token Var (((letter | '\'') (letter | digit | '_' | '\'')*)|(('_') (letter | digit | '_' | '\'')+)) ; 162 | 163 | -- Comments: 164 | comment "//" ; 165 | comment "/*" "*/" ; 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rholang IntelliJ IDEA language plugin 2 | 3 | ![beta][beta-badge] 4 | 5 | This is the early stage of editor support for [Rholang][rho-github]. :smile: 6 | 7 | For now, it has only support for syntax highlighting. I tried to make parser more forgiving so it can highlight wider range of correct programs. With more context information from compiler it could be much more precise. 8 | 9 | > **Rholang** is a fully featured, general purpose, Turing-complete programming language built from the rho-calculus. It is a behaviorally typed, **r**-eflective, **h**-igher **o**-rder process language and the official smart contracting language of [RChain][rchain-coop]. Its purpose is to concretize fine-grained, programmatic concurrency. [RChain Architecture][arch-rholang] 10 | 11 | Rholang is currently in active development and syntax can slightly change. Current version of plugin follows this version of [Rho grammar][rho-bnf-origin] and available examples. 12 | 13 | I found interesting that many grammar rules have a strong gravity towards `Proc`ess :cyclone: but that should not be strange for π-calculus, _λ-expression_ is not the main _actor_ here. [Mobile process calculi for programming the new blockchain][tuplespaces-to-picalculus] 14 | 15 | Programmers in concurrent languages such as Erlang/Elixir say that one of the hardest problems is to coordinate the names (locations) of processes. It seems that Rholang with [Namespace logic][arch-namespace-logic] looks like a great solution for coordination of resources. 16 | 17 | With all this sweet superpowers, that comes with the Rholang compiler and type checker, it will be a pleasure to write smart contracts. :lollipop: 18 | 19 | ## Configure custom colors on the settings page 20 | 21 | Maybe you want to set color for _Bind parameter_ which has no default value. 22 | 23 | ![Idea settings page](./docs/settings-page.png) 24 | 25 | ## Install 26 | 27 | From [JetBrains Plugins Repository][rho-idea-plugin] searchable inside the editor. 28 | 29 | Or download **rholang-idea.jar** from the [latest release][releases] and install through [File > Settings > Plugins][idea-install-from-disk] menu. 30 | 31 | ## [Contributing](./CONTRIBUTING.md) 32 | 33 | Any feedback, suggestions, bugs, testing, pull-requests, issues are very welcome. :smile: 34 | 35 | ### Development 36 | 37 | - setup [IntelliJ dev-plugin prerequisites][idea-dev-setup] 38 | - generate Java parser from `Rho.bnf` through the file context menu [Generate Parser Code][idea-gen-parser] 39 | - generate Java lexer from `Rho.flex` through the file context menu [Run JFlex Generator][idea-gen-lexer] (choose _out_ folder or any folder outside the project where jflex.jar will be downloaded) 40 | - build the project (choose _IntelliJ SDK_ and language level _8_) 41 | - create new Plugin Run configuration with default setup 42 | - run/debug in a separate editor 43 | - optionally, to keep formatting consistent install plugin for [EditorConfig][editor-config] 44 | 45 | ### Test 46 | 47 | IntelliJ has provided testing framework. This framework simplifies verification. For more details, you can read [IntelliJ Platform SDK DevGuide][idea-test-guide]. 48 | 49 | #### How to use 50 | 51 | Just as using JUnit, there is a 'run' button on the left of the class or test case. You can click this button to run or debug. Also, _right-click_ on the `test` folder has option to _Run/Debug 'All Tests'_. 52 | 53 | ### Deployment 54 | 55 | - generate _jar_ file through the project root context menu [Prepare Plugin Module ... For Deployment][idea-deploy] (in `.idea` folder) 56 | - upload _jar_ to [JetBrains Plugins Repository][rho-idea-plugin] 57 | 58 | ### TODO 59 | 60 | - write more tests and configure CI 61 | - write [Completion Contributor][idea-completion] 62 | - write [Reference Contributor][idea-reference] 63 | - add [plugin actions][idea-plugin-actions] 64 | - connect with the compiler (get semantic info) 65 | - ... 66 | 67 | ## Release Notes 68 | 69 | ### 0.2.0 [@AbnerZheng](https://github.com/AbnerZheng) 70 | - Updated grammar for Rholang Mercury release. 71 | 72 | ### 0.1.0 [@AbnerZheng](https://github.com/AbnerZheng) 73 | - Implemented formatting feature. 74 | - Updated grammar (quick fix before Mercury) [@tgrospic](https://github.com/tgrospic). 75 | 76 | ### 0.0.4 [@AbnerZheng](https://github.com/AbnerZheng) 77 | - Implemented folding feature. 78 | - Added initial tests. 79 | 80 | ### 0.0.3 81 | - Syntax: Contracts as processes (recursive). 82 | - Syntax: Fix arithmetic operators. 83 | - New file icon. 84 | 85 | ### 0.0.2 86 | - Contributing info, plugin name change. 87 | 88 | ### 0.0.1 89 | - Initial release. Syntax highlighting. 90 | 91 | ## License 92 | 93 | [The MIT License (MIT)][license] 94 | 95 | [releases]: https://github.com/tgrospic/rholang-idea/releases 96 | [rchain-coop]: https://www.rchain.coop 97 | [rho-github]: https://github.com/rchain/rchain/tree/master/rholang 98 | [rho-bnf-origin]: https://github.com/rchain/rchain/blob/1f5450e8e54b2bbce7d81206eb8d4fdd6bc96797/rholang/src/main/bnfc/rholang.cf 99 | [rho-idea-plugin]: https://plugins.jetbrains.com/plugin/9833-rholang 100 | [arch-rholang]: http://rchain-architecture.readthedocs.io/en/latest/contracts/contract-design.html#rholang-a-concurrent-language 101 | [arch-namespace-logic]: http://rchain-architecture.readthedocs.io/en/latest/contracts/namespaces.html#namespace-logic 102 | [tuplespaces-to-picalculus]: http://mobile-process-calculi-for-programming-the-new-blockchain.readthedocs.io/en/latest/actors-tuples-and-pi.html#from-tuplespaces-to-calculus 103 | 104 | [idea-dev-setup]: http://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support/prerequisites.html 105 | [idea-gen-parser]: http://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support/grammar_and_parser.html#generate-a-parser 106 | [idea-gen-lexer]: http://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support/lexer_and_parser_definition.html#generate-a-lexer-class 107 | [idea-deploy]: https://www.jetbrains.com/help/idea/preparing-plugins-for-publishing.html 108 | [idea-install-from-disk]: https://www.jetbrains.com/help/idea/installing-a-plugin-from-the-disk.html 109 | [idea-completion]: https://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support/completion_contributor.html 110 | [idea-reference]: https://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support/reference_contributor.html 111 | [idea-plugin-actions]: https://www.jetbrains.org/intellij/sdk/docs/basics/action_system.html 112 | [idea-test-guide]: https://www.jetbrains.org/intellij/sdk/docs/tutorials/writing_tests_for_plugins.html 113 | [editor-config]: http://editorconfig.org 114 | 115 | [beta-badge]: https://cdn.rawgit.com/tgrospic/rholang-idea/master/docs/beta-0.1.0.svg 116 | [license]: https://github.com/tgrospic/rholang-idea/blob/master/LICENSE 117 | -------------------------------------------------------------------------------- /src/coop/rchain/lang/Rho.bnf: -------------------------------------------------------------------------------- 1 | { 2 | parserClass="coop.rchain.lang.RhoParser" 3 | 4 | extends="com.intellij.extapi.psi.ASTWrapperPsiElement" 5 | 6 | psiClassPrefix="Rho" 7 | psiImplClassSuffix="Impl" 8 | psiPackage="coop.rchain.lang.psi" 9 | psiImplPackage="coop.rchain.lang.psi.impl" 10 | 11 | elementTypeHolderClass="coop.rchain.lang.psi.RhoTypes" 12 | elementTypeClass="coop.rchain.lang.psi.RhoElementType" 13 | tokenTypeClass="coop.rchain.lang.psi.RhoTokenType" 14 | 15 | tokens = [ 16 | CONTRACT = "contract" 17 | MATCH = "match" 18 | FOR = "for" 19 | NEW = "new" 20 | SELECT = "select" 21 | IF = "if" 22 | ELSE = "else" 23 | IN = "in" 24 | FALSE = "false" 25 | TRUE = "true" 26 | NIL = "Nil" 27 | 28 | FAT_ARROW = "=>" 29 | THIN_ARROW = "->" 30 | DOT = "." 31 | 32 | BITWISE_AND = "&" 33 | BITWISE_OR = "|" 34 | BITWISE_XOR = "^" 35 | 36 | TRIPLE_DOT = "..." 37 | DOUBLE_DOT = ".." 38 | DOUBLE_COLON = "::" 39 | COLON = ":" 40 | 41 | PLUS = "+" 42 | MINUS = "-" 43 | MULTIPLY = "*" 44 | DIVIDE = "/" 45 | REMAINDER = "%" 46 | 47 | ASSIGN_LEFT_SHIFT = "<<=" 48 | ASSIGN_RIGHT_SHIFT = ">>=" 49 | EQUAL = "==" 50 | ASSIGN = "=" 51 | NOT_EQUAL = "!=" 52 | LESS_THAN_OR_EQUAL = "<=" 53 | LESS_THAN = "<" 54 | GREATER_THAN_OR_EQUAL = ">=" 55 | GREATER_THAN = ">" 56 | 57 | NOT = "!" 58 | BOX = "~" 59 | AT = "@" 60 | SINGLE_QUOTE = "'" 61 | DOLLAR = "$" 62 | 63 | HASH = "#" 64 | OPEN_SQUARE_BRACKET = "[" 65 | CLOSE_SQUARE_BRACKET = "]" 66 | OPEN_PAREN = "(" 67 | CLOSE_PAREN = ")" 68 | OPEN_BRACE = "{" 69 | CLOSE_BRACE = "}" 70 | COMMA = "," 71 | SEMICOLON = ";" 72 | UNDERSCORE = "_" 73 | 74 | 75 | space='regexp:\s+' 76 | line_comment='regexp://.*' 77 | block_comment="regexp:/\*(.|\n)*\*/" 78 | 79 | Integer='regexp:\d+(\.\d*)?' 80 | ID_NAME="regexp:([a-zA-Z'][a-zA-Z_0-9']*)|([_a-zA-Z0-9']+)" 81 | StringLit="regexp:('([^'\\]|\\.)*'|\"([^\"\\]|\\.)*\")" 82 | 83 | // todo-abner url regexp 84 | URI = "regexp:`([^`\\]|\\[`\\])*`" 85 | ] 86 | 87 | // psiImplUtilClass="coop.rchain.psi.impl.RhoPsiImplUtil" 88 | // consumeTokenMethod("Proc.*|Proc")="consumeTokenFast" 89 | 90 | // extends(".*Quantity")=Quantity 91 | } 92 | 93 | RootProc ::= Proc 94 | Proc ::= Proc_ (COMMA Proc_)* 95 | private Proc_ ::= Proc1 Proc__ 96 | private Proc__ ::= ["|" Proc1 Proc__] 97 | 98 | private Proc16 ::= Ground | Collection | ProcVar | "Nil" | SimpleType | ProcBlock 99 | private Proc15 ::= "~" Proc15 | Proc16 100 | private Proc14 ::= Proc15 Proc14_ 101 | private Proc14_ ::= ["/\\" Proc15 Proc14_] 102 | private Proc13 ::= Proc14 Proc13_ 103 | private Proc13_ ::= ["\\/" Proc14 Proc13_ | VarRefKind Var Proc13_] 104 | private Proc12 ::= "*" RhoName | Proc13 105 | private Proc11 ::= Proc12 Proc11_ | OPEN_PAREN Proc4 CLOSE_PAREN Proc11_ 106 | private private Proc11_ ::= [DOT Var ProcParenOption Proc11_] 107 | 108 | private Proc10 ::= NOT Proc10 | "-" Proc10 | Proc11 109 | 110 | private Proc9 ::= Proc10 Proc9_ 111 | private Proc9_ ::= [("*" | "/" | "%%") Proc10 Proc9_] 112 | 113 | private Proc8 ::= Proc9 Proc8_ 114 | private Proc8_ ::= [("+" | "-" | "++" | "--") Proc9 Proc8_] 115 | 116 | private Proc7 ::= Proc8 Proc7_ 117 | private Proc7_ ::= [("<" | "<=" | ">" | ">=" | "matches") Proc8 Proc7_] 118 | 119 | private Proc6 ::= Proc7 Proc6_ 120 | private Proc6_ ::= [("==" | "!=") Proc7 Proc6_] 121 | 122 | private Proc5 ::= Proc6 Proc5_ 123 | private Proc5_ ::= ["and" Proc6 Proc5_] 124 | 125 | private Proc4 ::= Proc5 Proc4_ 126 | private Proc4_ ::= ["or" Proc5 Proc4_] 127 | Proc3 ::= RhoName Send ProcParenOption | Proc4 128 | private Proc2 ::= PContr | PInput | PChoice | PMatch | PBundle | Proc3 129 | private Proc1 ::= PIfElse | PIf | PNew | Proc2 130 | 131 | PContr ::= CONTRACT RhoName OPEN_PAREN RhoName? NameRemainder CLOSE_PAREN ASSIGN ProcBlock 132 | PInput ::= FOR OPEN_PAREN Receipt CLOSE_PAREN ProcBlock 133 | PChoice ::= SELECT OPEN_BRACE Branch? CLOSE_BRACE 134 | PBundle ::= Bundle ProcBlock 135 | PMatch ::= MATCH Proc4 CaseBlock 136 | 137 | CaseBlock ::= OPEN_BRACE [Case] CLOSE_BRACE 138 | 139 | PIfElse ::= IF OPEN_PAREN Proc CLOSE_PAREN Proc2 ELSE Proc1 140 | PIf ::= IF OPEN_PAREN Proc CLOSE_PAREN Proc2 141 | PNew ::= NEW NameDecl? IN Proc1 142 | 143 | 144 | ProcBlock ::= OPEN_BRACE Proc CLOSE_BRACE 145 | ProcBlockOption ::= OPEN_BRACE [Proc] CLOSE_BRACE 146 | ProcParenOption ::= "(" [Proc] ")" 147 | 148 | // Process variables 149 | ProcVar ::= "_" | Var 150 | 151 | Var ::= ID_NAME 152 | 153 | // This is needed for differ from Name and ProcessVar 154 | NameVar ::= Var { 155 | implements = [ "coop.rchain.lang.psi.RhoNamedElement" ] 156 | mixin = "coop.rchain.lang.psi.RhoNamedElementImpl" 157 | } 158 | 159 | // Names 160 | Name_ ::= "_" | NameVar | AT Proc12 { 161 | implements = [ "coop.rchain.lang.psi.RhoNamedElement" ] 162 | mixin = "coop.rchain.lang.psi.RhoNamedElementImpl" 163 | } 164 | RhoName ::= Name_ ("," Name_)* 165 | 166 | // Bundle 167 | Bundle ::= "bundle+" | "bundle-" | "bundle0" | "bundle" 168 | 169 | // Receipt 170 | Receipt ::= ReceiptLinearImpl 171 | 172 | ReceiptLinearImpl ::= [LinearBind] 173 | 174 | private LinearBind_ ::= [RhoName] NameRemainder ("<-"|"<=") RhoName 175 | 176 | LinearBind ::= LinearBind_ (";" LinearBind_)* 177 | 178 | // Types of Send 179 | Send ::= "!" || "!!" 180 | 181 | // select branches 182 | private Branch_ ::= ReceiptLinearImpl "=>" Proc3 183 | Branch ::= Branch_+ 184 | 185 | // Match Cases 186 | Case_ ::= Proc13 "=>" Proc3 187 | Case ::= Case_+ 188 | 189 | // Name Declarations 190 | // Eventually will have IOPairs. 191 | NameDecl ::= NameDecl_ ("," NameDecl_)* 192 | NameDecl_ ::= NameVar OPEN_PAREN URI CLOSE_PAREN | NameVar 193 | 194 | // Booleans: 195 | Bool ::= TRUE | FALSE 196 | 197 | // Ground 198 | Ground ::= Bool | Integer | StringLit | URI 199 | 200 | // Collections: 201 | private CollectList ::= OPEN_SQUARE_BRACKET [Proc] ProcRemainder CLOSE_SQUARE_BRACKET 202 | private CollectTuple ::= Tuple 203 | private CollectSet ::= "Set" "(" [Proc] ")" 204 | private CollectMap ::= "{" [KeyValuePair] "}" 205 | 206 | // important: we use Proc_ here, because if we use Proc, they will all consume COMMA 207 | private KeyValuePair_ ::= Proc COLON Proc_ 208 | KeyValuePair ::= KeyValuePair_ (COMMA KeyValuePair_)* 209 | private Tuple ::= OPEN_PAREN Proc ",)" | OPEN_PAREN Proc COMMA [Proc] CLOSE_PAREN 210 | 211 | 212 | 213 | Collection ::= CollectList | CollectTuple | CollectMap | CollectSet 214 | 215 | 216 | // Remainders: 217 | ProcRemainder ::= (TRIPLE_DOT Var)? 218 | 219 | NameRemainder ::= (TRIPLE_DOT AT Var)? 220 | 221 | 222 | VarRefKind ::= "=" | "=" "*" 223 | 224 | SimpleType ::= "Bool" | "Int" | "String" | "Url" | "ByteArray" 225 | -------------------------------------------------------------------------------- /testData/lexer/token.rho: -------------------------------------------------------------------------------- 1 | // A token contract that implements the ERC20 standard. 2 | // This contract demonstrates the creation of a token, 3 | // the transferring of tokens, the querying of a balance, 4 | // and the printing of the balance query result. 5 | 6 | new token in { 7 | contract token (message_sender, total_supply, return_channel) = { 8 | new allowed_channel, balances_channel, owner_channel in { 9 | allowed_channel!(Map()) | 10 | owner_channel!(message_sender) | 11 | balances_channel!(Map()) | 12 | for (balances <- balances_channel) { 13 | balances_channel!( balances.insert(message_sender, total_supply) ) 14 | } | 15 | new transfer, transfer_from, approve, balance_of, allowance, contract_owner in { 16 | contract transfer(message_sender, to, amount, rtn) = { 17 | for (balances <- balances_channel) { 18 | new x, y in { 19 | x!(balances.getOrElse(message_sender, 0)) | 20 | y!(balances.getOrElse(to, 0)) | 21 | for (balance_of_sender <- x 22 | ; balance_of_receiver <- y) { 23 | // Preconditions to check before the transfer goes through 24 | match [ 25 | balance_of_sender >= amount, 26 | amount > 0, 27 | balance_of_receiver + amount > balance_of_receiver 28 | ] { 29 | [true, true, true] => { 30 | balances_channel!( 31 | (balances 32 | .insert(message_sender, balance_of_sender - amount)) 33 | .insert(to, balance_of_receiver+amount) 34 | ) | 35 | rtn!(true) 36 | } 37 | _ => { 38 | balances_channel!(balances) | 39 | rtn!(false) 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } | 46 | // Same as the transfer contract but allows for the sender to be different from 47 | // the person calling the transfer_from contract 48 | contract transfer_from(message_sender, from, to, amount, rtn) = { 49 | for (balances <- balances_channel 50 | ; allowed <- allowed_channel) { 51 | new x, y, z in { 52 | x!(balances.getOrElse(from, 0)) | 53 | y!(allowed.getOrElse(from, message_sender, 0)) | 54 | z!(balances.getOrElse(to, 0)) | 55 | for ( balance_of_sender <- x 56 | ; sender_allowed <- y 57 | ; balance_of_receiver <- z ) { 58 | match [ 59 | balance_of_sender >= amount, 60 | sender_allowed >= amount, 61 | amount > 0, 62 | balance_of_receiver + amount > balance_of_receiver 63 | ] { 64 | [true, true, true, true] => { 65 | balances_channel!( 66 | (balances 67 | .insert(from, balance_of_sender - amount)) 68 | .insert(to, balance_of_receiver + amount) 69 | ) | 70 | allowed_channel!( 71 | allowed.insert(from, message_sender, sender_allowed - amount) 72 | ) | 73 | rtn!(true) 74 | } 75 | _ => { 76 | balances_channel!(balances) | 77 | allowed_channel!(allowed) | 78 | rtn!(false) 79 | } 80 | } 81 | } 82 | } 83 | } 84 | } | 85 | // This is the way an address can pre-approve (delegate) the transfer of 86 | // a certain amount of tokens to some other address. This allows for 87 | // that other address, through the use of the transfer_from function, 88 | // to send up to that amount of tokens. 89 | contract approve(message_sender, spender, amount, rtn) = { 90 | for (allowed <- allowed_channel) { 91 | allowed_channel!(allowed.insert(message_sender,spender,amount)) | 92 | rtn!(true) 93 | } 94 | } | 95 | contract balance_of(owner, rtn) = { 96 | for (balances <- balances_channel) { 97 | rtn!(balances.getOrElse(owner, 0)) | 98 | balances_channel!(balances) 99 | } 100 | } | 101 | contract allowance(owner, spender, rtn) = { 102 | for (allowed <- allowed_channel) { 103 | allowed_channel!(allowed) | 104 | rtn!(allowed.getOrElse(owner,spender,0)) 105 | } 106 | } | 107 | contract contract_owner(rtn) = { 108 | for (owner <- owner_channel) { 109 | owner_channel!(owner) | 110 | rtn!(owner) 111 | } 112 | } | 113 | return_channel!( 114 | Map().insertMany("transfer", transfer, "transfer_from", transfer_from, 115 | "approve", approve, "balance_of", balance_of, "allowance", allowance, 116 | "contract_owner", contract_owner)) 117 | // TODO: Eventually just insert with compiler 118 | } 119 | } 120 | } | 121 | new rtn, me, they in { 122 | token!(me, 100, rtn) | 123 | for (token_contract <- rtn) { 124 | new unused_rtn, balance_of_rtn in { 125 | @token_contract.get("transfer")!(me, they, 50, unused_rtn) | 126 | @token_contract.get("balance_of")!(they, balance_of_rtn) | 127 | for (they_balance <- balance_of_rtn) { 128 | they_balance.display("\n") 129 | } 130 | } 131 | } 132 | } | 133 | new rtn2, me2, they2 in { 134 | token!(me2, 1000, rtn2) | 135 | for (token_contract2 <- rtn2) { 136 | new unused_rtn2, balance_of_rtn2 in { 137 | @token_contract2.get("transfer")!(me2, they2, 500, unused_rtn2) | 138 | @token_contract2.get("balance_of")!(they2, balance_of_rtn2) | 139 | for (they_balance2 <- balance_of_rtn2) { 140 | they_balance2.display("\n") 141 | } 142 | } 143 | } 144 | } 145 | // Once we have a registry, we can do registry_channel!(token) to save the contract there 146 | } 147 | -------------------------------------------------------------------------------- /testData/parser/token.txt: -------------------------------------------------------------------------------- 1 | Rholang File 2 | RhoPNewImpl(P_NEW) 3 | PsiElement(new)('new') 4 | PsiWhiteSpace(' ') 5 | RhoNameDeclImpl(NAME_DECL) 6 | RhoVarImpl(VAR) 7 | PsiElement(ID_NAME)('testResult') 8 | PsiElement(comma)(',') 9 | PsiWhiteSpace(' ') 10 | RhoVarImpl(VAR) 11 | PsiElement(ID_NAME)('philosopher1') 12 | PsiElement(comma)(',') 13 | PsiWhiteSpace(' ') 14 | RhoVarImpl(VAR) 15 | PsiElement(ID_NAME)('philosopher2') 16 | PsiWhiteSpace(' ') 17 | PsiElement(in)('in') 18 | PsiWhiteSpace(' ') 19 | RhoProc3Impl(PROC_3) 20 | RhoProcBlockImpl(PROC_BLOCK) 21 | PsiElement({)('{') 22 | PsiWhiteSpace('\n ') 23 | RhoPNewImpl(P_NEW) 24 | PsiElement(new)('new') 25 | PsiWhiteSpace(' ') 26 | RhoNameDeclImpl(NAME_DECL) 27 | RhoVarImpl(VAR) 28 | PsiElement(ID_NAME)('north') 29 | PsiElement(comma)(',') 30 | PsiWhiteSpace(' ') 31 | RhoVarImpl(VAR) 32 | PsiElement(ID_NAME)('south') 33 | PsiElement(comma)(',') 34 | PsiWhiteSpace(' ') 35 | RhoVarImpl(VAR) 36 | PsiElement(ID_NAME)('knife') 37 | PsiElement(comma)(',') 38 | PsiWhiteSpace(' ') 39 | RhoVarImpl(VAR) 40 | PsiElement(ID_NAME)('spoon') 41 | PsiWhiteSpace(' ') 42 | PsiElement(in)('in') 43 | PsiWhiteSpace(' ') 44 | RhoProc3Impl(PROC_3) 45 | RhoProcBlockImpl(PROC_BLOCK) 46 | PsiElement({)('{') 47 | PsiWhiteSpace('\n ') 48 | RhoProc3Impl(PROC_3) 49 | RhoRhoNameImpl(RHO_NAME) 50 | RhoName_Impl(NAME_) 51 | RhoVarImpl(VAR) 52 | PsiElement(ID_NAME)('north') 53 | RhoSendImpl(SEND) 54 | PsiElement(!)('!') 55 | RhoProcParenOptionImpl(PROC_PAREN_OPTION) 56 | PsiElement(()('(') 57 | RhoProc3Impl(PROC_3) 58 | PsiElement(*)('*') 59 | RhoRhoNameImpl(RHO_NAME) 60 | RhoName_Impl(NAME_) 61 | RhoVarImpl(VAR) 62 | PsiElement(ID_NAME)('knife') 63 | PsiElement())(')') 64 | PsiWhiteSpace(' ') 65 | PsiElement(|)('|') 66 | PsiWhiteSpace('\n ') 67 | RhoProc3Impl(PROC_3) 68 | RhoRhoNameImpl(RHO_NAME) 69 | RhoName_Impl(NAME_) 70 | RhoVarImpl(VAR) 71 | PsiElement(ID_NAME)('south') 72 | RhoSendImpl(SEND) 73 | PsiElement(!)('!') 74 | RhoProcParenOptionImpl(PROC_PAREN_OPTION) 75 | PsiElement(()('(') 76 | RhoProc3Impl(PROC_3) 77 | PsiElement(*)('*') 78 | RhoRhoNameImpl(RHO_NAME) 79 | RhoName_Impl(NAME_) 80 | RhoVarImpl(VAR) 81 | PsiElement(ID_NAME)('spoon') 82 | PsiElement())(')') 83 | PsiWhiteSpace(' ') 84 | PsiElement(|)('|') 85 | PsiWhiteSpace('\n ') 86 | RhoPInputImpl(P_INPUT) 87 | PsiElement(for)('for') 88 | PsiWhiteSpace(' ') 89 | PsiElement(()('(') 90 | RhoReceiptImpl(RECEIPT) 91 | RhoReceiptLinearImplImpl(RECEIPT_LINEAR_IMPL) 92 | RhoLinearBindImpl(LINEAR_BIND) 93 | RhoRhoNameImpl(RHO_NAME) 94 | RhoName_Impl(NAME_) 95 | PsiElement(@)('@') 96 | RhoProcVarImpl(PROC_VAR) 97 | RhoVarImpl(VAR) 98 | PsiElement(ID_NAME)('knf') 99 | PsiWhiteSpace(' ') 100 | RhoNameRemainderImpl(NAME_REMAINDER) 101 | 102 | PsiElement(<)('<') 103 | PsiElement(-)('-') 104 | PsiWhiteSpace(' ') 105 | RhoRhoNameImpl(RHO_NAME) 106 | RhoName_Impl(NAME_) 107 | RhoVarImpl(VAR) 108 | PsiElement(ID_NAME)('north') 109 | PsiElement(;)(';') 110 | PsiWhiteSpace(' ') 111 | RhoRhoNameImpl(RHO_NAME) 112 | RhoName_Impl(NAME_) 113 | PsiElement(@)('@') 114 | RhoProcVarImpl(PROC_VAR) 115 | RhoVarImpl(VAR) 116 | PsiElement(ID_NAME)('spn') 117 | PsiWhiteSpace(' ') 118 | RhoNameRemainderImpl(NAME_REMAINDER) 119 | 120 | PsiElement(<)('<') 121 | PsiElement(-)('-') 122 | PsiWhiteSpace(' ') 123 | RhoRhoNameImpl(RHO_NAME) 124 | RhoName_Impl(NAME_) 125 | RhoVarImpl(VAR) 126 | PsiElement(ID_NAME)('south') 127 | PsiElement())(')') 128 | PsiWhiteSpace(' ') 129 | PsiElement({)('{') 130 | PsiWhiteSpace('\n ') 131 | RhoProc3Impl(PROC_3) 132 | RhoRhoNameImpl(RHO_NAME) 133 | RhoName_Impl(NAME_) 134 | RhoVarImpl(VAR) 135 | PsiElement(ID_NAME)('philosopher1') 136 | RhoSendImpl(SEND) 137 | PsiElement(!)('!') 138 | RhoProcParenOptionImpl(PROC_PAREN_OPTION) 139 | PsiElement(()('(') 140 | RhoProc3Impl(PROC_3) 141 | RhoGroundImpl(GROUND) 142 | RhoBoolImpl(BOOL) 143 | PsiElement(true)('true') 144 | PsiElement())(')') 145 | PsiWhiteSpace(' ') 146 | PsiElement(|)('|') 147 | PsiWhiteSpace('\n ') 148 | RhoProc3Impl(PROC_3) 149 | RhoRhoNameImpl(RHO_NAME) 150 | RhoName_Impl(NAME_) 151 | RhoVarImpl(VAR) 152 | PsiElement(ID_NAME)('north') 153 | RhoSendImpl(SEND) 154 | PsiElement(!)('!') 155 | RhoProcParenOptionImpl(PROC_PAREN_OPTION) 156 | PsiElement(()('(') 157 | RhoProc3Impl(PROC_3) 158 | RhoProcVarImpl(PROC_VAR) 159 | RhoVarImpl(VAR) 160 | PsiElement(ID_NAME)('knf') 161 | PsiElement())(')') 162 | PsiWhiteSpace(' ') 163 | PsiElement(|)('|') 164 | PsiWhiteSpace('\n ') 165 | RhoProc3Impl(PROC_3) 166 | RhoRhoNameImpl(RHO_NAME) 167 | RhoName_Impl(NAME_) 168 | RhoVarImpl(VAR) 169 | PsiElement(ID_NAME)('south') 170 | RhoSendImpl(SEND) 171 | PsiElement(!)('!') 172 | RhoProcParenOptionImpl(PROC_PAREN_OPTION) 173 | PsiElement(()('(') 174 | RhoProc3Impl(PROC_3) 175 | RhoProcVarImpl(PROC_VAR) 176 | RhoVarImpl(VAR) 177 | PsiElement(ID_NAME)('spn') 178 | PsiElement())(')') 179 | PsiWhiteSpace('\n ') 180 | PsiElement(})('}') 181 | PsiWhiteSpace(' ') 182 | PsiElement(|)('|') 183 | PsiWhiteSpace('\n ') 184 | RhoPInputImpl(P_INPUT) 185 | PsiElement(for)('for') 186 | PsiWhiteSpace(' ') 187 | PsiElement(()('(') 188 | RhoReceiptImpl(RECEIPT) 189 | RhoReceiptLinearImplImpl(RECEIPT_LINEAR_IMPL) 190 | RhoLinearBindImpl(LINEAR_BIND) 191 | RhoRhoNameImpl(RHO_NAME) 192 | RhoName_Impl(NAME_) 193 | PsiElement(@)('@') 194 | RhoProcVarImpl(PROC_VAR) 195 | RhoVarImpl(VAR) 196 | PsiElement(ID_NAME)('spn') 197 | PsiWhiteSpace(' ') 198 | RhoNameRemainderImpl(NAME_REMAINDER) 199 | 200 | PsiElement(<)('<') 201 | PsiElement(-)('-') 202 | PsiWhiteSpace(' ') 203 | RhoRhoNameImpl(RHO_NAME) 204 | RhoName_Impl(NAME_) 205 | RhoVarImpl(VAR) 206 | PsiElement(ID_NAME)('south') 207 | PsiElement(;)(';') 208 | PsiWhiteSpace(' ') 209 | RhoRhoNameImpl(RHO_NAME) 210 | RhoName_Impl(NAME_) 211 | PsiElement(@)('@') 212 | RhoProcVarImpl(PROC_VAR) 213 | RhoVarImpl(VAR) 214 | PsiElement(ID_NAME)('knf') 215 | PsiWhiteSpace(' ') 216 | RhoNameRemainderImpl(NAME_REMAINDER) 217 | 218 | PsiElement(<)('<') 219 | PsiElement(-)('-') 220 | PsiWhiteSpace(' ') 221 | RhoRhoNameImpl(RHO_NAME) 222 | RhoName_Impl(NAME_) 223 | RhoVarImpl(VAR) 224 | PsiElement(ID_NAME)('north') 225 | PsiElement())(')') 226 | PsiWhiteSpace(' ') 227 | PsiElement({)('{') 228 | PsiWhiteSpace('\n ') 229 | RhoProc3Impl(PROC_3) 230 | RhoRhoNameImpl(RHO_NAME) 231 | RhoName_Impl(NAME_) 232 | RhoVarImpl(VAR) 233 | PsiElement(ID_NAME)('philosopher2') 234 | RhoSendImpl(SEND) 235 | PsiElement(!)('!') 236 | RhoProcParenOptionImpl(PROC_PAREN_OPTION) 237 | PsiElement(()('(') 238 | RhoProc3Impl(PROC_3) 239 | RhoGroundImpl(GROUND) 240 | RhoBoolImpl(BOOL) 241 | PsiElement(true)('true') 242 | PsiElement())(')') 243 | PsiWhiteSpace(' ') 244 | PsiElement(|)('|') 245 | PsiWhiteSpace('\n ') 246 | RhoProc3Impl(PROC_3) 247 | RhoRhoNameImpl(RHO_NAME) 248 | RhoName_Impl(NAME_) 249 | RhoVarImpl(VAR) 250 | PsiElement(ID_NAME)('north') 251 | RhoSendImpl(SEND) 252 | PsiElement(!)('!') 253 | RhoProcParenOptionImpl(PROC_PAREN_OPTION) 254 | PsiElement(()('(') 255 | RhoProc3Impl(PROC_3) 256 | RhoProcVarImpl(PROC_VAR) 257 | RhoVarImpl(VAR) 258 | PsiElement(ID_NAME)('knf') 259 | PsiElement())(')') 260 | PsiWhiteSpace(' ') 261 | PsiElement(|)('|') 262 | PsiWhiteSpace('\n ') 263 | RhoProc3Impl(PROC_3) 264 | RhoRhoNameImpl(RHO_NAME) 265 | RhoName_Impl(NAME_) 266 | RhoVarImpl(VAR) 267 | PsiElement(ID_NAME)('south') 268 | RhoSendImpl(SEND) 269 | PsiElement(!)('!') 270 | RhoProcParenOptionImpl(PROC_PAREN_OPTION) 271 | PsiElement(()('(') 272 | RhoProc3Impl(PROC_3) 273 | RhoProcVarImpl(PROC_VAR) 274 | RhoVarImpl(VAR) 275 | PsiElement(ID_NAME)('spn') 276 | PsiElement())(')') 277 | PsiWhiteSpace('\n ') 278 | PsiElement(})('}') 279 | PsiWhiteSpace('\n ') 280 | PsiElement(})('}') 281 | PsiWhiteSpace(' ') 282 | PsiElement(|)('|') 283 | PsiWhiteSpace('\n ') 284 | RhoPInputImpl(P_INPUT) 285 | PsiElement(for)('for') 286 | PsiElement(()('(') 287 | RhoReceiptImpl(RECEIPT) 288 | RhoReceiptLinearImplImpl(RECEIPT_LINEAR_IMPL) 289 | RhoLinearBindImpl(LINEAR_BIND) 290 | RhoRhoNameImpl(RHO_NAME) 291 | RhoName_Impl(NAME_) 292 | PsiElement(_)('_') 293 | PsiWhiteSpace(' ') 294 | RhoNameRemainderImpl(NAME_REMAINDER) 295 | 296 | PsiElement(<)('<') 297 | PsiElement(-)('-') 298 | PsiWhiteSpace(' ') 299 | RhoRhoNameImpl(RHO_NAME) 300 | RhoName_Impl(NAME_) 301 | RhoVarImpl(VAR) 302 | PsiElement(ID_NAME)('philosopher1') 303 | PsiElement(;)(';') 304 | PsiWhiteSpace(' ') 305 | RhoRhoNameImpl(RHO_NAME) 306 | RhoName_Impl(NAME_) 307 | PsiElement(_)('_') 308 | PsiWhiteSpace(' ') 309 | RhoNameRemainderImpl(NAME_REMAINDER) 310 | 311 | PsiElement(<)('<') 312 | PsiElement(-)('-') 313 | PsiWhiteSpace(' ') 314 | RhoRhoNameImpl(RHO_NAME) 315 | RhoName_Impl(NAME_) 316 | RhoVarImpl(VAR) 317 | PsiElement(ID_NAME)('philosopher2') 318 | PsiElement())(')') 319 | PsiWhiteSpace(' ') 320 | PsiElement({)('{') 321 | PsiWhiteSpace('\n ') 322 | RhoProc3Impl(PROC_3) 323 | RhoRhoNameImpl(RHO_NAME) 324 | RhoName_Impl(NAME_) 325 | RhoVarImpl(VAR) 326 | PsiElement(ID_NAME)('testResult') 327 | RhoSendImpl(SEND) 328 | PsiElement(!)('!') 329 | RhoProcParenOptionImpl(PROC_PAREN_OPTION) 330 | PsiElement(()('(') 331 | RhoProc3Impl(PROC_3) 332 | RhoGroundImpl(GROUND) 333 | RhoBoolImpl(BOOL) 334 | PsiElement(true)('true') 335 | PsiElement())(')') 336 | PsiWhiteSpace('\n ') 337 | PsiElement(})('}') 338 | PsiWhiteSpace('\n') 339 | PsiElement(})('}') 340 | -------------------------------------------------------------------------------- /testData/lexer/token.txt: -------------------------------------------------------------------------------- 1 | line_comment ('// A token contract that implements the ERC20 standard.') 2 | WHITE_SPACE ('\n') 3 | line_comment ('// This contract demonstrates the creation of a token,') 4 | WHITE_SPACE ('\n') 5 | line_comment ('// the transferring of tokens, the querying of a balance,') 6 | WHITE_SPACE ('\n') 7 | line_comment ('// and the printing of the balance query result.') 8 | WHITE_SPACE ('\n\n') 9 | new ('new') 10 | WHITE_SPACE (' ') 11 | ID_NAME ('token') 12 | WHITE_SPACE (' ') 13 | in ('in') 14 | WHITE_SPACE (' ') 15 | { ('{') 16 | WHITE_SPACE ('\n ') 17 | contract ('contract') 18 | WHITE_SPACE (' ') 19 | ID_NAME ('token') 20 | WHITE_SPACE (' ') 21 | ( ('(') 22 | ID_NAME ('message_sender') 23 | comma (',') 24 | WHITE_SPACE (' ') 25 | ID_NAME ('total_supply') 26 | comma (',') 27 | WHITE_SPACE (' ') 28 | ID_NAME ('return_channel') 29 | ) (')') 30 | WHITE_SPACE (' ') 31 | = ('=') 32 | WHITE_SPACE (' ') 33 | { ('{') 34 | WHITE_SPACE ('\n ') 35 | new ('new') 36 | WHITE_SPACE (' ') 37 | ID_NAME ('allowed_channel') 38 | comma (',') 39 | WHITE_SPACE (' ') 40 | ID_NAME ('balances_channel') 41 | comma (',') 42 | WHITE_SPACE (' ') 43 | ID_NAME ('owner_channel') 44 | WHITE_SPACE (' ') 45 | in ('in') 46 | WHITE_SPACE (' ') 47 | { ('{') 48 | WHITE_SPACE ('\n ') 49 | ID_NAME ('allowed_channel') 50 | ! ('!') 51 | ( ('(') 52 | ID_NAME ('Map') 53 | ( ('(') 54 | ) (')') 55 | ) (')') 56 | WHITE_SPACE (' ') 57 | | ('|') 58 | WHITE_SPACE ('\n ') 59 | ID_NAME ('owner_channel') 60 | ! ('!') 61 | ( ('(') 62 | ID_NAME ('message_sender') 63 | ) (')') 64 | WHITE_SPACE (' ') 65 | | ('|') 66 | WHITE_SPACE ('\n ') 67 | ID_NAME ('balances_channel') 68 | ! ('!') 69 | ( ('(') 70 | ID_NAME ('Map') 71 | ( ('(') 72 | ) (')') 73 | ) (')') 74 | WHITE_SPACE (' ') 75 | | ('|') 76 | WHITE_SPACE ('\n ') 77 | for ('for') 78 | WHITE_SPACE (' ') 79 | ( ('(') 80 | ID_NAME ('balances') 81 | WHITE_SPACE (' ') 82 | < ('<') 83 | - ('-') 84 | WHITE_SPACE (' ') 85 | ID_NAME ('balances_channel') 86 | ) (')') 87 | WHITE_SPACE (' ') 88 | { ('{') 89 | WHITE_SPACE ('\n ') 90 | ID_NAME ('balances_channel') 91 | ! ('!') 92 | ( ('(') 93 | WHITE_SPACE (' ') 94 | ID_NAME ('balances') 95 | . ('.') 96 | ID_NAME ('insert') 97 | ( ('(') 98 | ID_NAME ('message_sender') 99 | comma (',') 100 | WHITE_SPACE (' ') 101 | ID_NAME ('total_supply') 102 | ) (')') 103 | WHITE_SPACE (' ') 104 | ) (')') 105 | WHITE_SPACE ('\n ') 106 | } ('}') 107 | WHITE_SPACE (' ') 108 | | ('|') 109 | WHITE_SPACE ('\n ') 110 | new ('new') 111 | WHITE_SPACE (' ') 112 | ID_NAME ('transfer') 113 | comma (',') 114 | WHITE_SPACE (' ') 115 | ID_NAME ('transfer_from') 116 | comma (',') 117 | WHITE_SPACE (' ') 118 | ID_NAME ('approve') 119 | comma (',') 120 | WHITE_SPACE (' ') 121 | ID_NAME ('balance_of') 122 | comma (',') 123 | WHITE_SPACE (' ') 124 | ID_NAME ('allowance') 125 | comma (',') 126 | WHITE_SPACE (' ') 127 | ID_NAME ('contract_owner') 128 | WHITE_SPACE (' ') 129 | in ('in') 130 | WHITE_SPACE (' ') 131 | { ('{') 132 | WHITE_SPACE ('\n ') 133 | contract ('contract') 134 | WHITE_SPACE (' ') 135 | ID_NAME ('transfer') 136 | ( ('(') 137 | ID_NAME ('message_sender') 138 | comma (',') 139 | WHITE_SPACE (' ') 140 | ID_NAME ('to') 141 | comma (',') 142 | WHITE_SPACE (' ') 143 | ID_NAME ('amount') 144 | comma (',') 145 | WHITE_SPACE (' ') 146 | ID_NAME ('rtn') 147 | ) (')') 148 | WHITE_SPACE (' ') 149 | = ('=') 150 | WHITE_SPACE (' ') 151 | { ('{') 152 | WHITE_SPACE ('\n ') 153 | for ('for') 154 | WHITE_SPACE (' ') 155 | ( ('(') 156 | ID_NAME ('balances') 157 | WHITE_SPACE (' ') 158 | < ('<') 159 | - ('-') 160 | WHITE_SPACE (' ') 161 | ID_NAME ('balances_channel') 162 | ) (')') 163 | WHITE_SPACE (' ') 164 | { ('{') 165 | WHITE_SPACE ('\n ') 166 | new ('new') 167 | WHITE_SPACE (' ') 168 | ID_NAME ('x') 169 | comma (',') 170 | WHITE_SPACE (' ') 171 | ID_NAME ('y') 172 | WHITE_SPACE (' ') 173 | in ('in') 174 | WHITE_SPACE (' ') 175 | { ('{') 176 | WHITE_SPACE ('\n ') 177 | ID_NAME ('x') 178 | ! ('!') 179 | ( ('(') 180 | ID_NAME ('balances') 181 | . ('.') 182 | ID_NAME ('getOrElse') 183 | ( ('(') 184 | ID_NAME ('message_sender') 185 | comma (',') 186 | WHITE_SPACE (' ') 187 | Integer ('0') 188 | ) (')') 189 | ) (')') 190 | WHITE_SPACE (' ') 191 | | ('|') 192 | WHITE_SPACE ('\n ') 193 | ID_NAME ('y') 194 | ! ('!') 195 | ( ('(') 196 | ID_NAME ('balances') 197 | . ('.') 198 | ID_NAME ('getOrElse') 199 | ( ('(') 200 | ID_NAME ('to') 201 | comma (',') 202 | WHITE_SPACE (' ') 203 | Integer ('0') 204 | ) (')') 205 | ) (')') 206 | WHITE_SPACE (' ') 207 | | ('|') 208 | WHITE_SPACE ('\n ') 209 | for ('for') 210 | WHITE_SPACE (' ') 211 | ( ('(') 212 | ID_NAME ('balance_of_sender') 213 | WHITE_SPACE (' ') 214 | < ('<') 215 | - ('-') 216 | WHITE_SPACE (' ') 217 | ID_NAME ('x') 218 | WHITE_SPACE ('\n ') 219 | ; (';') 220 | WHITE_SPACE (' ') 221 | ID_NAME ('balance_of_receiver') 222 | WHITE_SPACE (' ') 223 | < ('<') 224 | - ('-') 225 | WHITE_SPACE (' ') 226 | ID_NAME ('y') 227 | ) (')') 228 | WHITE_SPACE (' ') 229 | { ('{') 230 | WHITE_SPACE ('\n ') 231 | line_comment ('// Preconditions to check before the transfer goes through') 232 | WHITE_SPACE ('\n ') 233 | match ('match') 234 | WHITE_SPACE (' ') 235 | [ ('[') 236 | WHITE_SPACE ('\n ') 237 | ID_NAME ('balance_of_sender') 238 | WHITE_SPACE (' ') 239 | >= ('>=') 240 | WHITE_SPACE (' ') 241 | ID_NAME ('amount') 242 | comma (',') 243 | WHITE_SPACE ('\n ') 244 | ID_NAME ('amount') 245 | WHITE_SPACE (' ') 246 | > ('>') 247 | WHITE_SPACE (' ') 248 | Integer ('0') 249 | comma (',') 250 | WHITE_SPACE ('\n ') 251 | ID_NAME ('balance_of_receiver') 252 | WHITE_SPACE (' ') 253 | + ('+') 254 | WHITE_SPACE (' ') 255 | ID_NAME ('amount') 256 | WHITE_SPACE (' ') 257 | > ('>') 258 | WHITE_SPACE (' ') 259 | ID_NAME ('balance_of_receiver') 260 | WHITE_SPACE ('\n ') 261 | ] (']') 262 | WHITE_SPACE (' ') 263 | { ('{') 264 | WHITE_SPACE ('\n ') 265 | [ ('[') 266 | true ('true') 267 | comma (',') 268 | WHITE_SPACE (' ') 269 | true ('true') 270 | comma (',') 271 | WHITE_SPACE (' ') 272 | true ('true') 273 | ] (']') 274 | WHITE_SPACE (' ') 275 | => ('=>') 276 | WHITE_SPACE (' ') 277 | { ('{') 278 | WHITE_SPACE ('\n ') 279 | ID_NAME ('balances_channel') 280 | ! ('!') 281 | ( ('(') 282 | WHITE_SPACE ('\n ') 283 | ( ('(') 284 | ID_NAME ('balances') 285 | WHITE_SPACE ('\n ') 286 | . ('.') 287 | ID_NAME ('insert') 288 | ( ('(') 289 | ID_NAME ('message_sender') 290 | comma (',') 291 | WHITE_SPACE (' ') 292 | ID_NAME ('balance_of_sender') 293 | WHITE_SPACE (' ') 294 | - ('-') 295 | WHITE_SPACE (' ') 296 | ID_NAME ('amount') 297 | ) (')') 298 | ) (')') 299 | WHITE_SPACE ('\n ') 300 | . ('.') 301 | ID_NAME ('insert') 302 | ( ('(') 303 | ID_NAME ('to') 304 | comma (',') 305 | WHITE_SPACE (' ') 306 | ID_NAME ('balance_of_receiver') 307 | + ('+') 308 | ID_NAME ('amount') 309 | ) (')') 310 | WHITE_SPACE ('\n ') 311 | ) (')') 312 | WHITE_SPACE (' ') 313 | | ('|') 314 | WHITE_SPACE ('\n ') 315 | ID_NAME ('rtn') 316 | ! ('!') 317 | ( ('(') 318 | true ('true') 319 | ) (')') 320 | WHITE_SPACE ('\n ') 321 | } ('}') 322 | WHITE_SPACE ('\n ') 323 | _ ('_') 324 | WHITE_SPACE (' ') 325 | => ('=>') 326 | WHITE_SPACE (' ') 327 | { ('{') 328 | WHITE_SPACE ('\n ') 329 | ID_NAME ('balances_channel') 330 | ! ('!') 331 | ( ('(') 332 | ID_NAME ('balances') 333 | ) (')') 334 | WHITE_SPACE (' ') 335 | | ('|') 336 | WHITE_SPACE ('\n ') 337 | ID_NAME ('rtn') 338 | ! ('!') 339 | ( ('(') 340 | false ('false') 341 | ) (')') 342 | WHITE_SPACE ('\n ') 343 | } ('}') 344 | WHITE_SPACE ('\n ') 345 | } ('}') 346 | WHITE_SPACE ('\n ') 347 | } ('}') 348 | WHITE_SPACE ('\n ') 349 | } ('}') 350 | WHITE_SPACE ('\n ') 351 | } ('}') 352 | WHITE_SPACE ('\n ') 353 | } ('}') 354 | WHITE_SPACE (' ') 355 | | ('|') 356 | WHITE_SPACE ('\n ') 357 | line_comment ('// Same as the transfer contract but allows for the sender to be different from') 358 | WHITE_SPACE ('\n ') 359 | line_comment ('// the person calling the transfer_from contract') 360 | WHITE_SPACE ('\n ') 361 | contract ('contract') 362 | WHITE_SPACE (' ') 363 | ID_NAME ('transfer_from') 364 | ( ('(') 365 | ID_NAME ('message_sender') 366 | comma (',') 367 | WHITE_SPACE (' ') 368 | ID_NAME ('from') 369 | comma (',') 370 | WHITE_SPACE (' ') 371 | ID_NAME ('to') 372 | comma (',') 373 | WHITE_SPACE (' ') 374 | ID_NAME ('amount') 375 | comma (',') 376 | WHITE_SPACE (' ') 377 | ID_NAME ('rtn') 378 | ) (')') 379 | WHITE_SPACE (' ') 380 | = ('=') 381 | WHITE_SPACE (' ') 382 | { ('{') 383 | WHITE_SPACE ('\n ') 384 | for ('for') 385 | WHITE_SPACE (' ') 386 | ( ('(') 387 | ID_NAME ('balances') 388 | WHITE_SPACE (' ') 389 | < ('<') 390 | - ('-') 391 | WHITE_SPACE (' ') 392 | ID_NAME ('balances_channel') 393 | WHITE_SPACE ('\n ') 394 | ; (';') 395 | WHITE_SPACE (' ') 396 | ID_NAME ('allowed') 397 | WHITE_SPACE (' ') 398 | < ('<') 399 | - ('-') 400 | WHITE_SPACE (' ') 401 | ID_NAME ('allowed_channel') 402 | ) (')') 403 | WHITE_SPACE (' ') 404 | { ('{') 405 | WHITE_SPACE ('\n ') 406 | new ('new') 407 | WHITE_SPACE (' ') 408 | ID_NAME ('x') 409 | comma (',') 410 | WHITE_SPACE (' ') 411 | ID_NAME ('y') 412 | comma (',') 413 | WHITE_SPACE (' ') 414 | ID_NAME ('z') 415 | WHITE_SPACE (' ') 416 | in ('in') 417 | WHITE_SPACE (' ') 418 | { ('{') 419 | WHITE_SPACE ('\n ') 420 | ID_NAME ('x') 421 | ! ('!') 422 | ( ('(') 423 | ID_NAME ('balances') 424 | . ('.') 425 | ID_NAME ('getOrElse') 426 | ( ('(') 427 | ID_NAME ('from') 428 | comma (',') 429 | WHITE_SPACE (' ') 430 | Integer ('0') 431 | ) (')') 432 | ) (')') 433 | WHITE_SPACE (' ') 434 | | ('|') 435 | WHITE_SPACE ('\n ') 436 | ID_NAME ('y') 437 | ! ('!') 438 | ( ('(') 439 | ID_NAME ('allowed') 440 | . ('.') 441 | ID_NAME ('getOrElse') 442 | ( ('(') 443 | ID_NAME ('from') 444 | comma (',') 445 | WHITE_SPACE (' ') 446 | ID_NAME ('message_sender') 447 | comma (',') 448 | WHITE_SPACE (' ') 449 | Integer ('0') 450 | ) (')') 451 | ) (')') 452 | WHITE_SPACE (' ') 453 | | ('|') 454 | WHITE_SPACE ('\n ') 455 | ID_NAME ('z') 456 | ! ('!') 457 | ( ('(') 458 | ID_NAME ('balances') 459 | . ('.') 460 | ID_NAME ('getOrElse') 461 | ( ('(') 462 | ID_NAME ('to') 463 | comma (',') 464 | WHITE_SPACE (' ') 465 | Integer ('0') 466 | ) (')') 467 | ) (')') 468 | WHITE_SPACE (' ') 469 | | ('|') 470 | WHITE_SPACE ('\n ') 471 | for ('for') 472 | WHITE_SPACE (' ') 473 | ( ('(') 474 | WHITE_SPACE (' ') 475 | ID_NAME ('balance_of_sender') 476 | WHITE_SPACE (' ') 477 | < ('<') 478 | - ('-') 479 | WHITE_SPACE (' ') 480 | ID_NAME ('x') 481 | WHITE_SPACE ('\n ') 482 | ; (';') 483 | WHITE_SPACE (' ') 484 | ID_NAME ('sender_allowed') 485 | WHITE_SPACE (' ') 486 | < ('<') 487 | - ('-') 488 | WHITE_SPACE (' ') 489 | ID_NAME ('y') 490 | WHITE_SPACE ('\n ') 491 | ; (';') 492 | WHITE_SPACE (' ') 493 | ID_NAME ('balance_of_receiver') 494 | WHITE_SPACE (' ') 495 | < ('<') 496 | - ('-') 497 | WHITE_SPACE (' ') 498 | ID_NAME ('z') 499 | WHITE_SPACE (' ') 500 | ) (')') 501 | WHITE_SPACE (' ') 502 | { ('{') 503 | WHITE_SPACE ('\n ') 504 | match ('match') 505 | WHITE_SPACE (' ') 506 | [ ('[') 507 | WHITE_SPACE ('\n ') 508 | ID_NAME ('balance_of_sender') 509 | WHITE_SPACE (' ') 510 | >= ('>=') 511 | WHITE_SPACE (' ') 512 | ID_NAME ('amount') 513 | comma (',') 514 | WHITE_SPACE ('\n ') 515 | ID_NAME ('sender_allowed') 516 | WHITE_SPACE (' ') 517 | >= ('>=') 518 | WHITE_SPACE (' ') 519 | ID_NAME ('amount') 520 | comma (',') 521 | WHITE_SPACE ('\n ') 522 | ID_NAME ('amount') 523 | WHITE_SPACE (' ') 524 | > ('>') 525 | WHITE_SPACE (' ') 526 | Integer ('0') 527 | comma (',') 528 | WHITE_SPACE ('\n ') 529 | ID_NAME ('balance_of_receiver') 530 | WHITE_SPACE (' ') 531 | + ('+') 532 | WHITE_SPACE (' ') 533 | ID_NAME ('amount') 534 | WHITE_SPACE (' ') 535 | > ('>') 536 | WHITE_SPACE (' ') 537 | ID_NAME ('balance_of_receiver') 538 | WHITE_SPACE ('\n ') 539 | ] (']') 540 | WHITE_SPACE (' ') 541 | { ('{') 542 | WHITE_SPACE ('\n ') 543 | [ ('[') 544 | true ('true') 545 | comma (',') 546 | WHITE_SPACE (' ') 547 | true ('true') 548 | comma (',') 549 | WHITE_SPACE (' ') 550 | true ('true') 551 | comma (',') 552 | WHITE_SPACE (' ') 553 | true ('true') 554 | ] (']') 555 | WHITE_SPACE (' ') 556 | => ('=>') 557 | WHITE_SPACE (' ') 558 | { ('{') 559 | WHITE_SPACE ('\n ') 560 | ID_NAME ('balances_channel') 561 | ! ('!') 562 | ( ('(') 563 | WHITE_SPACE ('\n ') 564 | ( ('(') 565 | ID_NAME ('balances') 566 | WHITE_SPACE ('\n ') 567 | . ('.') 568 | ID_NAME ('insert') 569 | ( ('(') 570 | ID_NAME ('from') 571 | comma (',') 572 | WHITE_SPACE (' ') 573 | ID_NAME ('balance_of_sender') 574 | WHITE_SPACE (' ') 575 | - ('-') 576 | WHITE_SPACE (' ') 577 | ID_NAME ('amount') 578 | ) (')') 579 | ) (')') 580 | WHITE_SPACE ('\n ') 581 | . ('.') 582 | ID_NAME ('insert') 583 | ( ('(') 584 | ID_NAME ('to') 585 | comma (',') 586 | WHITE_SPACE (' ') 587 | ID_NAME ('balance_of_receiver') 588 | WHITE_SPACE (' ') 589 | + ('+') 590 | WHITE_SPACE (' ') 591 | ID_NAME ('amount') 592 | ) (')') 593 | WHITE_SPACE ('\n ') 594 | ) (')') 595 | WHITE_SPACE (' ') 596 | | ('|') 597 | WHITE_SPACE ('\n ') 598 | ID_NAME ('allowed_channel') 599 | ! ('!') 600 | ( ('(') 601 | WHITE_SPACE ('\n ') 602 | ID_NAME ('allowed') 603 | . ('.') 604 | ID_NAME ('insert') 605 | ( ('(') 606 | ID_NAME ('from') 607 | comma (',') 608 | WHITE_SPACE (' ') 609 | ID_NAME ('message_sender') 610 | comma (',') 611 | WHITE_SPACE (' ') 612 | ID_NAME ('sender_allowed') 613 | WHITE_SPACE (' ') 614 | - ('-') 615 | WHITE_SPACE (' ') 616 | ID_NAME ('amount') 617 | ) (')') 618 | WHITE_SPACE ('\n ') 619 | ) (')') 620 | WHITE_SPACE (' ') 621 | | ('|') 622 | WHITE_SPACE ('\n ') 623 | ID_NAME ('rtn') 624 | ! ('!') 625 | ( ('(') 626 | true ('true') 627 | ) (')') 628 | WHITE_SPACE ('\n ') 629 | } ('}') 630 | WHITE_SPACE ('\n ') 631 | _ ('_') 632 | WHITE_SPACE (' ') 633 | => ('=>') 634 | WHITE_SPACE (' ') 635 | { ('{') 636 | WHITE_SPACE ('\n ') 637 | ID_NAME ('balances_channel') 638 | ! ('!') 639 | ( ('(') 640 | ID_NAME ('balances') 641 | ) (')') 642 | WHITE_SPACE (' ') 643 | | ('|') 644 | WHITE_SPACE ('\n ') 645 | ID_NAME ('allowed_channel') 646 | ! ('!') 647 | ( ('(') 648 | ID_NAME ('allowed') 649 | ) (')') 650 | WHITE_SPACE (' ') 651 | | ('|') 652 | WHITE_SPACE ('\n ') 653 | ID_NAME ('rtn') 654 | ! ('!') 655 | ( ('(') 656 | false ('false') 657 | ) (')') 658 | WHITE_SPACE ('\n ') 659 | } ('}') 660 | WHITE_SPACE ('\n ') 661 | } ('}') 662 | WHITE_SPACE ('\n ') 663 | } ('}') 664 | WHITE_SPACE ('\n ') 665 | } ('}') 666 | WHITE_SPACE ('\n ') 667 | } ('}') 668 | WHITE_SPACE ('\n ') 669 | } ('}') 670 | WHITE_SPACE (' ') 671 | | ('|') 672 | WHITE_SPACE ('\n ') 673 | line_comment ('// This is the way an address can pre-approve (delegate) the transfer of') 674 | WHITE_SPACE ('\n ') 675 | line_comment ('// a certain amount of tokens to some other address. This allows for') 676 | WHITE_SPACE ('\n ') 677 | line_comment ('// that other address, through the use of the transfer_from function,') 678 | WHITE_SPACE ('\n ') 679 | line_comment ('// to send up to that amount of tokens.') 680 | WHITE_SPACE ('\n ') 681 | contract ('contract') 682 | WHITE_SPACE (' ') 683 | ID_NAME ('approve') 684 | ( ('(') 685 | ID_NAME ('message_sender') 686 | comma (',') 687 | WHITE_SPACE (' ') 688 | ID_NAME ('spender') 689 | comma (',') 690 | WHITE_SPACE (' ') 691 | ID_NAME ('amount') 692 | comma (',') 693 | WHITE_SPACE (' ') 694 | ID_NAME ('rtn') 695 | ) (')') 696 | WHITE_SPACE (' ') 697 | = ('=') 698 | WHITE_SPACE (' ') 699 | { ('{') 700 | WHITE_SPACE ('\n ') 701 | for ('for') 702 | WHITE_SPACE (' ') 703 | ( ('(') 704 | ID_NAME ('allowed') 705 | WHITE_SPACE (' ') 706 | < ('<') 707 | - ('-') 708 | WHITE_SPACE (' ') 709 | ID_NAME ('allowed_channel') 710 | ) (')') 711 | WHITE_SPACE (' ') 712 | { ('{') 713 | WHITE_SPACE ('\n ') 714 | ID_NAME ('allowed_channel') 715 | ! ('!') 716 | ( ('(') 717 | ID_NAME ('allowed') 718 | . ('.') 719 | ID_NAME ('insert') 720 | ( ('(') 721 | ID_NAME ('message_sender') 722 | comma (',') 723 | ID_NAME ('spender') 724 | comma (',') 725 | ID_NAME ('amount') 726 | ) (')') 727 | ) (')') 728 | WHITE_SPACE (' ') 729 | | ('|') 730 | WHITE_SPACE ('\n ') 731 | ID_NAME ('rtn') 732 | ! ('!') 733 | ( ('(') 734 | true ('true') 735 | ) (')') 736 | WHITE_SPACE ('\n ') 737 | } ('}') 738 | WHITE_SPACE ('\n ') 739 | } ('}') 740 | WHITE_SPACE (' ') 741 | | ('|') 742 | WHITE_SPACE ('\n ') 743 | contract ('contract') 744 | WHITE_SPACE (' ') 745 | ID_NAME ('balance_of') 746 | ( ('(') 747 | ID_NAME ('owner') 748 | comma (',') 749 | WHITE_SPACE (' ') 750 | ID_NAME ('rtn') 751 | ) (')') 752 | WHITE_SPACE (' ') 753 | = ('=') 754 | WHITE_SPACE (' ') 755 | { ('{') 756 | WHITE_SPACE ('\n ') 757 | for ('for') 758 | WHITE_SPACE (' ') 759 | ( ('(') 760 | ID_NAME ('balances') 761 | WHITE_SPACE (' ') 762 | < ('<') 763 | - ('-') 764 | WHITE_SPACE (' ') 765 | ID_NAME ('balances_channel') 766 | ) (')') 767 | WHITE_SPACE (' ') 768 | { ('{') 769 | WHITE_SPACE ('\n ') 770 | ID_NAME ('rtn') 771 | ! ('!') 772 | ( ('(') 773 | ID_NAME ('balances') 774 | . ('.') 775 | ID_NAME ('getOrElse') 776 | ( ('(') 777 | ID_NAME ('owner') 778 | comma (',') 779 | WHITE_SPACE (' ') 780 | Integer ('0') 781 | ) (')') 782 | ) (')') 783 | WHITE_SPACE (' ') 784 | | ('|') 785 | WHITE_SPACE ('\n ') 786 | ID_NAME ('balances_channel') 787 | ! ('!') 788 | ( ('(') 789 | ID_NAME ('balances') 790 | ) (')') 791 | WHITE_SPACE ('\n ') 792 | } ('}') 793 | WHITE_SPACE ('\n ') 794 | } ('}') 795 | WHITE_SPACE (' ') 796 | | ('|') 797 | WHITE_SPACE ('\n ') 798 | contract ('contract') 799 | WHITE_SPACE (' ') 800 | ID_NAME ('allowance') 801 | ( ('(') 802 | ID_NAME ('owner') 803 | comma (',') 804 | WHITE_SPACE (' ') 805 | ID_NAME ('spender') 806 | comma (',') 807 | WHITE_SPACE (' ') 808 | ID_NAME ('rtn') 809 | ) (')') 810 | WHITE_SPACE (' ') 811 | = ('=') 812 | WHITE_SPACE (' ') 813 | { ('{') 814 | WHITE_SPACE ('\n ') 815 | for ('for') 816 | WHITE_SPACE (' ') 817 | ( ('(') 818 | ID_NAME ('allowed') 819 | WHITE_SPACE (' ') 820 | < ('<') 821 | - ('-') 822 | WHITE_SPACE (' ') 823 | ID_NAME ('allowed_channel') 824 | ) (')') 825 | WHITE_SPACE (' ') 826 | { ('{') 827 | WHITE_SPACE ('\n ') 828 | ID_NAME ('allowed_channel') 829 | ! ('!') 830 | ( ('(') 831 | ID_NAME ('allowed') 832 | ) (')') 833 | WHITE_SPACE (' ') 834 | | ('|') 835 | WHITE_SPACE ('\n ') 836 | ID_NAME ('rtn') 837 | ! ('!') 838 | ( ('(') 839 | ID_NAME ('allowed') 840 | . ('.') 841 | ID_NAME ('getOrElse') 842 | ( ('(') 843 | ID_NAME ('owner') 844 | comma (',') 845 | ID_NAME ('spender') 846 | comma (',') 847 | Integer ('0') 848 | ) (')') 849 | ) (')') 850 | WHITE_SPACE ('\n ') 851 | } ('}') 852 | WHITE_SPACE ('\n ') 853 | } ('}') 854 | WHITE_SPACE (' ') 855 | | ('|') 856 | WHITE_SPACE ('\n ') 857 | contract ('contract') 858 | WHITE_SPACE (' ') 859 | ID_NAME ('contract_owner') 860 | ( ('(') 861 | ID_NAME ('rtn') 862 | ) (')') 863 | WHITE_SPACE (' ') 864 | = ('=') 865 | WHITE_SPACE (' ') 866 | { ('{') 867 | WHITE_SPACE ('\n ') 868 | for ('for') 869 | WHITE_SPACE (' ') 870 | ( ('(') 871 | ID_NAME ('owner') 872 | WHITE_SPACE (' ') 873 | < ('<') 874 | - ('-') 875 | WHITE_SPACE (' ') 876 | ID_NAME ('owner_channel') 877 | ) (')') 878 | WHITE_SPACE (' ') 879 | { ('{') 880 | WHITE_SPACE ('\n ') 881 | ID_NAME ('owner_channel') 882 | ! ('!') 883 | ( ('(') 884 | ID_NAME ('owner') 885 | ) (')') 886 | WHITE_SPACE (' ') 887 | | ('|') 888 | WHITE_SPACE ('\n ') 889 | ID_NAME ('rtn') 890 | ! ('!') 891 | ( ('(') 892 | ID_NAME ('owner') 893 | ) (')') 894 | WHITE_SPACE ('\n ') 895 | } ('}') 896 | WHITE_SPACE ('\n ') 897 | } ('}') 898 | WHITE_SPACE (' ') 899 | | ('|') 900 | WHITE_SPACE ('\n ') 901 | ID_NAME ('return_channel') 902 | ! ('!') 903 | ( ('(') 904 | WHITE_SPACE ('\n ') 905 | ID_NAME ('Map') 906 | ( ('(') 907 | ) (')') 908 | . ('.') 909 | ID_NAME ('insertMany') 910 | ( ('(') 911 | StringLit ('"transfer"') 912 | comma (',') 913 | WHITE_SPACE (' ') 914 | ID_NAME ('transfer') 915 | comma (',') 916 | WHITE_SPACE (' ') 917 | StringLit ('"transfer_from"') 918 | comma (',') 919 | WHITE_SPACE (' ') 920 | ID_NAME ('transfer_from') 921 | comma (',') 922 | WHITE_SPACE ('\n ') 923 | StringLit ('"approve"') 924 | comma (',') 925 | WHITE_SPACE (' ') 926 | ID_NAME ('approve') 927 | comma (',') 928 | WHITE_SPACE (' ') 929 | StringLit ('"balance_of"') 930 | comma (',') 931 | WHITE_SPACE (' ') 932 | ID_NAME ('balance_of') 933 | comma (',') 934 | WHITE_SPACE (' ') 935 | StringLit ('"allowance"') 936 | comma (',') 937 | WHITE_SPACE (' ') 938 | ID_NAME ('allowance') 939 | comma (',') 940 | WHITE_SPACE ('\n ') 941 | StringLit ('"contract_owner"') 942 | comma (',') 943 | WHITE_SPACE (' ') 944 | ID_NAME ('contract_owner') 945 | ) (')') 946 | ) (')') 947 | WHITE_SPACE ('\n ') 948 | line_comment ('// TODO: Eventually just insert with compiler') 949 | WHITE_SPACE ('\n ') 950 | } ('}') 951 | WHITE_SPACE ('\n ') 952 | } ('}') 953 | WHITE_SPACE ('\n ') 954 | } ('}') 955 | WHITE_SPACE (' ') 956 | | ('|') 957 | WHITE_SPACE ('\n ') 958 | new ('new') 959 | WHITE_SPACE (' ') 960 | ID_NAME ('rtn') 961 | comma (',') 962 | WHITE_SPACE (' ') 963 | ID_NAME ('me') 964 | comma (',') 965 | WHITE_SPACE (' ') 966 | ID_NAME ('they') 967 | WHITE_SPACE (' ') 968 | in ('in') 969 | WHITE_SPACE (' ') 970 | { ('{') 971 | WHITE_SPACE ('\n ') 972 | ID_NAME ('token') 973 | ! ('!') 974 | ( ('(') 975 | ID_NAME ('me') 976 | comma (',') 977 | WHITE_SPACE (' ') 978 | Integer ('100') 979 | comma (',') 980 | WHITE_SPACE (' ') 981 | ID_NAME ('rtn') 982 | ) (')') 983 | WHITE_SPACE (' ') 984 | | ('|') 985 | WHITE_SPACE ('\n ') 986 | for ('for') 987 | WHITE_SPACE (' ') 988 | ( ('(') 989 | ID_NAME ('token_contract') 990 | WHITE_SPACE (' ') 991 | < ('<') 992 | - ('-') 993 | WHITE_SPACE (' ') 994 | ID_NAME ('rtn') 995 | ) (')') 996 | WHITE_SPACE (' ') 997 | { ('{') 998 | WHITE_SPACE ('\n ') 999 | new ('new') 1000 | WHITE_SPACE (' ') 1001 | ID_NAME ('unused_rtn') 1002 | comma (',') 1003 | WHITE_SPACE (' ') 1004 | ID_NAME ('balance_of_rtn') 1005 | WHITE_SPACE (' ') 1006 | in ('in') 1007 | WHITE_SPACE (' ') 1008 | { ('{') 1009 | WHITE_SPACE ('\n ') 1010 | @ ('@') 1011 | ID_NAME ('token_contract') 1012 | . ('.') 1013 | ID_NAME ('get') 1014 | ( ('(') 1015 | StringLit ('"transfer"') 1016 | ) (')') 1017 | ! ('!') 1018 | ( ('(') 1019 | ID_NAME ('me') 1020 | comma (',') 1021 | WHITE_SPACE (' ') 1022 | ID_NAME ('they') 1023 | comma (',') 1024 | WHITE_SPACE (' ') 1025 | Integer ('50') 1026 | comma (',') 1027 | WHITE_SPACE (' ') 1028 | ID_NAME ('unused_rtn') 1029 | ) (')') 1030 | WHITE_SPACE (' ') 1031 | | ('|') 1032 | WHITE_SPACE ('\n ') 1033 | @ ('@') 1034 | ID_NAME ('token_contract') 1035 | . ('.') 1036 | ID_NAME ('get') 1037 | ( ('(') 1038 | StringLit ('"balance_of"') 1039 | ) (')') 1040 | ! ('!') 1041 | ( ('(') 1042 | ID_NAME ('they') 1043 | comma (',') 1044 | WHITE_SPACE (' ') 1045 | ID_NAME ('balance_of_rtn') 1046 | ) (')') 1047 | WHITE_SPACE (' ') 1048 | | ('|') 1049 | WHITE_SPACE ('\n ') 1050 | for ('for') 1051 | WHITE_SPACE (' ') 1052 | ( ('(') 1053 | ID_NAME ('they_balance') 1054 | WHITE_SPACE (' ') 1055 | < ('<') 1056 | - ('-') 1057 | WHITE_SPACE (' ') 1058 | ID_NAME ('balance_of_rtn') 1059 | ) (')') 1060 | WHITE_SPACE (' ') 1061 | { ('{') 1062 | WHITE_SPACE ('\n ') 1063 | ID_NAME ('they_balance') 1064 | . ('.') 1065 | ID_NAME ('display') 1066 | ( ('(') 1067 | StringLit ('"\n"') 1068 | ) (')') 1069 | WHITE_SPACE ('\n ') 1070 | } ('}') 1071 | WHITE_SPACE ('\n ') 1072 | } ('}') 1073 | WHITE_SPACE ('\n ') 1074 | } ('}') 1075 | WHITE_SPACE ('\n ') 1076 | } ('}') 1077 | WHITE_SPACE (' ') 1078 | | ('|') 1079 | WHITE_SPACE ('\n ') 1080 | new ('new') 1081 | WHITE_SPACE (' ') 1082 | ID_NAME ('rtn2') 1083 | comma (',') 1084 | WHITE_SPACE (' ') 1085 | ID_NAME ('me2') 1086 | comma (',') 1087 | WHITE_SPACE (' ') 1088 | ID_NAME ('they2') 1089 | WHITE_SPACE (' ') 1090 | in ('in') 1091 | WHITE_SPACE (' ') 1092 | { ('{') 1093 | WHITE_SPACE ('\n ') 1094 | ID_NAME ('token') 1095 | ! ('!') 1096 | ( ('(') 1097 | ID_NAME ('me2') 1098 | comma (',') 1099 | WHITE_SPACE (' ') 1100 | Integer ('1000') 1101 | comma (',') 1102 | WHITE_SPACE (' ') 1103 | ID_NAME ('rtn2') 1104 | ) (')') 1105 | WHITE_SPACE (' ') 1106 | | ('|') 1107 | WHITE_SPACE ('\n ') 1108 | for ('for') 1109 | WHITE_SPACE (' ') 1110 | ( ('(') 1111 | ID_NAME ('token_contract2') 1112 | WHITE_SPACE (' ') 1113 | < ('<') 1114 | - ('-') 1115 | WHITE_SPACE (' ') 1116 | ID_NAME ('rtn2') 1117 | ) (')') 1118 | WHITE_SPACE (' ') 1119 | { ('{') 1120 | WHITE_SPACE ('\n ') 1121 | new ('new') 1122 | WHITE_SPACE (' ') 1123 | ID_NAME ('unused_rtn2') 1124 | comma (',') 1125 | WHITE_SPACE (' ') 1126 | ID_NAME ('balance_of_rtn2') 1127 | WHITE_SPACE (' ') 1128 | in ('in') 1129 | WHITE_SPACE (' ') 1130 | { ('{') 1131 | WHITE_SPACE ('\n ') 1132 | @ ('@') 1133 | ID_NAME ('token_contract2') 1134 | . ('.') 1135 | ID_NAME ('get') 1136 | ( ('(') 1137 | StringLit ('"transfer"') 1138 | ) (')') 1139 | ! ('!') 1140 | ( ('(') 1141 | ID_NAME ('me2') 1142 | comma (',') 1143 | WHITE_SPACE (' ') 1144 | ID_NAME ('they2') 1145 | comma (',') 1146 | WHITE_SPACE (' ') 1147 | Integer ('500') 1148 | comma (',') 1149 | WHITE_SPACE (' ') 1150 | ID_NAME ('unused_rtn2') 1151 | ) (')') 1152 | WHITE_SPACE (' ') 1153 | | ('|') 1154 | WHITE_SPACE ('\n ') 1155 | @ ('@') 1156 | ID_NAME ('token_contract2') 1157 | . ('.') 1158 | ID_NAME ('get') 1159 | ( ('(') 1160 | StringLit ('"balance_of"') 1161 | ) (')') 1162 | ! ('!') 1163 | ( ('(') 1164 | ID_NAME ('they2') 1165 | comma (',') 1166 | WHITE_SPACE (' ') 1167 | ID_NAME ('balance_of_rtn2') 1168 | ) (')') 1169 | WHITE_SPACE (' ') 1170 | | ('|') 1171 | WHITE_SPACE ('\n ') 1172 | for ('for') 1173 | WHITE_SPACE (' ') 1174 | ( ('(') 1175 | ID_NAME ('they_balance2') 1176 | WHITE_SPACE (' ') 1177 | < ('<') 1178 | - ('-') 1179 | WHITE_SPACE (' ') 1180 | ID_NAME ('balance_of_rtn2') 1181 | ) (')') 1182 | WHITE_SPACE (' ') 1183 | { ('{') 1184 | WHITE_SPACE ('\n ') 1185 | ID_NAME ('they_balance2') 1186 | . ('.') 1187 | ID_NAME ('display') 1188 | ( ('(') 1189 | StringLit ('"\n"') 1190 | ) (')') 1191 | WHITE_SPACE ('\n ') 1192 | } ('}') 1193 | WHITE_SPACE ('\n ') 1194 | } ('}') 1195 | WHITE_SPACE ('\n ') 1196 | } ('}') 1197 | WHITE_SPACE ('\n ') 1198 | } ('}') 1199 | WHITE_SPACE ('\n ') 1200 | line_comment ('// Once we have a registry, we can do registry_channel!(token) to save the contract there') 1201 | WHITE_SPACE ('\n') 1202 | } ('}') 1203 | --------------------------------------------------------------------------------