Updated Application overview (markdown)

Bartłomiej Przemysław Pluta
2020-03-30 18:26:47 +02:00
parent 980880f7d1
commit 08e561a626

@@ -2,7 +2,7 @@
[[schemas/architecture.svg]]
The system is composed of following components (which are technically Gradle subprojects) :
* `core` - the SMNP language engine consisting of interpreter (being actually a facade for tokenizer, parser and evaluator), as well as the modules management system
* `core` - the SMNP language engine consisting of interpreter (being actually a facade for tokenizer, parser and evaluator), as well as the modules' management system
* `app` - the commandline-based frontend for `core` component
* modules (`smnp.lang`, `smnp.io`, `smnp.audio.synth` etc.) - a set of external modules that extends the functionality of SMNP scripts
* `api` - component that provides shared interfaces and abstract classes common for both `core` and each module components.
@@ -149,10 +149,10 @@ parenthesesExpr ::= '(' expr ')' ;
atom ::= parenthesesExpr | identifier | staff | list | map ;
```
Therefore `allOf(a, b, c) {...}` is equivalent of `a = a b c`, whereas `oneOf(a, b, c)` is equivalent of `a = a | b | c`.
Therefore, `allOf(a, b, c) {...}` is equivalent of `a = a b c`, whereas `oneOf(a, b, c)` is equivalent of `a = a | b | c`.
### Parsers' cascade
Parsers are cascadingly composed and thanks to that, they are able to parse a one-dimensional tokens stream to tree structure. For example, the mentioned before `AtomParser` is used by `UnitParser` which is responsible for parsing minus operator and dot operator. In turn, the `UnitParser` is used by `FactorParser` that is responsible for parsing `not` operator and power operator. The `FactorParser` is used by `TermParser` which is responsible for parsing product operator. The `TermParser` is used by `SubexpressionParser` which provides production rules for logic operators, relation operators etc. The `SubexpressionParser` is used by `ExpressionParser` which technically is `oneOf`-based wrapper for `SubexpressionParser` and `LoopParser`. The `ExpressionParser represents all constructions that can product a value and is used by `StatementParser` which is eventually used by `RootParser`.
Parsers are cascaded composed and thanks to that, they are able to parse a one-dimensional tokens' stream to tree structure. For example, the mentioned before `AtomParser` is used by `UnitParser` which is responsible for parsing minus operator and dot operator. In turn, the `UnitParser` is used by `FactorParser` that is responsible for parsing `not` operator and power operator. The `FactorParser` is used by `TermParser` which is responsible for parsing product operator. The `TermParser` is used by `SubexpressionParser` which provides production rules for logic operators, relation operators etc. The `SubexpressionParser` is used by `ExpressionParser` which technically is `oneOf`-based wrapper for `SubexpressionParser` and `LoopParser`. The `ExpressionParser represents all constructions that can product a value and is used by `StatementParser` which is eventually used by `RootParser`.
The order of each parser in the cascade determines the precedence of each operation and has influence on the
AST's shape. Take look at the following example:
@@ -194,8 +194,33 @@ class SubexpressionParser : Parser() {
return expr4Parser.parse(input)
}
```
This is a code of `SubexpressionParser` and it consists of 4 subparser cascadingly composed. Because of the `expr4Parser` (responsible for `or` operator) is defined using `expr3Parser` (responsible for `and` operator), the `or` operator has a higher precendee than `and` operator (please compare [[Operators#Operators precedence]].
Take a look at the following AST:
This is a code of `SubexpressionParser` and it consists of 4 subparsers cascaded composed. Because of the `expr4Parser` (responsible for `or` operator) is defined using `expr3Parser` (responsible for `and` operator), the `or` operator has a higher precedence than `and` operator (please compare [[Operators#Operators precedence]]).
Following listening features the composition of `and` and `or` operator nodes honoring their precedence:
```
$ smnp --ast --dry-run -c "true and false or not false and not false;"
RootNode 1:16
└─LogicOperatorNode 1:16
├─LogicOperatorNode 1:6
│ ├─BoolLiteralNode 1:1
│ │ └ (bool, »true«, 1:1)
│ ├─TokenNode 1:6
│ │ └ (and, »and«, 1:6)
│ └─BoolLiteralNode 1:10
│ └ (bool, »false«, 1:10)
├─TokenNode 1:16
│ └ (or, »or«, 1:16)
└─LogicOperatorNode 1:29
├─NotOperatorNode 1:19
│ ├─TokenNode 1:19
│ │ └ (not, »not«, 1:19)
│ └─BoolLiteralNode 1:23
│ └ (bool, »false«, 1:23)
├─TokenNode 1:29
│ └ (and, »and«, 1:29)
└─NotOperatorNode 1:33
├─TokenNode 1:33
│ └ (not, »not«, 1:33)
└─BoolLiteralNode 1:37
└ (bool, »false«, 1:37)
```