All Projects → LordGolias → sqf

LordGolias / sqf

Licence: BSD-3-Clause license
Parser, static analyzer and interpreter of SQF (Arma programming language)

Programming Languages

python
139335 projects - #7 most used programming language

Labels

Projects that are alternatives of or similar to sqf

Asl
Arma Scripting Language - a clean scripting language compiling to Arma 3 SQF scripts.
Stars: ✭ 20 (-70.15%)
Mutual labels:  arma3
Acre2
Advanced Combat Radio Environment 2 (ACRE2) for Arma 3
Stars: ✭ 161 (+140.3%)
Mutual labels:  arma3
CLib
CLib is a Function/Script Library for ArmA 3
Stars: ✭ 22 (-67.16%)
Mutual labels:  arma3
Domination
Domination - A MP mission for Arma 3
Stars: ✭ 45 (-32.84%)
Mutual labels:  arma3
Armake
A C implementation of Arma modding tools (PAA conversion, binarization/rapification, PBO packing). (WIP)
Stars: ✭ 82 (+22.39%)
Mutual labels:  arma3
X3daudio1 7 hrtf
HRTF for Arma 3, Skyrim, and other titles that use XAudio2 + X3DAudio
Stars: ✭ 192 (+186.57%)
Mutual labels:  arma3
Poppy
A reliable, self configuring, error finding loadout framework for Arma.
Stars: ✭ 6 (-91.04%)
Mutual labels:  arma3
PboViewer
Cross-platform PBO maker / unpacker
Stars: ✭ 28 (-58.21%)
Mutual labels:  arma3
Arma Server Web Admin
Web based server manager for Arma
Stars: ✭ 84 (+25.37%)
Mutual labels:  arma3
LambsDanger
AI enhancement mod for Arma 3
Stars: ✭ 88 (+31.34%)
Mutual labels:  arma3
A3 Antistasi
A3-Antistasi is the new official Antistasi version
Stars: ✭ 71 (+5.97%)
Mutual labels:  arma3
Acex
ACE3 Extra misc modules and components
Stars: ✭ 82 (+22.39%)
Mutual labels:  arma3
Kp Liberation
The work on GreuhZbugs Liberation Mission for Arma 3 continues...
Stars: ✭ 196 (+192.54%)
Mutual labels:  arma3
Hemtt
Build System for Arma 3
Stars: ✭ 43 (-35.82%)
Mutual labels:  arma3
diwako dui
A UI showing unit positions and names of units in your squad
Stars: ✭ 39 (-41.79%)
Mutual labels:  arma3
Arma3launcherlib
Simple .NET library containing everything needed for a custom Arma 3 launcher.
Stars: ✭ 7 (-89.55%)
Mutual labels:  arma3
Intercept
A C/C++ Binding Library for SQF and RV Engine Access Abstraction Layer
Stars: ✭ 191 (+185.07%)
Mutual labels:  arma3
A3ExtendedChat
Adds new functionality to the Arma 3 chat system with emojis, history viewer, message filters and commands!
Stars: ✭ 16 (-76.12%)
Mutual labels:  arma3
Pythia
An extension for Arma 3 that lets you write extensions in Python 3
Stars: ✭ 50 (-25.37%)
Mutual labels:  arma3
Framework
Altis Life RPG mission framework for Arma 3 originally made by @TAWTonic.
Stars: ✭ 224 (+234.33%)
Mutual labels:  arma3

Build Status Coverage Status

SQF linter

This project contains a parser, static analyzer and interpreter for SQF (Arma scripting language), written in Python. It can be used to:

  • syntax-check and static analyze SQF files and projects
  • execute SQF on a limited virtual environment

Problem it solves

One of the major bottlenecks of scripting in SQF is the time spent testing it in-game, by running the game.

Often, these scripts contain errors (missing ";", wrong usage of params) that everyone would love to find without restarting the mission.

This package allows to parse SQF to check for syntactic errors, wrong types, problems in variables scopes, and many more subtle issues of SQF.

Analyzer examples

>>> code = 'if (true) {1}'
>>> errors = sqf.analyzer.analyze(sqf.parser.parse(code))
>>> errors[0]
SQFParserError((1, 11), "'(true)' can't preceed '{1}' (missing ';'?)")

>>> code = 'private _y = _z'
>>> analyzer = sqf.scope_analyzer.interpret(sqf.parser.parse(code))
>>> analyzer.exceptions[0]
SQFWarning((1, 14), 'Local variable "_z" is not from this scope (not private)')

Parser example

Behind the curtains, the analyzer uses a parser to convert SQF code in a set of statements:

>>> code = '[1, 2, 3]'
>>> sqf.parser.parse(code)
Statement([Statement([
    Array([Statement([N(1)]), Statement([Space(), N(2)]), Statement([Space(), N(3)])])
])])

Interpreter example

The interpreter is able to run scripts on an emulated (and limited) environment. The interpreter is obviously not intended to run Arma simulation; it is aimed for you, moder, run tests of your scripts (e.g. Unit Tests) without having to run the game.

from sqf.interpreter import interpret
interpreter, outcome = interpret('_x = [1, 2]; _y = _x; reverse _y;')
# outcome equals to "Nothing"
# interpreter['_y'] equals to Array([Number(2), Number(1)])
# interpreter['_x'] equals to Array([Number(2), Number(1)])  # <= _y is a reference

Requirements and installation

This code is written in Python 3 and has no dependencies. You can install it using

pip3 install sqflint

Tests and coverage

The code is heavily tested (coverage 98%+), and the tests can be found in tests. Run them using standard Python unittest:

python -m unittest discover

Compatibility with editors

This package is compatible with known editors, and can be used to efficiently write SQF with them. See the respective projects for more details:

Code organization

This code contains essentially 4 components, a tokenizer, a parser, analyzer and interpreter:

Interpreter

The interpreter is a class that executes parsed scripts. It receives a Statement and executes it as per described in the Arma 3' wiki. To automatically initialise the interpreter and execute code, run interpret:

>>> from sqf.interpreter import interpret
>>> script = '''
a = 0;
b = true;
for [{_i = 0}, {_i < 10 && b}, {_i = _i + 1}] do {
    a = a + 1;
    if (a >= 7) then {b = false}
}
'''
>>> interpreter, outcome = interpret(script)
>>> interpreter['a']
Number(7)
>>> outcome
Boolean(False)

The call interpreter['a'] returns the outermost Scope of the Namespace "missionNamespace", but you can use setVariable and getVariable to interact with other namespaces. sqf.tests.test_interpreter contains the tests of the implemented functionality.

The source is in sqf/interpreter.py, the tests in tests/test_interpreter.py. The main loop of the interpreter is defined in sqf/interpreter.py, and the expressions it evaluates are defined in sqf/expressions.py.

Analyzer

The analyzer consumes the result of the parser and checks for static errors. The source is in sqf/analyzer.py, the tests in tests/test_analyzer.py.

Parser

The parser transforms a string into a nested Statement, i.e. a nested list of instances of types, operators, and keywords defined in SQF. For example,

>>> from sqf.parser import parser
>>> script = '_x=2;'
>>> result = parse(script)
>>> result
Statement([Statement([Variable('_x'), Keyword('='), Number(2)], ending=';')])
>>> script == str(result) # True

This rather convolved result takes into account operator precedence and the meaning of the different parenthesis ([], {}, ()). To transform the script into tokens used in the parser, the tokenizer is called. sqf.tests.test_parser contains the tests.

Tokenizer

The tokenizer transforms a string into a list of tokens split by the relevant tokens of SQF. E.g.

>>> from sqf.base_tokenizer import tokenize
>>> tokenize('/*_x = 1;*/')
['/*', '_x', ' ', '=', ' ', '1', ';', '*/']

The source can be found in sqf.base_tokenizer.

Licence

This code is licenced under BSD.

Author

This code was written by Lord Golias, [email protected]

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].