Skip to content

Commit 1aa514d

Browse files
committed
added section on architecture.
1 parent 87a28a3 commit 1aa514d

File tree

1 file changed

+89
-4
lines changed

1 file changed

+89
-4
lines changed

README.md

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ complicated parse trees for big command command line programs.
2727
* [Error Handling](#error-handling)
2828
* [Logging](#logging)
2929
* [Architecture](#architecture)
30-
* [Parse Trees](#parse-trees)
3130
* [Parse Path](#parse-path)
3231

3332
## Installation
@@ -542,10 +541,96 @@ try! argtree.parse()
542541
Note that most of the logging is done on debug level, so this level should be activated to see any log output.
543542

544543
## Architecture
545-
TODO
546544

547-
### Parse Trees
545+
The basic idead it so define a tree of parsers, which then consume argument after argument. This package helps to
546+
define the parser tree and invoke it. Each node in the parser tree usually parses specific types of arguments, e.g.
547+
flags or options. To understand, how the parser tree must be set up, it is important to know how the tree is
548+
traversed. Consider the following example
549+
```
550+
arguments = ['arg_0', 'arg_1', 'arg_2']
551+
```
552+
The first argument is always ignored, since it refers to the script name. Parsing is started at `arg_1`.
553+
Now, if there is the following tree
554+
```
555+
argTree
556+
+-- parser_0
557+
| +-- parser_0_1
558+
+-- parser_1
559+
```
560+
first, `arg_1` will be parsed. Thereby `argTree` calls each child parser with the arguments array and the index `i`,
561+
where parsing should be done.
562+
Each child parser, `parser_0` and `parser_1` in this case can decidide to consume any number of arguments
563+
starting from `i` and returns how many arguments it consumed. Hence, if `parser_0` decides to consume all arguments,
564+
`parser_1` will never get called, since there are no arguments left. If `parser_0` consumes no argument, `parser_1` get
565+
called on the same index `i` and may also consume an arbitrary amount of arguments.
566+
For any index `i` calling subsequent child parsers is stopped, as soon as one child parser consumes a non-zero amount
567+
of argumts. After that, the index `i` is incremented by the number of consumed arguments and the list of child parsers
568+
ist iterated again from the beginning.
569+
So if `parser_0` consumes `arg_1`, `parser_1` is not called. Instead `i` is incremented by one and `parser_0` is called
570+
again for `arg_2`. So it is important to understand that parsers with low indices always have higher precedence
571+
than the following parsers.
572+
One corner case is, if an argument is not consumed by any parser. In this case `i` is incremented by one and the
573+
next argument is parsed. This means that the argument not parsed is simply ignored. If ignoring arguments is not
574+
the expected behaviour, an `UnexpectedArgHandler` can be added to throw an error.
575+
It should be clear now that the `UnexpectedArgHandler` must be added as last parser, since it simply consumes any
576+
argument and converts it into an error.
577+
578+
Having understood the parsing process for one node, it is straightforward to understand the whole tree. Since every
579+
parser node can consume any number of arguments, it is not important how the node parses arguments. So each node
580+
may can itself delegate to child parses in the described way. This makes it very easy to reuse simple parsers
581+
for flags and options.
582+
Here is a short example for a command line program, which takes a global flag `-v` and two commands `foo` and `bar`
583+
which themselves take flags `-f` and `-b` respectively.
584+
```
585+
argTree
586+
+-- -v
587+
+-- foo
588+
| +-- -f
589+
+-- bar
590+
+-- -b
591+
```
548592

549593
### Parse Path
550-
TODO
594+
595+
To define the context of a parsed argument, a parse path is always specified. This is simply an array of parsers in
596+
the call chain. Note, that the root parser is not added to the path.
597+
So for the following example
598+
```
599+
argTree
600+
+-- -v
601+
+-- foo
602+
| +-- -f
603+
+-- bar
604+
+-- -b
605+
```
606+
there would be the folowing paths when parsing
607+
```
608+
[] : -v
609+
[foo] : -f
610+
[bar] : -b
611+
```
612+
This path can be used, if a parser should be used multiple times, but should act context aware. If e.g. `-v` should
613+
do something different for the `foo` and for `bar` the following tree should be defined
614+
```
615+
argTree
616+
+-- foo
617+
| +-- -v
618+
| +-- -f
619+
+-- bar
620+
+-- -v
621+
+-- -b
622+
```
623+
Or, alternatively
624+
```
625+
argTree
626+
+-- -v
627+
+-- foo
628+
| +-- -v
629+
| +-- -f
630+
+-- bar
631+
+-- -v
632+
+-- -b
633+
```
634+
if `-v` should also be supported on the global level.
635+
For an example on path specific actions see [Semi Global Flags (or Options)](#semi-global-flags-or-options).
551636

0 commit comments

Comments
 (0)