version 0.6.0
Notus language specification

Functions

recursive integer function mod_nts_language::nts_evaluate_integer_expression (parser)
 Evaluate an integer expression. More...
 
recursive double precision function mod_nts_language::nts_evaluate_double_expression (parser)
 Evaluate a double precision expression. More...
 
recursive character(len=:) function, allocatable mod_nts_language::nts_evaluate_string_expression (parser)
 Evaluate a string precision expression. More...
 
recursive logical function mod_nts_language::nts_evaluate_boolean_expression (parser)
 Evaluate a boolean expression. More...
 
recursive double precision function, dimension(dimension) mod_nts_parse_array::nts_parse_double_array (parser, dimension)
 Parse an array of real numbers. More...
 
recursive integer function, dimension(dimension) mod_nts_parse_array::nts_parse_integer_array (parser, dimension)
 Parse an array of integers. More...
 
recursive subroutine mod_nts_parse_array::nts_parse_double_array_nodimension (parser, array)
 Parse an array of real numbers with undefined dimension. More...
 
recursive subroutine mod_ui_parse_block::ui_parse_block (parser, block_reader)
 Read a new block. More...
 

Detailed Description

Description

# I am a comment
# Declaration of an integer variable
integer three = 3;
# Declaration of a real variable. Note that it is initialized with an expression.
double pi = 2.0*acos(0.0);
# Start a block named 'domain'
domain {
spatial_dimension 2;
}
# Conditions
if (three == 3) {
}

Capabilities:

Basic instructions

Read and evaluate expressions

To read real expression such as

3.0 + cos(0.1*(1.414+sqrt(3.0)))

or integer expression such as

(1 + 7)*4

or boolean expression such as

(a > b) | (b == c)

or string expression such as

"I " + "love " + "notus"

the instructions are:

use mod_nts_language
integer :: integer_value
double precision :: double_value
character(len=:), allocatable :: string_value
logical :: boolean_value
integer_value = nts_evaluate_integer_expression(parser)
double_value = nts_evaluate_double_expression(parser)
string_value = nts_evaluate_string_expression(parser)
boolean_value = nts_evaluate_boolean_expression(parser)
recursive integer function nts_evaluate_integer_expression(parser)
Evaluate an integer expression.
Definition: nts_language.f90:547
recursive logical function nts_evaluate_boolean_expression(parser)
Evaluate a boolean expression.
Definition: nts_language.f90:663
recursive character(len=:) function, allocatable nts_evaluate_string_expression(parser)
Evaluate a string precision expression.
Definition: nts_language.f90:629
recursive double precision function nts_evaluate_double_expression(parser)
Evaluate a double precision expression.
Definition: nts_language.f90:588

Read an integer or real array

To read a 3-dimensional integer array such as

(1, 5+3, 4*4 + 1)

or a 2-dimensional real array

(cos(1.2), sin(1.3))

the instructions are:

use mod_nts_parse_array
integer, dimension(3) :: integer_array
double precision, dimension(2) :: double_array
integer_array = nts_parse_integer_array(parser, 3)
double_array = nts_parse_double_array(parser, 2)
recursive integer function, dimension(dimension) nts_parse_integer_array(parser, dimension)
Parse an array of integers.
Definition: parse_array.f90:94
recursive double precision function, dimension(dimension) nts_parse_double_array(parser, dimension)
Parse an array of real numbers.
Definition: parse_array.f90:60

Manipulate tokens

The following instructions read the next token without consuming it

type(t_token) :: next_token
call nts_peek(parser, next_token)

To ensure that the next token is a semicolon, the following instruction must be used:

call nts_expect(parser, tk_semicolon)

If the next token is not a semicolon, an error is thrown, with, for example, the message: "'semicolon' expected, but got 'keyword'" if the next token is a keyword.

Sometimes, we want only to check if there is specific token without throwing an error. For example, to check if the next token is a comma, the following instruction can be used:

if (nts_next_token(parser, tk_comma)) call notus_log("The next token is a comma", 0)

If we want to check if the next token is a keyword and the keyword is 'domain', there is a special instruction:

if (nts_next_keyword(parser, kw_domain)) call notus_log("The next keyword is 'domain'", 0)

Note that this instruction will return false without throwing any error if the next token is not a keyword.

How to read a block?

A block starts with an opening brace '{', ends with a closing brace '}' and may contains other blocks, variable declarations, loop instruction (while, exit) or conditionals (if, else).

A block defines also a scope for the variable definition, that is a variable declared in a block is available in the current block, in child blocks, but not in parent blocks.

For example, we want to read the following block:

domain {
spatial_dimension 1+1;
}

The parser has already read the keyword 'domain' and the syntax requires that a block must be started. The first thing to do is to ensure that the next token is an opening brace. Then, we start a new scope that begins with the opening brace token. Finally, we start the block reader. The next listing contains the code to start the block reader of the above example:

type(t_token) :: tok_brace
call nts_peek(parser, tok_brace) ! Save the next token into tok_brace
call nts_expect(parser, tk_left_brace) ! Ensure that the next token is an opening brace
call parser%new_scope(tok_brace) ! Start a new scope
call nts_parse_block(parser, ui_parse_domain) ! Read the block with ui_parse_domain

The example block above can be read by the following code:

logical recursive function ui_parse_domain(parser, tok, keyword_id) result(keyword_id_found)
use variable_domain ! Import variables from the library
type(t_parser) :: parser ! Current parser
type(t_token), intent(in) :: tok ! Current token
integer, intent(in) :: keyword_id ! Current token id
type(t_token) :: tok_brace
keyword_id_found = .true.
select case(keyword_id)
case(kw_spatial_dimension)
spatial_dimension = nts_evaluate_integer_expression(parser)
if (spatial_dimension < 2 .or. spatial_dimension > 3) then
call parser%throw_error(tok, "spatial_dimension must be equal to 2 or 3")
end if
call nts_expect(parser, tk_semicolon)
case default
keyword_id_found = .false.
end select
end function ui_parse_domain

Usage

Organisation:

Concepts:

Function Documentation

◆ nts_evaluate_boolean_expression()

recursive logical function mod_nts_language::nts_evaluate_boolean_expression ( type(t_parser parser)

This routine evaluate expressions such as:

(cos(4.1*3.5) > sin(2.2/3.7)) & (2 > 3)

◆ nts_evaluate_double_expression()

recursive double precision function mod_nts_language::nts_evaluate_double_expression ( type(t_parser parser)

This routine evaluate expressions such as:

cos(7.0*3.5)+tan(0.2/1.4)

◆ nts_evaluate_integer_expression()

recursive integer function mod_nts_language::nts_evaluate_integer_expression ( type(t_parser parser)

This routine evaluate integer expressions such as:

2*(5+3) - 8/(2+2)

If the expression contains real number, they will be converted in integers at the evaluation.

◆ nts_evaluate_string_expression()

recursive character(len=:) function, allocatable mod_nts_language::nts_evaluate_string_expression ( type(t_parser parser)

This routine evaluate expressions such as:

"I love" + " Notus"

◆ nts_parse_double_array()

recursive double precision function, dimension(dimension) mod_nts_parse_array::nts_parse_double_array ( type(t_parser parser,
integer, intent(in)  dimension 
)

Read a double precision array of dimension dimension. Return an array of the required dimension.

 (<double expression>, <double expression>,..., <double expression>)
  <--------------------------------------------------------------->
               dimension double precision expressions
Parameters
parsercurrent parser
dimensionrequired dimension

◆ nts_parse_double_array_nodimension()

recursive subroutine mod_nts_parse_array::nts_parse_double_array_nodimension ( type(t_parser parser,
double precision, dimension(:), intent(inout), allocatable  array 
)

Read a double precision array of unknown dimension. Return an array of the dimension .

 (<double expression>, <double expression>,...)
  <------------------------------------------>
      dimension double precision expressions
Parameters
parsercurrent parser

◆ nts_parse_integer_array()

recursive integer function, dimension(dimension) mod_nts_parse_array::nts_parse_integer_array ( type(t_parser parser,
integer, intent(in)  dimension 
)

Read an integer array of dimension dimension. Return an array of the required dimension.

 (<integer expression>, <integer expression>,..., <integer expression>)
  <------------------------------------------------------------------>
                    dimension integer expressions
Parameters
parsercurrent parser
dimensionrequired dimension

◆ ui_parse_block()

recursive subroutine mod_ui_parse_block::ui_parse_block ( type(t_parser parser,
procedure(block_function)  block_reader 
)

A block starts with an opening brace '{' and ends with a closing brace '}'.

In a block, a user may define variables, start a new block, use controle structures (loops, if, else, etc.) and use authorized keywords. Authorized keyword are defined by a specific block reader.

A block reader is a routine with a specific interface:

logical recursive function block_reader(parser, tok, keyword_id)

Where:

  • parser is the current parser
  • tok is the keyword token being read
  • keyword_id is the keyword id of tok
Parameters
parsercurrent parser
block_readerroutine containing