#A = &CH1 + arcsin ( &CH2 * ln &CH3 )
    
    
    exp ::= "-" exp
    exp ::= "(" exp ")"
    exp ::= exp op exp
    
    op ::= "+" | "-" | "*" | "/" | "^" | and | or | xor
    
    
    #A = &CH1 ^ -( &Ch2 / 10 )
    #B = #A and 0x07 // bit 0-2 of #A
    
    
    exp ::= unop exp
    
    unop ::= arccos | arcsin | arctan | cos | cosh
               | ln | log | sin | sinh | sqr
               | tan | tanh
    
    #A = sqr &CH1
    
    condition ::= exp comp exp
    condition ::= bit comp bit
    condition ::= "(" condition ")"
    condition ::= condition { comb_op condition }
    
    comp ::= "<" | <= | "=" | >= | ">" | <>
    
    bit ::= bitreg | bitvalue
    bitvalue ::= on | off | true | false
    comb_op ::= and | or
    
    
    if #A >= &CH1 - #offset then
      write "     too high     "
    endif
    
    if |CAPTURE_PIN = off and |RECEIVE_READY = true then
      gosub read_serial_data
    endif
    
    
    if (&DISPLAY and 0x00000001) = 0 then
      // display value is even
    endif
    
    
    dim A[] = [ "Hello ", \
                "World" ]
    write A[0] : append A[1]
    
    // if the line contains only the comment
    rem the comment markers don't differ
    write "Hello " // but when preceded with other commands
    append "World" : rem REM needs a separator
    
    
    #A = -100
    let %FloatValue_1 = 100.0
    &CH1 = #A
    
    
    mem &USER_MEMORY_1 = 0
    
    // preset setpoint 1-3
    mem &SETPOINT1[] = [ 1000, 2000, 3000 ]
    
    
    reg &WaterTemperature = &CH1
    bit |Phase_1 = |LED1
    
    
    bitreg &CODE2 = [ ,,,,,, |FREQ_50HZ, |FAST_MODE ]
    
    
    const ButtonTimeout = 40
    const DefaultScaleFactor = 0.125
    
    
    dim A[] = [ "0 Butane", "1 Oxygen", "2 Hydrogen", "3 Nitrogen" ]
    dim B[] = [ 100, 101, 104, 109, 116, 125, 136, 149, 164, 181, 200 ]
    ...
    write A[0]  // this is equivalent to: write "0 Butane"
    
    
if_statement ::= if condition then
                   statement_sequence
               { elsif condition then
                   statement_sequence }
               [ else
                   statement_sequence ]
                 endif
     
    The IF statement can have any number of ELSIF branches but only one ELSE. Please
    note that the ENDIF command is mandatory.
    
    if |SP1 = on then
      &DATA_SOURCE_TOTAL1 = addr(&CH1)
    elsif |SP2 = on then
      &DATA_SOURCE_TOTAL1 = addr(&CH2)
    else
      &DATA_SOURCE_TOTAL1 = 0
    endsel
    
    select_statement ::= select var_regThe SELECT statement allows you to test a register for fixed values. The register can be either integer or floating point and might even be an array index. It needs at least one CASE branch with at least one immediate value as well as the ENDSEL at the end. The optional final DEFAULT case matches any value
case immediate { "," immediate } ":" statement_sequence
{ case immediate { "," immediate } ":" statement_sequence }
[ default: statement_sequence ]
endsel
var_reg ::= var | var "[" exp "]"
    select &PumpState[#curPump]
    case pOFF:
      // do nothing
    case pLOW, pMEDIUM:
      write "Pump" + #curPump
    case pHIGH:
      write "Alarm"
    endsel
    
    
    error:
    |Pump1 = off
    |Pump2 = off
    #state = sERROR
    write "ALARM"
    end
    ...
    select #state
    case pHIGH:
      if &Temperature = FATAL then
        goto error
      endif
    endsel
    
    
    RESET_MACRO:
    &TOTAL1 = 0
    
    reset_cycle:
    #counter = 0
    #cycle = CYCLE_INIT
    end
    
    MAIN_MACRO:
    if |CAPTURE_PIN = on then
      gosub reset_cycle
    endif
 
    ...
    
    
    RESET_MACRO:
    &TOTAL1 = 0
    // last thing to do, so we don't have to get back
    goto reset_cycle
    end
    
    reset_cycle:
    #counter = 0
    #cycle = CYCLE_INIT
    return
    
    MAIN_MACRO:
    if |CAPTURE_PIN = on then
      gosub reset_cycle
    endif
 
    ...
    
    
for_loop ::= for var "=" exp to exp [ step exp ]
               statement_sequence
             next var
    
    The FOR loop uses a counter variable which is initialized (start value) and then
    increased with every NEXT command by the STEP value (default is 1). When the
    counter reached the TO (end) value the loop is terminated and the execution continues
    after the NEXT statement. As long as the counter is between the start and the end
    value the command sequence between FOR and NEXT will be executed.
    
    for #counter = 0 to 31
      &TABLE1_OUTPUT1[#counter] = &USER_MEMORY_1[#counter]
    next #counter
    
    
repeat_loop ::= repeat
                  statement_sequence
                until condition
    
    The REPEAT command leads to a so called non-rejecting loop as it executes the
    command sequence within at least once before checking the condition. If the
    condition is false the loop back to the repeat command and execute the sequence again.
    #digits = MAX_VALUE
    print "&CH1 ="
    repeat
      print " "
      #digits = #digits / 10
    until #digits < &CH1
    print &CH1
    
    
    include "C:\BasicLibrary\SerialProtocol.bas"
    
    
    if &TIMER1 > LOG_TIMEOUT then
      &TIMER1 = 0
      FORCE_LOG
    endif
    
    
    abs_function ::= abs "(" exp ")"
    
    
    #diff = abs(&CH1 - &CH2)
     
    
    addr_function ::= addr "(" var ")"
    
    
    // show the value of #diff on the display
    &DATA_SOURCE_DISPLAY1 = addr(#diff)
     
  	
    asc_function ::= asc "(" """ char """ ")"
    chr_function ::= chr "(" ASCII_int ")"
    
    
    mem &TEXT_CHARACTER_CH1 = asc("T")
    
    print "Hello, World!" + CHR(CR) + CHR(LF)
     
  	
    scale_function ::= scale "(" exp "," table_num ")"
    table_num ::= "1" | "2" | "3" | "4"
    
    
    // apply lintable 2 to the sum of CH1, CH2, and CH3
    #lin_out = scale(&CH1+&CH2+&CH3, 2)
    
    
    append_statement ::= append text_string
    write_statement ::= write text_string
    write_port_statement ::= write const_int text_string
    
    text_string ::= dim_array_name "[" const_int "]"
    text_string ::= const_reg | sub_string { "+" sub_string }
    sub_string ::= quoted_text | var | chr_function
    const_reg ::= var | var "[" const_int "]"
    
    
    dim space[] = [ "   ___", "___   " ]
    const LEADING = 0
    const TRAILING = 1
    
    write "" // interrupt previous message
    write space[LEADING]
    append "Setpoint 1 = " + &SETPOINT1
    append space[TRAILING]
    
    
    write 1 "Hello " // top display
    write 2 "World!" // bottom/default display
    
    
    edit_statement ::= edit constant | edit var_reg
    edit_numeric_statement ::= edit_numeric
    edit_text_statement ::= edit_text dim_array_name []
    exit_edit_statement ::= exit_edit [ var_reg ]
    
    var_reg ::= var | var "[" exp "]"
    
    
    dim ExitEnter[] = [ "  Exit", " Enter" ]
    const mEXIT = 0
    const mENTER = 1
    ...
    MAIN_MACRO:
    if |CAPTURE_PIN = on and &STATE = 0 and &EDIT_STATE = 0 then
      edit mEXIT
      &EDIT_MIN = mEXIT
      &EDIT_MAX = mENTER
      edit_text ExitEnter[]
      &STATE = eENTER_SETUP
    endif
    end
    
    EDIT_MACRO:
    select &STATE
    case eENTER_SETUP:
    exit_edit #temp
    if #temp = mEXIT then
      &STATE = 0
    else
      // continue with next value
    endif
    ...
    endsel
    end
 
    
    
    
    print_statement ::= print text_string
    print_statement ::= print const_reg print_format
    print_port_statement ::= print const_int text_string
    print_port_statement ::= print const_int const_reg print_format
    
    text_string ::= reg_string | sub_string { "+" sub_string }
    sub_string ::= quoted_text | reg | chr_function
    const_reg ::= var | var "[" const_int "]"
    print_format ::= "," const_int [ "," ASCII_int ]
    
    
    print ""  // flush the buffer
    print "Channel 1 = " + &CH1 + chr(CR) + chr(LF)
    
    print 2 "Hello, World!" // print to second port
    
    
    // print CH1 left aligned, 8 chars wide, use '-' to fill up the trailing spaces
    print &CH1, -8, asc("-")
    
  	
    serial_condition ::= serial_input [ const_int ] str_op comp_string [ "+" comp_string ]
    str_op ::= "=" | <>
    comp_string ::= quoted_string | chr_function
    
    
    if SERIAL_INPUT 2 = "SR" then
      // string in serial buffer 2 starts with 'SR'
    endif
     
  	
    parse_func ::= num_func "(" serial_pointer [ const_int ] ["," const_int ] ")"
    
    num_func ::= float | hex | integer
    
    
    // read integer from index 8 to index 13 of buffer 2
    &SERIAL_POINTER2 = 8
    #data = int(serial_pointer 2, 6)
    
    // read float variable from current position in default buffer (port 1)
    %scale = float(serial_pointer)
     
  	
    mb_read ::= modbus_read "(" const_int "," const_int "," var [ "," mb_flag ]")"
    mb_write ::= modbus_write "(" const_int "," var "," const_int [ "," mb_flag ]")"
    
    mb_flag ::= MB_BYTE | MB_SHORT | MB_24 | MB_24_SWAPPED | MB_LONG | MB_LONG_SWAPPED | MB_FLOAT | MB_FLOAT_SWAPPED
    
    
    const TIGER320_RESULT = 40513
    
    MODBUS_MASTER_MACRO:
    |LED1 = off : |LED2 = off
    if #modbus = mbREAD then
      // read CH3 from other Tiger 380
      modbus_read 2 (5, addr(&CH3), &RESULT)
      |LED1 = on
    elsif #modbus = mbWRITE then
      // write to a Tiger 320
      modbus_write 2 (7, &RESULT, TIGER320_RESULT)
      |LED2 = on
    endif
    end