# Expression Syntax

The scripting language allows expressions to do calculations with variables.

## Expression Definition

An expression combines any number of numbers, strings, variables, and functions with operators. An expression evaluates to a numeric or string value. The general, recursive definition of an expression is:

[EXPRESSION] = [sign] [ATOMIC] [op] [ATOMIC] [op] [ATOMIC] ... [op] [ATOMIC]

where

`[sign]`is an optional leading sign of`+`or`-``[op]`are operators that determine how the`[ATOMIC]`'s are combined. The options are:`+`for addition`-`for subtraction`*`for multiplication`/`for division`^`for raising to a power`&`for string concatenation

`^`followed by`*`and`/`followed by`+`and`-`. When there are multiple operators of the same precedence, they are evaluated left to right. In string expressions, all top-level`[op]`'s must be for concatenation (`&`), although any`[ATOMIC]`can be a numeric expression enclosed in parentheses.`[ATOMIC]`are the elements that are combined. The possible atomics are:- An unsigned number (23, 2.234, 3e2, 4.56e-3, ...).
^{2} - A variable (such as
`#varname`,`#x[2]`,`#z[#i][#j]`,*etc.*) and the value of the variable is used. The variable must have been previously defined. - Text in quotes ("some text") and the value is the text after the quotes are removed.
- Unquoted text and the value is all the text between the operators after all spaces have been removed. To include spaces in text
`[ATOMIC]`'s, the text must be quoted. - Another expression in parenthesis or
`([EXPRESSION])`and the value of the`[ATOMIC]`is the value of the included expression. - A function of an expression (such as
`sin([EXPRESSION])`) and the value of the`[ATOMIC]`is the value of the function applied to the value of the expression. The allowed functions are listed below. - An "at" expression beginning in an
`@`sign and containing specific items separated by periods, such as "`@key.TopLeft.x`" to evaluate to the x value of the keypoint named`TopLeft`.- The available "at" expressions are defined elsewhere (for example, see Keypoint Command and Path Command).
- Any of the period-delimited items can be a variable (such as
`@key.#kname.x`) and the contents of`#kname`will replace that item in the expression. - Variables used as items can only be a single variable and not an expression. They also cannot be an array variable with a variable index (
*e.g.*, it can be`#n[3]`but cannot be`#n[#i]`). Hint: if you need to index an array with a variable, you can define simple variable first (*e.g.*,`#ni=#n[#i]`) and then use that in an expression (*e.g.*,`@key.#ni.y`).

- An unsigned number (23, 2.234, 3e2, 4.56e-3, ...).

## Supported Functions

### Numeric Functions

The following numeric functions are supported in both NairnFEAMPM and NairnFEAMPMViz:

`sin()`- sine of argument in radians`cos()`- cosine of argument in radians`tan()`- tangent of argument in radians`asin()`- inverse sine with result in radians`acos()`- inverse cosine with result in radians`atan()`- inverse tangent with result in radians`sinh()`- hyperbolic sine`cosh()`- hyperbolic cosine`tanh()`- hyperbolic tangent`erf()`- error function`erfc()`- error function complement`exp()`- exponential`log()`- natural log`log10()`- log base 10`sqrt()`- square root`abs()`- absolute value`int()`- integer part`sign(x)`- 1 if x is positive or 0 if it is negative`sgn(x)`- -1 if x <0, 0 if x=0, and +1 if x>0`ramp(A,x)`- 0 if x< 0, Ax if 0<x<1, A if x>1`cosramp(A,x)`- 0 if x< 0, (A/2)(1-cos(πx)) if 0<x<1, A if x>1`box(A,x)`- 0 if x< 0, A if 0<x<1, 0 if x>1`sinbox(A,x)`- 0 if x< 0, A sin(πx) if 0<x<1, 0 if x>1`tri(x)`- 1-|x| for -1 < x < 1, 0 otherwise`mod(A,x)`- remainder of A/x and workings with non-integer values (useful for creating periodic functions)`rand(x)`- a random number between 0 and x.`cdfinv(x)`- find inverse of the cumulative distribution function. For a random variable*Z*with mean*m*and standard deviation σ, the value of*x*such that the probability that*Z*<*x*is*p*is equal to*x*=*m*+σ*`cdfinv(p)`.

### String Functions

Each string function takes a single string expression as an argument. Some functions embed sub-arguments delimited by back slashes within the evaluated single string expression. The following string functions are supported in both NairnFEAMPM and NairnFEAMPMViz:

`length()`- number of characters in a string.`words()`- number of words in a string.`firstWord()`- first word in a string.`lastWord()`- last word in a string.`removeFirstWord()`- string with first word removed.`removeLastWord()`- string with last word removed.`trim()`- string with leading and trailing white space removed.`chars(c1\c2\string)`- returns characters`c1`to`c2`(inclusive) of`string`(the first character is character 1). If omitted,`c1`and`c2`default to 1 and length of`string`, respectively. Thus`char(c1\string)`gets character 1 to the end and`char(\c2\string)`gets character 1 through`c2`. Either`c1`or`c2`can be <=0 to indicate character number relative to end of the string (*e.g.*, 0 is last character, -1 is next to last,*etc.*)`word(w1\string)`- rreturns word`w1`of`string`. If`w1<=0`, it specifies word number relative to end of the string (*e.g.*, 0 is last word, -1 is next to last,*etc.*).`offset(s1\c1\string)`- returns offset of string`s1`in string at or after character`c1`(the first character is character 1) or returns 0 if string`s1`is not found.`c1 can`be omitted to find`s1`any place in`string`

. The search is case insensitive.`replace(s1\s2\string)`- returns string where all occurrences of string`s1`in`string`are replaced with string`s2`.`s2`may be omitted to delete all occurrences of string`s1`.`upperCase()`- convert string to upper case.`lowerCase()`- convert string to lower case.`titleCase()`- convert to string with capitalized words.

To omit first subargument in `chars()`, `offset()`, or `replace()`, start with a back slash (*e.g.*, `chars(\c2\string)`). To omit second argument, you can either omit it and its backslash (*e.g.*, `chars(c1\string)`), but if `string` might contain a backslash, it is better to just omit the subargument (*e.g.*, `chars(c1\\string)`).

## Notes

- An assignment command can be combined with an operator as in
#x [op]= [EXPRESSION]

which is equivalent to

#x = #x [op] ([EXPRESSION])

provided the variable is already a defined variable. It is an error if the variable has not previously been defined.