Integration with Ren'py #268
Replies: 30 comments 26 replies
-
Hi @blurymind I'm not very experienced with parsers, do you think it's possible to give the possibility to bind renpy files with pixi-vn? as we are doing with ink |
Beta Was this translation helpful? Give feedback.
-
That would be a killer feature for sure... but I dont have alot of experience with parsers. I did some bug fixing on bondagejs (yarn file parser) in the past. That uses jison, not sure if its the best choice. Its a cool idea because in theory it might help with directly converting renpy games to pixi-vn games! |
Beta Was this translation helpful? Give feedback.
-
Update: I tested https://github.com/damyo-scientists/renpy-js in the basic cases it manages to extrapolate something, but I'm afraid it doesn't have such an effective control. But I thought of another way that could be effective even if a Parser is not used: It doesn't seem like a simple process and it would need the help of one of the developers. but it would have the advantage that it would be continuously updated by renpy. |
Beta Was this translation helpful? Give feedback.
-
Hi, I've started working on a full parser behind the scenes on different branches on that repo. One is on the 'parser' branch, and the other on the 'lsp-server' branch. (With the lsp-server setup, it should be possible to interact with that from any other application as well.) I'd love to help setup what you guys need, and get some help with that parser from you guys as well. To give a quick overview of what is currently implemented: The parser is in it's early stages though, the parser is needed to get an AST (abstract syntax tree). The AST allows us to verify if a token sequence is valid renpy code grammar. |
Beta Was this translation helpful? Give feedback.
-
yes i noticed that branch. in fact i planned to fork it and then create a library. i can help, but it would be better to create an npm parser library external to the vscode extension project, in this way i can install it in my project and in this way it is easier to understand how it works. |
Beta Was this translation helpful? Give feedback.
-
Yeah, so that's the idea behind the lsp-server. You basically build a completely separate application (I chose to build it in typescript as an npm package). That lsp-server can then be used outside of vscode as well. The 'client' is the vscode extension. (Read this if you want to learn more). In your case you'd implement the client side in your application using the Language Server Protocol setup by Microsoft. The server will then do all the parsing and you'd only have to request the data you want. |
Beta Was this translation helpful? Give feedback.
-
LSP is the best goal to achieve for both me and you. I would also be interested in implementing a function that extracts a json with the information of a renpy file (with LSP it is certainly feasible). I have never created one but I can certainly help. However, I insist on the fact that to create it it would be better to start from an empty project with a Submodules (temporary) that points to https://github.com/renpy/vscode-language-renpy/tree/parser (to obtain the elements that are currently in that repo) I or you can create a new repo to start working on it (giving access to others), then eventually move it to renpy. |
Beta Was this translation helpful? Give feedback.
-
I understand you completely, and I also avoided implementing the lsp elements for that reason. It adds a lot of 'unnecessary' overhead. (In my case it has become a necessity, because that's the only way to do proper multi-threaded processing. Allowing the server to be processing all files in the project without the client freezing). I will say that it's just me doing this for fun in my free time (which is already limited), and a completely separate library doesn't align with my (personal) current goals for the project. That said, I'm happy to tell you what files to look at and how to use them. |
Beta Was this translation helpful? Give feedback.
-
Ok I can help with vscode-language-renpy implementation but I will need more detailed explanation to understand how to test the LSP. |
Beta Was this translation helpful? Give feedback.
-
The LSP is something I just started a couple of days ago. I'll need some time to link and move the previous implementation correctly. As far as I can tell, it won't take too much effort. Should be just a matter of calling the right API from the right events. FYI, I'm in the middle of moving to a new place, so I will have very limited time until the 9th of August. I think you'll be more interested in the parser branch rn. There is a single function called 'testParser()'. That will run the current implementation of the parser. What it does right now is run the tokenizer on the opened file, then run some simple parser rules and output some parser debug information to the console. I was working on a formal grammar definition that you can find in the 'grammar' folder. That is very helpful for defining the grammar rules correctly in code. (The grammar file is about 60% complete, and it might be missing some of the new features.) Quick overview of the functionality: The tokenizer is fully mature and is used in production right now. It is able to output some 'unusual' tokens (it's sort of a parser itself). It is able to output meta tokens that basically give you a rudimentary AST. It's just not yet verified, which is what the parser is supposed to do. The tokenizer works equivalent to the one build into vscode, which they use for syntax highlighting. (Which is using this https://github.com/kkos/oniguruma). (My version is a completely custom implementation in ts though). Sorry if that was too much info dumping, but let me know if you need more info :) |
Beta Was this translation helpful? Give feedback.
-
Ok should I fork this or can you add me to the projects? |
Beta Was this translation helpful? Give feedback.
-
Unfortunately I can't add you as a dev myself. (I'm not the owner of the repo with admin rights). So for now you'll need to fork and make a PR. |
Beta Was this translation helpful? Give feedback.
-
ok I forked and invited you so we can collaborate. |
Beta Was this translation helpful? Give feedback.
-
Doing this right now is a bit difficult due to my limited time until the 9th. I can try to set that up ASAP, but can't promise it can be done before that. To launch the extension is relatively simple though. (There should be instructions on the repo). You just open the repo using vscode, then you run npm install, and finally you just run the extension (through vscode's launch mechanism) |
Beta Was this translation helpful? Give feedback.
-
ok, yes i understand how to execute it. now i will spend some time to understand how the parser actually works. |
Beta Was this translation helpful? Give feedback.
-
Awesome, I've added a new section on the main page with the build instructions in a PR. (Also includes tips for usage btw). I realized that it can be hard to find in the contributing link. Let me know if you need any more help or if you'd like me to explain something. Chatting using my phone I can do while I'm not at my pc |
Beta Was this translation helpful? Give feedback.
-
Hi, I took a look at the parser. Anyway, what interests me most is when the parser "extracts information" in the rows that make up a label, has this step already been implemented? |
Beta Was this translation helpful? Give feedback.
-
Yes, you are correct. That's the core loop. The statementParser.test() function is running the code here. The way the parser is structured right now, is that I have defined a bunch of 'rules', which build 'nodes'. So to give an example, the line linked above is a rule that loops through a list of rules. One of those rules is the DefineStatementRule. This rule has a test and a parse function. If test returns true, this means the rule should be parsed. The loop (a bit back up the callstack) then triggers the parse method. This parse method will parse tokens. Again to give an example, the DefineStatementRule checks the current token. In this case it requires that the first token is the keyword 'define'. The renpy syntax allows an optional integer, then an assignment operation. And lastly it expects an end of line. In the comments above the class you can see a bit of EBNF grammar definition. Please read the comment in the grammars/renpy.grammar.ebnf file to understand the syntax. |
Beta Was this translation helpful? Give feedback.
-
It appears I have not yet made the rule for labels, however I did already define the ebnf definition for labels, so it should be possible to implement the label rule with that definition. I should note though, that I know some edge cases have not been handled by the parser yet. For example, I don't think I handle comments yet. And the error handling needs to be improved, but if we start with some valid syntax while building the parser we can deal with that later. Also check out this file (and the others in that folder) for a complete list of all the tokens that the tokenizer can output. |
Beta Was this translation helpful? Give feedback.
-
Also, I hope to get some time before the 9th so we can work on it together, but I doubt I will have time before that. On the other hand, this gives you a chance to get familiar with the codebase and stuff so I guess it's not that big of a deal for those couple of days right? |
Beta Was this translation helpful? Give feedback.
-
yes, don't worry. It will take a while before I understand how the parser works to be able to implement something. Every now and then I will ask you some questions |
Beta Was this translation helpful? Give feedback.
-
I had a couple minutes when I took a break and I did a quick test run. Noticed a couple of bugs, so fixed them real quick. I pushed them to the origin branch. I also added a simple parser_test.rpy file, which will run the define parse and then process the AST to get the defined 'e' symbol. (You can put some breakpoints to see what it does). I did notice I didn't hook it up to the document changed event, so currently it will only run on start |
Beta Was this translation helpful? Give feedback.
-
Made a bunch of improvements again. It is now able to parse labels and has improved error handling |
Beta Was this translation helpful? Give feedback.
-
@duckdoom4 I'm not sure what else needs to be implemented, however if you write me what needs to be implemented and more or less how you thought of doing it, I can help you |
Beta Was this translation helpful? Give feedback.
-
Yeah, so I made some more changes on the main branch. I've merged them into your branch now. How it works internallySo if we look at the file Then the parser uses this sequence to generate an AST (abstract syntax tree). We then process the AST (iterate the nodes) to create the 'RpyProgram' object using As an example the following line searches for a symbol named 'e' in the global program scope (note that python doesn't really have local scopes, so might remove this later): -- What we can do nextSo I hope that makes it a bit more clear how it works. Let's talk about what to do next. My latest addition is label definition processing. I'd recommend looking at the changes I introduced to What I think could be a really nice introduction for you is attempting to implement the 'jump' statement from renpy. This one is very simple. Define the grammarFirst we need the grammar definition. (I already made it, you can find it here.) Implement the parserWith the parser implemented (let me know if you still want some more details about that), we can now integrate it. That's also pretty straight forward. If you search in the ebnf file, you will also find out where it's supposed to be used. (In this case only as part of the statement group). So adding it to this list will mean it's processed correctly. Add the ASTLastly, we will need to create and implement the ResultIf we did everything correctly, we should then be able to go back to the Let me know if you need more info or help with anything. Looking forward to your attempt! (And no worries if you don't quite get it yet, it took me weeks to wrap my head around compiler theory) |
Beta Was this translation helpful? Give feedback.
-
Just in case you tried it today or yesterday; I just pushed a fix to the parser branch (yours as well). Apparently I broke it, but it's fixed now xd |
Beta Was this translation helpful? Give feedback.
-
hello sorry for not writing to you, I've been very busy developing the integration with ink (another narrative language), I didn't expect ink to be very large. as soon as I'm done with ink I'll switch to renpy. |
Beta Was this translation helpful? Give feedback.
-
Hello @duckdoom4 I completed/tested the integration with ink (ink documentation is here https://pixi-vn.web.app/ink/ink.html), now I intend to work on integration with Ren'Py. I quickly explain how this integration will work (maybe I had already hoped for it previously). Exactly as it was developed for integration with ink, I will create a function that receives the text of the What I need to serve is a function that after giving input a text written with the language of Renpy gives me an element with information on the procedures written in that text. After I will take care of transforming that element into a Json readable by pixi-vn-json. By rereading the old comments I saw that you had explained to me that in the extension of vs-code for Ren'py there was a class that I could use to do this. is it still like that? Is this class unrelated to the bookstore to create extensions in vs-code? If it is not, is it possible to disconnect it from the library to create extensions in vs-code? The development of this integration will be divided into step. The first step would simply get the Label list in a file and for each of this understand which dialogues are present. For example in this case: label sample1:
"Here is 'sample1' label."
label sample2:
"Here is 'sample2' label." I would like to get: {
"labels": {
"sample1": [
{
"dialogue": "Here is 'sample1' label.",
}
],
"sample2": [
{
"dialogue": "Here is 'sample2' label.",
}
]
}
} Is it currently possible to get this information from your VS-Code extension? |
Beta Was this translation helpful? Give feedback.
-
@duckdoom4 hello, sorry for the disturbance. I managed to make the parser work using a string. I created a small project https://github.com/DRincs-Productions/pixi-vn-renpy I can run the code of the following function. But I don't understand now that I have the "parser" object how can I get the information of the text written in renpy that I passed as input.
|
Beta Was this translation helpful? Give feedback.
-
Hi @duckdoom4 , I managed to get through the library. but I have doubts about the following texts: label start:
"Hello, World!"
"This is a test."
"This is a test."
label end:
"Goodbye, World!" In this case starting from
Is there a way to get the information that after label back_in_london:
"We arrived into London at 9.45pm exactly."
call hurry_home
label hurry_home:
"We hurried home to Savile Row as fast as we could."
return The following text gives me some errors. but I'm not sure why. is it because it doesn't have a label called ( if you want to debug them in the usual project I have inserted some test files ) |
Beta Was this translation helpful? Give feedback.
-
On the internet I found this library that allows you to run a ren'py file to get all the information of that file.
I think it can be used to give the possibility of making renpy files compatible with pixi vn.
https://github.com/damyo-scientists/renpy-js developed by @horace-velmont
I noticed that the repo is based on the official renpy parser in python:
Renpy: parser.py
https://www.renpy.org/static/wiki/parser.py
Beta Was this translation helpful? Give feedback.
All reactions