|
subroutine | mod_parser::parser_initialize (parser, filename, keywords) |
| Initialize the parser. More...
|
|
subroutine | mod_parser::parser_finalize (parser) |
| Finalize the parser. More...
|
|
subroutine | mod_parser::parser_new_scope (parser, tok, kind) |
| Start a new scope. More...
|
|
subroutine | mod_parser::parser_pop_scope (parser, tok) |
| Remove the scope at the top of the scope stack. More...
|
|
subroutine | mod_parser::parser_reset_scope (parser) |
| Reset the parser to the beginning of the scope. More...
|
|
subroutine | mod_parser::parser_get_identifier_type (parser, tok, id_kind) |
| Find the type of an identifier. More...
|
|
logical function | mod_parser::parser_is_identifier_defined (parser, tok) |
| Check if a given identifier is defined. More...
|
|
subroutine | mod_parser::parser_add_identifier (parser, tok, intgr, dbl, bool, string) |
| Add an identifier to the current scope. More...
|
|
integer function | mod_parser::parser_get_integer_identifier (parser, tok) |
| Get the value of an integer identifier. More...
|
|
double precision function | mod_parser::parser_get_double_identifier (parser, tok) |
| Get the value of a double identifier. More...
|
|
logical function | mod_parser::parser_get_boolean_identifier (parser, tok) |
| Get the value of a boolean identifier. More...
|
|
character(len=:) function, allocatable | mod_parser::parser_get_string_identifier (parser, tok) |
| Get the value of a string identifier. More...
|
|
subroutine | mod_parser::parser_get (parser, tok) |
| Get the next token. More...
|
|
subroutine | mod_parser::parser_peek (parser, tok) |
| Get the next token but not consume it. More...
|
|
subroutine | mod_parser::parser_unget (parser, tok) |
| Unget a token. More...
|
|
logical function | mod_parser::parser_next_token (parser, kind, peek) |
| Check if the next token is of a specific kind. More...
|
|
logical function | mod_parser::parser_next_keyword (parser, keyword_id) |
| Check if the next token is a keyword of a specific kind. More...
|
|
subroutine | mod_parser::parser_expect (parser, kind, has_leading_space, message) |
| Ensure that the next token is of a specific kind. More...
|
|
subroutine | mod_parser::parser_throw_error (parser, tok, message) |
| Display an error message. More...
|
|
Brief description
Let us recall the lexer/parser organization with the 3 main units:
keyword list
v
┌──────────┐ ┌───────────┐ ┏━━━━━━━━━━━━┓
files │ │ characters │ │ tokens ┃ ┃ ───────>
─────> │ File │ ──────────>│ Lexer │ ───────> ┃ Parser ┃ tokens / actions
│ │ │ │ ┃ ┃ <───────
└──────────┘ └───────────┘ ┗━━━━━━━━━━━━┛
mod_source_file mod_lexer mod_parser
mod_identifier
mod_scope
Usage
A complete usage of the parser can be found in the OBJ Wavefront reader code.
Let us consider the source code example of the lexer section with the file example.txt
:
# Print a message to screen
print "I love Notus <3";
# Compute the square of 42 an print the result to screen
square 42;
Specifications:
- A comment line starts with a '#'
- An instruction line must ends with ';' (tk_semicolon)
- The language has two keywords with the following syntax:
- 'print':
print tk_string tk_semicolon
- 'square':
square tk_integer tk_semicolon
The following code read the source file and execute the instructions.
type(t_parser) :: parser
type(t_keyword_name), dimension(2) :: keywords
type(t_token) :: tok, next_tok
keywords(kw_print )%name = "print"
keywords(kw_square)%name = "square"
call parser_initialize(parser, "example.txt", keywords)
do
call parser%get(tok)
select case(tok%kind)
case(tk_eof)
write(*,'("EOF")')
exit
case(tk_keyword)
select case(tok%keyword_id)
case(kw_print)
call parser%get(next_tok)
if (next_tok%kind /= tk_string) call parser%throw_error(next_tok, "'print' keyword requires a string")
call parser%expect(tk_semicolon)
write(*,'(a)') next_tok%string_value
case(kw_square)
call parser%get(next_tok)
if (next_tok%kind /= tk_integer) call parser%throw_error(next_tok, "'square' keyword requires an integer")
call parser%expect(tk_semicolon)
write(*,'(g0)') next_tok%integer_value**2
end select
case default
call parser%throw_error("Forbidden token '"//trim(token_id_to_string(tok%kind))//"'")
end select
end do
Expected output:
◆ parser_add_identifier()
subroutine mod_parser::parser_add_identifier |
( |
class(t_parser) |
parser, |
|
|
type(t_token) |
tok, |
|
|
integer, intent(in), optional |
intgr, |
|
|
double precision, intent(in), optional |
dbl, |
|
|
logical, intent(in), optional |
bool, |
|
|
character(len=*), intent(in), optional |
string |
|
) |
| |
- Parameters
-
[in,out] | parser | Parser |
[in] | tok | Identifier token |
[in] | intgr | If present, the identifier is an integer (id_integer) |
[in] | dbl | If present, the identifier is a double (id_double) |
[in] | bool | If present, the identifier is a boolean (id_boolean) |
[in] | string | If present, the identifier is a string (id_string) |
◆ parser_expect()
subroutine mod_parser::parser_expect |
( |
class(t_parser) |
parser, |
|
|
integer, intent(in) |
kind, |
|
|
logical, intent(in), optional |
has_leading_space, |
|
|
character(len=*), intent(in), optional |
message |
|
) |
| |
If the kind of the next token is the same as the one provided, the next token is consumed. Otherwise, a parser error is thrown.
Typical usage to ensure that the next token is a semicolon ';':
- Parameters
-
[in,out] | parser | Parser |
[in] | kind | required kind of the next token |
[in] | has_leading_space | optional argument that check if the token has a leading space |
[in] | message | optional message to display the expected token is not found |
◆ parser_finalize()
subroutine mod_parser::parser_finalize |
( |
type(t_parser) |
parser | ) |
|
- Parameters
-
[in,out] | parser | Parser to finalize |
◆ parser_get()
subroutine mod_parser::parser_get |
( |
class(t_parser) |
parser, |
|
|
type(t_token), intent(out) |
tok |
|
) |
| |
Act as a wrapper for lexer_read_token.
Throw an error if the lexer encounters an error.
- Parameters
-
[in,out] | parser | Parser |
[out] | tok | Token |
◆ parser_get_boolean_identifier()
logical function mod_parser::parser_get_boolean_identifier |
( |
class(t_parser) |
parser, |
|
|
type(t_token) |
tok |
|
) |
| |
Throw an error when if the identifier is not found.
- Parameters
-
[in,out] | parser | Parser |
[in] | tok | Identifier token (tokkink == tk_identifier) |
- Returns
- Boolean value of the identifier
◆ parser_get_double_identifier()
double precision function mod_parser::parser_get_double_identifier |
( |
class(t_parser) |
parser, |
|
|
type(t_token) |
tok |
|
) |
| |
Throw an error when if the identifier is not found.
- Parameters
-
[in,out] | parser | Parser |
[in] | tok | Identifier token (tokkink == tk_identifier) |
- Returns
- Double value of the identifier
◆ parser_get_identifier_type()
subroutine mod_parser::parser_get_identifier_type |
( |
class(t_parser) |
parser, |
|
|
type(t_token), intent(in) |
tok, |
|
|
integer, intent(out) |
id_kind |
|
) |
| |
Behavior:
- Find an identifier starting with the current scope.
- If an identifier is not found on the current scope, search deeper in the scope stack.
- Throw an error when the identifier is not found.
- Parameters
-
[in,out] | parser | Parser |
[in] | tok | Identifier token (tokkind == tk_identifier) |
[in] | id_kind | Type of identifier (id_integer, id_double, id_boolean, id_string) |
◆ parser_get_integer_identifier()
integer function mod_parser::parser_get_integer_identifier |
( |
class(t_parser) |
parser, |
|
|
type(t_token) |
tok |
|
) |
| |
Throw an error when if the identifier is not found.
- Parameters
-
[in,out] | parser | Parser |
[in] | tok | Identifier token (tokkink == tk_identifier) |
- Returns
- Integer value of the identifier
◆ parser_get_string_identifier()
character(len=:) function, allocatable mod_parser::parser_get_string_identifier |
( |
class(t_parser) |
parser, |
|
|
type(t_token) |
tok |
|
) |
| |
Throw an error when if the identifier is not found.
- Parameters
-
[in,out] | parser | Parser |
[in] | tok | Identifier token (tokkink == tk_identifier) |
- Returns
- String value of the identifier
◆ parser_initialize()
subroutine mod_parser::parser_initialize |
( |
type(t_parser), intent(inout) |
parser, |
|
|
character(len=*), intent(in) |
filename, |
|
|
type(t_keyword_name), dimension(:), intent(in) |
keywords |
|
) |
| |
The parser initializes a lexer with filename
and keywords
.
- Parameters
-
[in,out] | parser | Parser to initialize |
[in] | filename | Source file name |
[in] | keywords | List of keywords |
◆ parser_is_identifier_defined()
logical function mod_parser::parser_is_identifier_defined |
( |
class(t_parser), intent(inout) |
parser, |
|
|
type(t_token), intent(in) |
tok |
|
) |
| |
- Parameters
-
[in,out] | parser | Parser |
[in] | tok | Identifier token |
- Returns
- Return .true. if the given identifier is defined
◆ parser_new_scope()
subroutine mod_parser::parser_new_scope |
( |
class(t_parser) |
parser, |
|
|
type(t_token), intent(in) |
tok, |
|
|
integer, intent(in), optional |
kind |
|
) |
| |
Start a new scope beginning at the position of the token tok
. It is possible to attribute a flag to identify the scope with the kind
argument.
- Parameters
-
[in,out] | parser | Parser |
[in] | tok | Token where the scope starts |
[in] | kind | Flag to identify the scope |
◆ parser_next_keyword()
logical function mod_parser::parser_next_keyword |
( |
class(t_parser) |
parser, |
|
|
integer, intent(in) |
keyword_id |
|
) |
| |
The function returns false if the next token is not a keyword or the keyword has the wrong id.
- Parameters
-
[in,out] | parser | Parser |
[in] | keyword_id | wished id of the next keyword |
◆ parser_next_token()
logical function mod_parser::parser_next_token |
( |
class(t_parser) |
parser, |
|
|
integer, intent(in) |
kind, |
|
|
logical, intent(in), optional |
peek |
|
) |
| |
If the kind of the next token is the same as the one provided, the next token is consumed (unless peek is set to true) and the function returns .true.
. Otherwise, the next token is not consumed and the function returns .false.
.
Act as a wrapper for lexer_next_token.
- Parameters
-
[in,out] | parser | Parser |
[in] | kind | wished kind of the next token |
[in] | peek | peek token instead of consumming it |
◆ parser_peek()
subroutine mod_parser::parser_peek |
( |
class(t_parser) |
parser, |
|
|
type(t_token), intent(out) |
tok |
|
) |
| |
Act as a wrapper for lexer_peek_token.
- Parameters
-
[in,out] | parser | Parser |
[out] | tok | Contains the next token |
◆ parser_pop_scope()
subroutine mod_parser::parser_pop_scope |
( |
class(t_parser) |
parser, |
|
|
type(t_token), intent(in) |
tok |
|
) |
| |
If an error occurs, a message is thrown with a position determined by the token arguement tok
.
- Parameters
-
[in,out] | parser | Parser |
[in] | tok | Token to tell where a potential error occurs. |
◆ parser_reset_scope()
subroutine mod_parser::parser_reset_scope |
( |
class(t_parser) |
parser | ) |
|
◆ parser_throw_error()
subroutine mod_parser::parser_throw_error |
( |
class(t_parser) |
parser, |
|
|
type(t_token), intent(in) |
tok, |
|
|
character(len=*), intent(in) |
message |
|
) |
| |
Throw an error message to the user with the line, the column and the file where the provided token was read.
- Parameters
-
[in,out] | parser | current parser |
[in] | tok | token where the error occurs |
[in] | message | error message |
◆ parser_unget()
subroutine mod_parser::parser_unget |
( |
class(t_parser) |
parser, |
|
|
type(t_token), intent(in) |
tok |
|
) |
| |
Act as a wrapper for lexer_unget_token.
- Parameters
-
[in,out] | parser | Parser |
[in] | tok | Token to unget |