{"name":"SQF Syntax","title":"SQF Syntax","type":"topic","url":"https://community.bistudio.com/wiki/SQF_Syntax","revid":363899,"updated":"2024-04-24T15:51:27Z","aliases":["*/","/*","/**/","//","SQF","SQF syntax","sqf"],"markdown":"**SQF** stands for **S**tatus **Q**uo **F**unction - a successor of **S**tatus **Q**uo **S**cript, which is deprecated since Armed Assault but could still be used in Arma 3.\nSQF was first introduced in Operation Flashpoint: Resistance together with the call operator in update 1.85.\n\n- \"Status Quo\" was a code name for [Operation Flashpoint](https://en.wikipedia.org/wiki/Operation_Flashpoint)\n- \"Combined Arms\" was a code name for [Arma](https://en.wikipedia.org/wiki/ARMA_(series))\n- \"Futura\" was a code name for [Arma 3](https://en.wikipedia.org/wiki/ARMA_3).\n\nThe SQF Language is fairly simple in how it is built.\nIn fact: there are barely any actual language structures at all.\n\nThe functionality is provided via so called *operators* (or more commonly known scripting commands).\nThose operators are one of the following types: Nular [sic], Unary, or Binary.\n\n### Terminating an expression\n\nAn SQF expression has to be terminated via either `;` (preferred by convention!) or `,`.\n\n```sqf\n_num = 10;\n_num = _num + 20; systemChat str _num;\n```\n\nIn the above example, there are three expressions:\n1. `_num = 10`\n1. `_num = _num + 20`\n1. `systemChat str _num`\nAll are separated by `;` and not the line return - they could all be inlined and it would not impact the code.\n\n### Brackets\n\n- `()` - Round brackets are used to override the default Order of Precedence or improve legibility.\n- `[]` - Square brackets define Arrays.\n- `{}` - Curly brackets enclose instances of the Code Data Type. They are also used in Control Structures.\n\n### Whitespaces\n\nWhitespace consists of tabs and/or space characters.\n\n For the\n  purposes of the\n    engine\n      The 'line' begins at the first non whitespace character.\n\nSimilarly, trailing whitespace at the end of a line or statement is also ignored.\n\n### Blank Lines\n\nBlank lines are lines containing nothing but whitespace and are therefore ignored by the engine.\n\n### Comments\n\nA comment is additional text that gets ignored when a script is parsed.\nThey serve as future reference and are often used to explain a specific part of the code.\n\nIn SQF, there are two kind of comments:\n\n```sqf\n// in-line comment that ends on new line\n\n/* block comment that can span above multiple lines\nand ends on the following character combination: */\n```\n\nA comment can occur anywhere but inside a string.\nFor example, the following would be valid:\n\n```sqf\n1 + /* some random comment in an expression */ 1\n```\n\nIt should be mentioned that there is a comment unary operator that should not be used as it will actually be executed (thus taking time to execute) but does nothing besides consuming a string.\nThere is no benefit in using it and the reason it exists is solely for backward compatibility.\nAnother way to make a *comment* that way, is to just place a string: `/* some code */ \"I can be considered as a comment but should not be used\"; /* some other code */`\n\n*Comments are removed during the preprocessing phase.* This is important to know as that prevents usage in e.g a string that gets compiled using the compile unary operator or when only using loadFile.\n\n### Nular Operators\n\nA nular [sic] operator is more or less a computed variable. Each time accessed, it will return the current state of something.\nIt is tempting to think of a nular [sic] operator as nothing more but a magic global variable, but it is important to differentiate!\n\nConsider following example in a mission with e.g. 5 units:\n\n```sqf\n// put the result of allUnits into a Variable\n_unitsArray = allUnits;\n\n// display the current Array size using systemChat\nsystemChat str count _unitsArray;\n\n// create a new unit in the player group\ngroup player createUnit [\"B_RangeMaster_F\", getPosATL player, [], 0, \"NONE\"];\n\n// output the Array size again\nsystemChat str count _unitsArray;\n\n// output the size of allUnits\nsystemChat str count allUnits;\n```\n\nNow, what would the output of this look like?\n System: 5\n System: 5\n System: 6\n\nAs you can see, `_unitsArray` was not automatically updated as it would have been if it was not generated each time. If allUnits was just a global variable with a reference to some internal managed array, our private variable should have had reflected the change as value types are passed by reference.\nThe reason for this is because allUnits and other nular [sic] operators just return the current state of something and do not return a reference to eg. an array containing all units.\nIt is generated each time, which is why some of theese operators are more expensive to run then *just* using a variable.\n\n### Unary Operators\n\nThe unary operators are operators that expect an argument on their right side (`unary <argument>`). They always will take the first argument that occurs.\n\nA common mistake would be the following:\n\n```sqf\n// create some Array containing three arrays\n_arr = [[1, 2, 3, 4, 5], [1, 2, 3, 4], [1, 2]];\n\n// wrongly use the select operator to get the count of the third array\ncount _arr select 2; // error\n```\n\nNow, what went wrong?\n\nLet's put some brackets in the right places to make the mistake understandable:\n\n```sqf\n(count _arr) select 2; // error\n```\n\nDue to the nature of unary operators, count instantly consumes our variable *_arr* and returns the number *3*.\nThe *3* then is passed to select which does not knows what to do with a number as left argument and thus errors out.\n\nTo do it correctly, one would have to put the `_arr select 2` in brackets.\nThe correct code thus would be:\n\n```sqf\n// create an array containing three Arrays\n_arr = [[1, 2, 3, 4, 5], [1, 2, 3, 4], [1, 2]];\n\n// use brackets to correctly get count of the third Array\ncount (_arr select 2); // good :) will evaluate to 2\n```\n\n### Binary Operators\n\nBinary operators expect two arguments (`<1st argument> binary <2nd argument>`) and are executed according to their #precedence. If their precedence is equal, they are executed left to right.\n\nAs example, we will look into the following expression:\n\n```sqf\n// create a nested Array with 5 levels\n_arr = [[[[[1]]]]];\n\n// receive the nested number with some random math expressions\n_arr select 0 select 1 - 1 select 15 / 3 - 5 select 0 select 10 * 10 + 4 * 0 - 100 // evaluates to 1\n```\n\nNow, let us analyze why this is happening for the first few expressions:\n1. _arr is loaded\n1. 0 is loaded\n1. select is executed with the result of 1. & 2.\n1. 1 is loaded\n1. 1 is loaded\n1. - is executed with the result of 4. & 5.\n1. select is executed with the result of 3. & 6.\n1. ...\n\nIf we now would put brackets at the correct spots, the expression will get clearer:\n\n```sqf\n((((_arr select 0) select (1 - 1)) select ((15 / 3) - 5)) select 0) select (((10 * 10) + (4 * 0)) - 100)\n```\n\nAs you can see the `*` and `/` are executed first which matches their precedence.\nAfterward, the `+` and `-` operators will get executed followed by our select operator, which are executed from the left to the right.","sections":[{"heading":null,"level":1,"markdown":"**SQF** stands for **S**tatus **Q**uo **F**unction - a successor of **S**tatus **Q**uo **S**cript, which is deprecated since Armed Assault but could still be used in Arma 3.\nSQF was first introduced in Operation Flashpoint: Resistance together with the call operator in update 1.85.\n\n- \"Status Quo\" was a code name for [Operation Flashpoint](https://en.wikipedia.org/wiki/Operation_Flashpoint)\n- \"Combined Arms\" was a code name for [Arma](https://en.wikipedia.org/wiki/ARMA_(series))\n- \"Futura\" was a code name for [Arma 3](https://en.wikipedia.org/wiki/ARMA_3).\n\nThe SQF Language is fairly simple in how it is built.\nIn fact: there are barely any actual language structures at all.\n\nThe functionality is provided via so called *operators* (or more commonly known scripting commands).\nThose operators are one of the following types: Nular [sic], Unary, or Binary."},{"heading":"Terminating an expression","level":3,"markdown":"An SQF expression has to be terminated via either `;` (preferred by convention!) or `,`.\n\n```sqf\n_num = 10;\n_num = _num + 20; systemChat str _num;\n```\n\nIn the above example, there are three expressions:\n1. `_num = 10`\n1. `_num = _num + 20`\n1. `systemChat str _num`\nAll are separated by `;` and not the line return - they could all be inlined and it would not impact the code."},{"heading":"Brackets","level":3,"markdown":"- `()` - Round brackets are used to override the default Order of Precedence or improve legibility.\n- `[]` - Square brackets define Arrays.\n- `{}` - Curly brackets enclose instances of the Code Data Type. They are also used in Control Structures."},{"heading":"Whitespaces","level":3,"markdown":"Whitespace consists of tabs and/or space characters.\n\n For the\n  purposes of the\n    engine\n      The 'line' begins at the first non whitespace character.\n\nSimilarly, trailing whitespace at the end of a line or statement is also ignored."},{"heading":"Blank Lines","level":3,"markdown":"Blank lines are lines containing nothing but whitespace and are therefore ignored by the engine."},{"heading":"Comments","level":3,"markdown":"A comment is additional text that gets ignored when a script is parsed.\nThey serve as future reference and are often used to explain a specific part of the code.\n\nIn SQF, there are two kind of comments:\n\n```sqf\n// in-line comment that ends on new line\n\n/* block comment that can span above multiple lines\nand ends on the following character combination: */\n```\n\nA comment can occur anywhere but inside a string.\nFor example, the following would be valid:\n\n```sqf\n1 + /* some random comment in an expression */ 1\n```\n\nIt should be mentioned that there is a comment unary operator that should not be used as it will actually be executed (thus taking time to execute) but does nothing besides consuming a string.\nThere is no benefit in using it and the reason it exists is solely for backward compatibility.\nAnother way to make a *comment* that way, is to just place a string: `/* some code */ \"I can be considered as a comment but should not be used\"; /* some other code */`\n\n*Comments are removed during the preprocessing phase.* This is important to know as that prevents usage in e.g a string that gets compiled using the compile unary operator or when only using loadFile."},{"heading":"Nular Operators","level":3,"markdown":"A nular [sic] operator is more or less a computed variable. Each time accessed, it will return the current state of something.\nIt is tempting to think of a nular [sic] operator as nothing more but a magic global variable, but it is important to differentiate!\n\nConsider following example in a mission with e.g. 5 units:\n\n```sqf\n// put the result of allUnits into a Variable\n_unitsArray = allUnits;\n\n// display the current Array size using systemChat\nsystemChat str count _unitsArray;\n\n// create a new unit in the player group\ngroup player createUnit [\"B_RangeMaster_F\", getPosATL player, [], 0, \"NONE\"];\n\n// output the Array size again\nsystemChat str count _unitsArray;\n\n// output the size of allUnits\nsystemChat str count allUnits;\n```\n\nNow, what would the output of this look like?\n System: 5\n System: 5\n System: 6\n\nAs you can see, `_unitsArray` was not automatically updated as it would have been if it was not generated each time. If allUnits was just a global variable with a reference to some internal managed array, our private variable should have had reflected the change as value types are passed by reference.\nThe reason for this is because allUnits and other nular [sic] operators just return the current state of something and do not return a reference to eg. an array containing all units.\nIt is generated each time, which is why some of theese operators are more expensive to run then *just* using a variable."},{"heading":"Unary Operators","level":3,"markdown":"The unary operators are operators that expect an argument on their right side (`unary <argument>`). They always will take the first argument that occurs.\n\nA common mistake would be the following:\n\n```sqf\n// create some Array containing three arrays\n_arr = [[1, 2, 3, 4, 5], [1, 2, 3, 4], [1, 2]];\n\n// wrongly use the select operator to get the count of the third array\ncount _arr select 2; // error\n```\n\nNow, what went wrong?\n\nLet's put some brackets in the right places to make the mistake understandable:\n\n```sqf\n(count _arr) select 2; // error\n```\n\nDue to the nature of unary operators, count instantly consumes our variable *_arr* and returns the number *3*.\nThe *3* then is passed to select which does not knows what to do with a number as left argument and thus errors out.\n\nTo do it correctly, one would have to put the `_arr select 2` in brackets.\nThe correct code thus would be:\n\n```sqf\n// create an array containing three Arrays\n_arr = [[1, 2, 3, 4, 5], [1, 2, 3, 4], [1, 2]];\n\n// use brackets to correctly get count of the third Array\ncount (_arr select 2); // good :) will evaluate to 2\n```"},{"heading":"Binary Operators","level":3,"markdown":"Binary operators expect two arguments (`<1st argument> binary <2nd argument>`) and are executed according to their #precedence. If their precedence is equal, they are executed left to right.\n\nAs example, we will look into the following expression:\n\n```sqf\n// create a nested Array with 5 levels\n_arr = [[[[[1]]]]];\n\n// receive the nested number with some random math expressions\n_arr select 0 select 1 - 1 select 15 / 3 - 5 select 0 select 10 * 10 + 4 * 0 - 100 // evaluates to 1\n```\n\nNow, let us analyze why this is happening for the first few expressions:\n1. _arr is loaded\n1. 0 is loaded\n1. select is executed with the result of 1. & 2.\n1. 1 is loaded\n1. 1 is loaded\n1. - is executed with the result of 4. & 5.\n1. select is executed with the result of 3. & 6.\n1. ...\n\nIf we now would put brackets at the correct spots, the expression will get clearer:\n\n```sqf\n((((_arr select 0) select (1 - 1)) select ((15 / 3) - 5)) select 0) select (((10 * 10) + (4 * 0)) - 100)\n```\n\nAs you can see the `*` and `/` are executed first which matches their precedence.\nAfterward, the `+` and `-` operators will get executed followed by our select operator, which are executed from the left to the right."}],"categories":["Syntax"],"groups":["Scripting"]}