Skip to content

Commit

Permalink
Merge pull request rouge-ruby#761 from BaerMitUmlaut/feature.sqf
Browse files Browse the repository at this point in the history
Add SQF lexer
  • Loading branch information
dblessing authored Aug 10, 2018
2 parents 443c6c5 + 6528ed9 commit ee66b98
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 0 deletions.
14 changes: 14 additions & 0 deletions lib/rouge/demos/sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Creates a dot marker at the given position
#include "script_component.hpp"
params ["_pos", "_txt"];

if (isNil QGVAR(markerID)) then {
GVAR(markerID) = 0;
};

_markerstr = createMarker [QGVAR(marker) + str GVAR(markerID), _pos];
_markerstr setMarkerShape "ICON";
_markerstr setMarkerType "hd_dot";
_markerstr setMarkerText _txt;

GVAR(markerID) = GVAR(markerID) + 1;
113 changes: 113 additions & 0 deletions lib/rouge/lexers/sqf.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# -*- coding: utf-8 -*- #

module Rouge
module Lexers
class SQF < RegexLexer
tag "sqf"
filenames "*.sqf"

title "SQF"
desc "Status Quo Function, a Real Virtuality engine scripting language"

def self.wordoperators
@wordoperators = Set.new %w(
and or not
)
end

def self.initializers
@initializers = Set.new %w(
private param params
)
end

def self.controlflow
@controlflow = Set.new %w(
if then else exitwith switch do case default while for from to step
foreach
)
end

def self.constants
@constants = Set.new %w(
true false player confignull controlnull displaynull grpnull
locationnull netobjnull objnull scriptnull tasknull teammembernull
)
end

def self.namespaces
@namespaces = Set.new %w(
currentnamespace missionnamespace parsingnamespace profilenamespace
uinamespace
)
end

def self.diag_commands
@diag_commands = Set.new %w(
diag_activemissionfsms diag_activesqfscripts diag_activesqsscripts
diag_activescripts diag_captureframe diag_captureframetofile
diag_captureslowframe diag_codeperformance diag_drawmode diag_enable
diag_enabled diag_fps diag_fpsmin diag_frameno diag_lightnewload
diag_list diag_log diag_logslowframe diag_mergeconfigfile
diag_recordturretlimits diag_setlightnew diag_ticktime diag_toggle
)
end

def self.commands
load Pathname.new(__FILE__).dirname.join("sqf/commands.rb")
@commands = self.commands
end

def self.detect?(text)
false
end

state :root do
# Whitespace
rule %r"\s+", Text

# Preprocessor instructions
rule %r"/\*.*?\*/"m, Comment::Multiline
rule %r"//.*\n", Comment::Single
rule %r"#(define|undef|if(n)?def|else|endif|include)", Comment::Preproc
rule %r"\\\r?\n", Comment::Preproc
rule %r"__(EVAL|EXEC|LINE__|FILE__)", Name::Builtin

# Literals
rule %r"\".*?\"", Literal::String
rule %r"'.*?'", Literal::String
rule %r"(\$|0x)[0-9a-fA-F]+", Literal::Number::Hex
rule %r"[0-9]+(\.)?(e[0-9]+)?", Literal::Number::Float

# Symbols
rule %r"[\!\%\&\*\+\-\/\<\=\>\^\|\#]", Operator
rule %r"[\(\)\{\}\[\]\,\:\;]", Punctuation

# Identifiers (variables and functions)
rule %r"[a-zA-Z0-9_]+" do |m|
name = m[0].downcase
if self.class.wordoperators.include? name
token Operator::Word
elsif self.class.initializers.include? name
token Keyword::Declaration
elsif self.class.controlflow.include? name
token Keyword::Reserved
elsif self.class.constants.include? name
token Keyword::Constant
elsif self.class.namespaces.include? name
token Keyword::Namespace
elsif self.class.diag_commands.include? name
token Name::Function
elsif self.class.commands.include? name
token Name::Function
elsif %r"_.+" =~ name
token Name::Variable
else
token Name::Variable::Global
end
end
end

end
end
end
13 changes: 13 additions & 0 deletions lib/rouge/lexers/sqf/commands.rb

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions spec/lexers/sqf_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# -*- coding: utf-8 -*- #

describe Rouge::Lexers::SQF do
let(:subject) { Rouge::Lexers::SQF.new }

describe 'guessing' do
include Support::Guessing

it 'guesses by filename' do
assert_guess :filename => 'foo.sqf'
end
end
end
50 changes: 50 additions & 0 deletions spec/visual/samples/sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Author: BaerMitUmlaut
* Generates and dumps a list of all currently available commands.
* List can be dumped to clipboard or global variable.
*
* Arguments:
* 0: Dump target (clipboard|var:VARNAME) <STRING>
* 1: List delimiter (default: new line) <STRING>
*
* Return Value:
* None
*/

#define SORT_ASC true
#define SORT_DESC false
#define MAKE_UNIQUE(arr) (arr arrayIntersect arr)

params [
["_target", "clipboard", [""]],
["_delimiter", endl, [""]]
];

private _supportInfo = supportInfo "";

// Remove types from list
private _allCommands = _supportInfo select {_x find "t:" == -1};

// Sort commands into categories for processing
private _nulars = _allCommands select {_x find "n:" == 0};
private _unaries = _allCommands select {_x find "u:" == 0};
private _binaries = _allCommands select {_x find "b:" == 0};

// Remove argument types from command description
_nulars = _nulars apply {_x select [2]};
_unaries = _unaries apply {_x select [2]};
_unaries = _unaries apply {_x splitString " " select 0};
_binaries = _binaries apply {_x splitString " " select 1};

// Merge lists
private _commandList = _nulars + _unaries + _binaries;
_commandList = MAKE_UNIQUE(_commandList);
_commandList sort SORT_ASC;

// Dump list
if (_target find "var:" == 0) then {
missionNamespace setVariable [_target select [4], _commandList];
} else {
_commandList = _commandList joinString _delimiter;
copyToClipboard _commandList;
};
37 changes: 37 additions & 0 deletions tasks/sqf.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*- #
require 'open-uri'

def render_sqf_commands
yield "# -*- coding: utf-8 -*- #"
yield "# automatically generated by `rake builtins:sqf`"
yield "module Rouge"
yield " module Lexers"
yield " class SQF < RegexLexer"
yield " def self.commands"
yield " @commands = Set.new %w("
yield " #{fetch_sqf_commands().join(" ")}"
yield " )"
yield " end"
yield " end"
yield " end"
yield "end"
end

def fetch_sqf_commands
url = "https://raw.githubusercontent.com/intercept/intercept/master/src/client/headers/client/sqf_assignments.hpp"
pattern = /(?<=\(").+?(?=")/

open(url) do |f|
f.read.scan(pattern)
end
end

namespace :builtins do
task :sqf do
File.open('lib/rouge/lexers/sqf/commands.rb', 'w') do |f|
render_sqf_commands do |line|
f.puts line
end
end
end
end

0 comments on commit ee66b98

Please sign in to comment.