Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SQF lexer #761

Merged
merged 4 commits into from Aug 10, 2018
Merged

Add SQF lexer #761

merged 4 commits into from Aug 10, 2018

Conversation

BaerMitUmlaut
Copy link
Contributor

This PR adds a lexer with a demo and an example for the SQF scripting language.

This scripting language is used in Bohemia Interactive's Arma series for creating singleplayer campaigns, multiplayer scenarios and gameplay addons. Github has had syntax highlighting for SQF for some time now, but Gitlab (which quite a few communities use for private developments) was unfortunately still lacking it.

Don't be confused by the large list of command keywords. In SQF there are only commands and variables, no keywords or operators, with the exception of private and =. Even if or : (for switch case) are commands. Commands are defined by the engine and cannot be defined by a user. The whole grammar looks something like this:

block := ((statement;)* statement)?;?
statement := (assignment)? code
assignment := (private)? variable =
code := literal
      | variable
      | { block }
      | [ ((code,)* code)? ]
      | nular
      | unary code
      | code binary code

The code in spec/visual/samples/sqf was used to generate the list of commands.

end

# high priority for filename matches
def self.analyze_text(*)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

analyze_text is no longer availabe on the maste branch.

See #763 for details

@BaerMitUmlaut
Copy link
Contributor Author

I assume it should just always return false if there is no doctype or shebang declaration for the language?

@gfx
Copy link
Member

gfx commented Sep 21, 2017

@BaerMitUmlau

Just use the default implementation of detect?: https://github.com/jneen/rouge/blob/master/lib/rouge/lexer.rb#L445-L447 (i.e. false), if a lexer can't detect the type from a source.

@BaerMitUmlaut
Copy link
Contributor Author

Should be good now.

# Identifiers (variables and functions)
rule %r"[a-zA-Z0-9_]+" do |m|
name = m[0].downcase
if self.class.wordoperators.include? name
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually prefer it this way for keyword lists - in my experience it tends to perform better than large | regexes.


def self.commands
@commands = Set.new %w(
abs acctime acos action actionids actionkeys actionkeysimages
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you make the list?

If it's programmatically generated, add the script as a comment (if it can be a one liner), or add rake task to tasks/.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's generated using the spec/visual/samples/sqf script, with some manual filtering afterwards (because as mentioned in the OP, pretty much everything is a command). Since that is run in game, that's not an option.
Alternatively, there's a wiki page that could be scraped. I will have to check how much it deviates from this list (there might be some outdated commands in there).

Copy link

@dedmen dedmen May 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use the same that I used for highlight.js. But it's much simpler since we don't need case sensitivity here.

https://github.com/dedmen/highlight.js_SQFgen

Basically parse
https://github.com/intercept/intercept/blob/master/src/client/headers/client/sqf_assignments.hpp
with regex \("([^"]*)"
That list get's regularly(programmatically) refreshed with all commands.

You'll have to add commands that are only available in specific game builds (https://github.com/dedmen/highlight.js_SQFgen/blob/master/additonalCommandList.txt)

and filter out things like
https://github.com/jneen/rouge/pull/761/files/5a9d5b12121b4c50c15deaf4183e0c42b59b6ba7#diff-21afe91a2d45af3ae84baa20d85ce523R13
and
https://github.com/jneen/rouge/pull/761/files/5a9d5b12121b4c50c15deaf4183e0c42b59b6ba7#diff-21afe91a2d45af3ae84baa20d85ce523R25

@JonBons
Copy link

JonBons commented Mar 29, 2018

Whats the status on this? I have SQF code on gitlab and it would be nice for support for this language to be added. Anything I can help with?

@dedmen
Copy link

dedmen commented May 7, 2018

Same here. I don't see anything stopping this from actually being completed. And we need it for ACE wiki and the SQF blog.

@BaerMitUmlaut
Copy link
Contributor Author

I can use that intercept list then. Is it automatically updated?

@dedmen
Copy link

dedmen commented May 7, 2018

The files are still manually copy-pasted from Arma directory into the repository. But the list itself is generated by Intercept code.

@dedmen
Copy link

dedmen commented May 7, 2018

^ only the intercept list that is. The "AdditionalCommands" list that I linked above is manual.
But seeing as Arma is very close to EOL and with it SQF too I wouldn't worry about new diagnose build only commands that much, because that's essentially all that's in the additionalCommands list.

@BaerMitUmlaut
Copy link
Contributor Author

@gfx I've added a rake task following dedmen's advice. I tried to imitate the existing rake tasks since I don't really know ruby. Please let me know if this looks good to you.

end

def self.commands
load Pathname.new(__FILE__).dirname.join("sqf/commands.rb")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think you forgot to push that file
https://travis-ci.org/jneen/rouge/jobs/381856670#L558

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh rip me

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nobody saw 🤫

Copy link

@dedmen dedmen May 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rake script produces duplicates. Meaning the commands list contains for example diag_log and params which are already in self.diag_commands and self.initializers
Does that create any problems?

Commands are checked last in the list so I guess it's not a problem then.

@BaerMitUmlaut
Copy link
Contributor Author

@gfx @jneen This PR is open since almost a year now, all issues that I know of have been fixed and there are no merge conflicts. Would really like to see this merged :shipit:

@dblessing
Copy link
Collaborator

Thanks @BaerMitUmlaut Sorry for the delay. There are a couple of very minor things that I want to change here but in the interest of getting this merged and not causing you further work and delay, I'm merging and I'll fix those very minor things in another PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants