DMNTK | Decision Model and Notation Toolkit
dmntk-feel-grammar
FEEL grammar and parsing tables generator:
- Definition of the grammar for
FEEL
language in the format acceptable byBison
parser generator. - LALR parsing tables generator for
Rust
language.
Overview
Excerpt from Decision Model and Notation™ specification, ver. 1.3, pp. 105-179:
"DMN 1.3 defines the friendly enough expression language (FEEL) for the purpose of giving standard executable semantics to many kinds of expressions in decision model. [...] FEEL syntax is defined as a grammar here [...]".
dmntk-feel-grammar crate defines the Bison
version of the full FEEL
grammar
as defined in clause 10.3 of cited above Decision Model and Notation™ specification.
In addition, dmntk-feel-grammar crate provides functionality for generating LALR parsing tables
and reduce actions
, ready to be used by LALR
parser written in Rust.
Such parser that uses the output from dmntk-feel-grammar crate
is implemented in dmntk-feel-parser.
How it works
Inputs and outputs of dmntk-feel-grammar crate are depicted in the following diagram:
dmntk-feel-grammar takes Yacc/Bison
compatible grammar file as an input.
Grammar file for FEEL
language is defined as a source file named feel.y
and compiled
with this crate.
The output from dmntk-feel-grammar create is a file named lalr.rs
.
This file is a Rust source code that contains definitions of parsing tables and reduce actions.
dmntk-feel-grammar crate uses Bison parser generator
to process the input grammar file and to generate the parser source for C
language.
Command that generates the parser for C
language using Bison
may look like this:
$ LANG=C bison -l -r states -L C feel.y
Bison
generates C
source file that contains the generated parsing tables.
dmntk-feel-grammar extracts those tables, adds reduce action definitions and saves
the result code in lalr.rs
file as Rust source code.
Requirements
dmntk-feel-grammar requires:
- installed the newest Rust nightly version,
- installed the newest
Bison
version.
Usage
dmntk-feel-grammar may be used as a library.
Add dmntk-feel-grammar
to your Cargo.toml
:
[]
= "0.0.20"
To generate LALR parsing tables, call lalr_rust_tables
function:
use lalr_rust_tables;
Implemented grammar rules
The following grammar rules are taken from Decision Model and Notation™ ver. 1.3
-
expression =
- a. boxed_expression |
- b. textual_expression ;
-
textual_expression =
- a. for_expression | if_expression | quantified_expression |
- b. disjunction |
- c. conjunction |
- d. comparison |
- e. arithmetic_expression |
- f. instance_of |
- g. path_expression | filter_expression | function_invocation |
- h. literal | simple_positive_unary_test | name |
(
, expression ,)
;
-
textual_expressions = textual expression , {
,
, textual_expression } ; -
arithmetic_expression =
- a. addition | subtraction |
- b. multiplication | division |
- c. exponentiation |
- d. arithmetic_negation ;
-
simple_expression = arithmetic_expression | simple_value ;
-
simple_expressions = simple_expression , {
,
, simple_expression } ; -
simple_positive_unary_test =
- a. [
<
|<=
|>
|>=
] , endpoint | - b. interval ;
- a. [
-
interval = ( open_interval_start | closed_interval_start ) , endpoint ,
..
, endpoint , ( open_interval_end | closed_interval_end ) ; -
open_interval_start =
(
|]
; -
closed_interval_start =
[
; -
open_interval_end =
)
|[
; -
closed_interval_end =
]
; -
positive_unary_test = expression ;
-
positive_unary_tests = positive_unary_test , {
,
, positive_unary_test } ; -
unary_tests =
- a. positive_unary_tests |
- b.
not
,(
, positive_unary_tests,)
| - c.
-
;
-
endpoint = simple_value ;
-
simple_value = qualified_name | simple_literal ;
-
qualified_name = name , {
.
, name } ; -
addition = expression ,
+
, expression ; -
subtraction = expression ,
-
, expression ; -
multiplication = expression ,
*
, expression ; -
division = expression ,
/
, expression ; -
exponentiation = expression,
**
, expression ; -
arithmetic_negation =
-
, expression ; -
name = name_start , { name_part | additional_name_symbols } ;
-
name_start = name_start_char, { name_part_char } ;
-
name_part = name_part_char , { name_part_char } ;
-
name_start_char =
?
|[A-Z]
|_
|[a-z]
|[\uC0-\uD6]
|[\uD8-\uF6]
|[\uF8-\u2FF]
|[\u370-\u37D]
|[\u37F-\u1FFF]
|[\u200C-\u200D]
|[\u2070-\u218F]
|[\u2C00-\u2FEF]
|[\u3001-\uD7FF]
|[\uF900-\uFDCF]
|[\uFDF0-\uFFFD]
|[\u10000-\uEFFFF]
; -
name_part_char = name_start_char | digit |
\uB7
|[\u0300-\u036F]
|[\u203F-\u2040]
; -
additional_name_symbols =
.
|/
|-
|’
|+
|*
; -
literal = simple_literal |
null
; -
simple_literal = numeric_literal | string_literal | boolean_literal | date_time_literal ;
-
string_literal =
"
, { character – ("
| vertical_space) | string_escape_sequence},"
; -
boolean_literal =
true
|false
; -
numeric_literal = [
-
] , ( digits , [.
, digits ] |.
, digits ) ; -
digit = [0-9] ;
-
digits = digit , { digit } ;
-
function_invocation = expression , parameters ;
-
parameters =
(
, ( named_parameters | positional_parameters ) ,)
; -
named_parameters = parameter_name ,
:
, expression , {,
, parameter name ,:
, expression } ; -
parameter_name = name ;
-
positional_parameters = [ expression , {
,
, expression } ] ; -
path_expression = expression ,
.
, name ; -
for_expression =
for
, name ,in
, iteration context {,
, name ,in
, iteration context } ,return
, expression ; -
if_expression =
if
, expression ,then
, expression ,else
expression ; -
quantified_expression = (
some
|every
) , name ,in
, expression , {,
, name ,in
, expression } ,satisfies
, expression ; -
disjunction = expression ,
or
, expression ; -
conjunction = expression ,
and
, expression ; -
comparison =
- a. expression , (
=
|!=
|<
|<=
|>
|>=
) , expression | - b. expression ,
between
, expression ,and
, expression | - c. expression ,
in
, positive_unary_test | - d. expression ,
in
,(
, positive unary tests,)
;
- a. expression , (
-
filter_expression = expression ,
[
, expression ,]
; -
instance_of = expression ,
instance
,of
, type ; -
type =
- a. qualified_name |
- b.
list
<
type>
| - c.
context
<
name:
type {,
name:
type }>
| - d.
function
<
[ type {,
type } ]>
->
type ;
-
boxed_expression = list | function_definition | context ;
-
list =
[
, [ expression , {,
, expression } ] ,]
; -
function_definition =
function
,(
, [ formal_parameter {,
, formal parameter } ] ,)
, [external
] , expression ; -
formal_parameter = parameter_name [
:
type ] ; -
context =
{
, [context_entry , {,
, context_entry } ] ,}
; -
context_entry = key ,
:
, expression ; -
key = name | string_literal ;
-
date_time_literal = at_literal | function_invocation ;
-
white_space = vertical_space |
\u0009
|\u0020
|\u0085
|\u00A0
|\u1680
|\u180E
|[\u2000-\u200B]
|\u2028
|\u2029
|\u202F
|\u205F
|\u3000
|\uFEFF
; -
vertical_space =
[\u000A-\u000D]
; -
iteration_context = expression, [
..
, expression ] ; -
string_escape_sequence =
\'
|\"
|\\
|\n
|\r
|\t
| code_point; -
at_literal =
@
, string_literal
License
dmntk-feel-grammar is distributed under the terms of both the MIT license and the Apache License (Version 2.0). See LICENSE-MIT and LICENSE-APACHE for details.