ItsDeltin / Overwatch-Script-To-Workshop

Converts scripts to Overwatch workshops.
207 stars 24 forks source link

Compatible code formatter? #422

Open mriswithe opened 1 year ago

mriswithe commented 1 year ago

I dearly appreciate this language for not making me write in the base overwatch language, so first thank you so very much. This is already so much better than what was provided, for me. That said, Is there a formatter/syntax I can feed to prettier to get it to consistently indent my code? .... I will admit I come from Python. It helps my brain box stuff together. I appreciate any pointers you have on this!

ItsDeltin commented 1 year ago

There isn't anything right now (unless there is some generic formatter which can work on any language?) I recognize how convenient this would be, I'll look into making a prettier extension.

mriswithe commented 1 year ago

I could whip something up in Python pretty quick. Is there a language parser declaration somewhere I can eat or do I need to write the grammar myself?

Also are you even interested in my help or is this your baby?

mriswithe commented 1 year ago

Just a poke on this as I have been messing around with some parser generators and the like. Are you interested in contribution on this? Don't want to spend time learning and building stuff otherwise!

ItsDeltin commented 1 year ago

Sorry for the late response and thanks for the offer! I am interested in contributions. Currently there isn't a document that specifies the syntax. This file handles the document parsing but I don't expect you to decipher it. What may be more helpful is this project which uses most features ostw has to offer if you need to need something to test the grammar with. I'll make sure to pay attention to activity in the repository (sorry)

mriswithe commented 1 year ago

Sorry for the late response

I'll make sure to pay attention to activity in the repository (sorry)

No, please understand. You owe me nothing. Would I have preferred an immediate response? Sure would, but I need to work on my patience anyway. You already made a language that is less of a pain to work with than the base workshop. I am just trying to make it pretty automatically.

https://github.com/ItsDeltin/Overwatch-Script-To-Workshop/blob/master/Deltinteger/Deltinteger/Compiler/Parse/Parser.cs

I had found that, also found some YAML -> JSON EBNF that is at least a decent point in the right direction. Also a dataset like the project you linked is perfect.

I am working with Tatsu, a Python PEG Parser library. I have very little experience in this realm, so it is slow going, but a decently fun puzzle.

So far I can parse all of these lines:

doMixedParams(param1,Param2,arg=thing,arg2=thing2);
doNoParams();
doParams(arg,arg2,arg3);
doKWOnly(arg2=ThingsStuff1,peanut=Butter);
doBadMixOnly(arg2=ThingsStuff1,peanut=Butter,arg3);
import "!potato.del";
import "something.del";

and get mostly reasonable JSON back (still figuring out how to indicate the presence or absence of the ! on import in a better way, but it isn't blocking, just not preferred.

[
  {
    "func": "doMixedParams",
    "params": [
      "param1",
      "Param2"
    ],
    "names": [
      "arg",
      "arg2"
    ],
    "vals": [
      "thing",
      "thing2"
    ]
  },
  {
    "func": "doNoParams"
  },
  {
    "func": "doParams",
    "params": [
      "arg",
      "arg2",
      "arg3"
    ]
  },
  {
    "func": "doKWOnly",
    "names": [
      "arg2",
      "peanut"
    ],
    "vals": [
      "ThingsStuff1",
      "Butter"
    ]
  },
  {
    "func": "doBadMixOnly",
    "names": [
      "arg2",
      "peanut"
    ],
    "vals": [
      "ThingsStuff1",
      "Butter"
    ],
    "params": "arg3"
  },
  {
    "IMPORT_NAME": [
      "!",
      "potato.del"
    ]
  },
  {
    "IMPORT_NAME": [
      null,
      "something.del"
    ]
  }
]

Also, is this a syntax error in OSTW?

doBadMixOnly(arg2=ThingsStuff1,peanut=Butter,arg3);

keyword arguments and non keyword in whatever order?

Actually, what is the syntax behind keyword arguments? I had seen you use them in a couple places, but couldn't really get the hang of them and I didn't see them explicitly in the wiki that I could find.

mriswithe commented 1 year ago

Oh also the EBNF is of course flavored by Tatsu, but it looks like this:

@@grammar::Ostw
@@eol_comments :: /\/\/.*?$/
@@keyword :: If Else While For Rule variables actions conditions event global player End
@@keyword :: conditions event global player End settings modes heroes

start = {stuff}+ $ ;

ident = /[\w\d]+/ ;
number = /[\d]+/ ;
func_start = func: ident '(';
func_end = ')' ';' ;
statement = >func_start ','.{(params: ident !'=')|{names: ident '=' vals: ident}}*  func_end;

import = 'import' '"' IMPORT_NAME: ( ['!']  /[a-zA-Z0-9!.]+/ ) '"' ';';

stuff
    =
    | statement
    | import
    ;
mriswithe commented 1 year ago

Also, I have said it before, and I will say it again, but if I were to use a language that requires getter/setters, I would want to use one where you define them like csharp does!

        public Stack<int> TokenRangeStart { get; } = new Stack<int>();
        public Stack<bool> TernaryCheck { get; } = new Stack<bool>();
        public Stack<bool> StringCheck { get; } = new Stack<bool>();
        public List<TokenCapture> NodeCaptures { get; } = new List<TokenCapture>();
        public List<IParserError> Errors { get; } = new List<IParserError>();
ItsDeltin commented 1 year ago

I should add this to the wiki, named parameters look like this:

rule: 'test'
{
    CreateHudText(
        AllPlayers(), // can start with unnamed parameters
        Text: 'hud text',
        Location: Location.Right,
        TextColor: Color.Aqua,
        HudTextRev.SortOrderAndColor // Syntax error, can't used unnamed parameters after named parameters.
    );
}
mriswithe commented 1 year ago
rule: 'test'
{
    CreateHudText(
        AllPlayers(), // can start with unnamed parameters
        Text: 'hud text',         Location: Location.Right,        TextColor: Color.Aqua,
    );
}

Is this acceptable? or are the new lines and tabbing load bearing? I would assume no.

ItsDeltin commented 1 year ago

You are correct, ostw ignores whitespace. Whitespace between the parameters like that is a style I haven't seen before, I'm more familiar with stuff like this:

CreateHudText(AllPlayers(), Text: 'hud text', Location: Location.Right, TextColor: Color.Aqua);
// or
CreateHudText(
    AllPlayers(),
    Text: 'hud text',
    Location: Location.Right,
    TextColor: Color.Aqua);

Another thing worth mentioning is that ostw also has # comments. I need to add this to the wiki, too. They differ slightly from // and /* */. When a statement is preceded by a # comment, it will be added to the workshop output.

// ostw
# Notify players that the game has begun
SmallMessage(AllPlayers(), "The game is afoot!");
// workshop
"Notify players that the game has begun"
SmallMessage(AllPlayers(), Custom String("The game is afoot!"));

They can also precede function definitions to document them. When the definition is hovered over, the description is shown.

# Gets the input player's next target goal.
void updatePlayerTarget(in Player player) { }

I don't think any special formatting needs to occur with them, just letting you know that they exist.

mriswithe commented 1 year ago

The comments I had found, but shouldn't be tricky. All the parser needs to do is know what is important input and what isn't, then spit the important stuff out in a neatly formatted pile.

Oh and that indent style is what I call horrordent. .... I just randomly messed with it to make sure that given bad whitespace was not suddenly important to the language.

mriswithe commented 1 year ago

From here: https://github.com/ItsDeltin/Overwatch-Script-To-Workshop/wiki/Lambdas-and-function-types#function-types

The types of the function parameters are defined on the left side of the =>, and the return type is defined on the right. To assign a function type in code to a method, declare the name of the method group. If there are multiple methods with the same name, the method chosen is matched with the parameters and return type of the function type.

This is either genius or insanity, is this basically global overloaded methods keyed on both the param types and the return types? Where did you come up with such an idea?? I am not judging, I want to understand.

I am currently working on the function type parsing code hehe, and I think I finally understand what that paragraph says.

mriswithe commented 1 year ago

If you wish to follow along at home, the grammar is here: https://github.com/mriswithe/ostw_formatter

ItsDeltin commented 1 year ago

C# does the same thing, here is a simple example:

void DestroyDummyBot(Team team, Number slot); // #1
void DestroyDummyBot(Player player);          // #2

// 2 methods with the same name are in scope
(Team, Number) => void my_variable_1 = DestroyDummyBot; // method #1 is chosen
(Player)       => void my_variable_2 = DestroyDummyBot; // method #2 is chosen

// destroy the event player (who is also a dummy)
my_variable_2(EventPlayer());

// even though both variables are assigned to `DestroyDummyBot`, they will have different values because
// of the variable type they are assigned to.
mriswithe commented 1 year ago

Breaking my fragile sysadmin mind! The fact that the return value was part of the "key" so to speak, was not something that had ever occurred to me as part of learning about overloads.

mriswithe commented 1 year ago

What are all of the valid constructs in a class definition:

class NumberSelector
{
// HERE
}

so far I have:

Also is this an acceptable path for my random language questions relating to parsing?

mriswithe commented 1 year ago

Looks like maybe macros can go there too?

ItsDeltin commented 1 year ago
struct|class NumberSelector
{
    // Variable
    public Number var1 = 3;
    // Macro variable
    public Number var2: 3;
    // Method
    public Number method1(in Number param1) { return param1 * 3; }
    // Macro method
    public Number method2(in Number param1): param1 * 3;
    // Class constructor
    constructor(in Number param1, in Number param2) {
    }
} 

Also is this an acceptable path for my random language questions relating to parsing?

This is fine, however, a few people who use ostw frequent the workshop.codes discord in the #hll-scripting channel. They'll be able to answer your questions when I'm not around, plus you can see how people prefer to format their code.

mriswithe commented 1 year ago

Excellent!! I joined up now! This is much better for casual back and forth and less of me beating my face against a wall sometimes hehehe.