Language Reference

ADia is an indent based language such as Python and uses indentation to specify the parent/children relationship between entities. Leading whitespaces at the beginning of a line is used to compute the indentation level of the line, which in turn is used to determine the grouping of statements.

Every statement of the ADia language is consist of one operation and an optional text as follow:

operation[: text]

Example:

adia.print('''
    diagram: foo
    sequence:
    foo -> bar
''')
DIAGRAM: foo

+-----+ +-----+
| foo | | bar |
+-----+ +-----+
   |       |
   |~~~~~~>|
   |       |
   |<------|
   |       |
+-----+ +-----+
| foo | | bar |
+-----+ +-----+

Comments

Every line started with # is comment and will be ignored by the lexer.

Diagram Header

Every ADia document should starts with the diagram: [TITLE] attribute. There is also two optional attributes: version and author.

Example:

adia.print('''
    diagram: Foo
    version: 1.0
    author: Alice

    sequence: Foo & Bar
    foo -> bar
''')
DIAGRAM: Foo
author: Alice
version: 1.0


SEQUENCE: Foo & Bar

+-----+ +-----+
| foo | | bar |
+-----+ +-----+
   |       |
   |~~~~~~>|
   |       |
   |<------|
   |       |
+-----+ +-----+
| foo | | bar |
+-----+ +-----+

Diagram Section

Every ADia document may consists of zero or more sections which could be one of sequence, class and fork.

adia.print('''
    diagram: Foo

    sequence:  Foo & Bar
    foo -> bar

    sequence: Bar & Baz
    bar -> baz
''')
DIAGRAM: Foo


SEQUENCE: Foo & Bar

+-----+ +-----+
| foo | | bar |
+-----+ +-----+
   |       |
   |~~~~~~>|
   |       |
   |<------|
   |       |
+-----+ +-----+
| foo | | bar |
+-----+ +-----+


SEQUENCE: Bar & Baz

+-----+ +-----+
| bar | | baz |
+-----+ +-----+
   |       |
   |~~~~~~>|
   |       |
   |<------|
   |       |
+-----+ +-----+
| bar | | baz |
+-----+ +-----+

Note

Currently, only the sequence diagram is implemented. It means every ADia document may consists of zero or more sequence diagrams.

Sequence Diagram

A sequence diagram always starts with the sequence: [TITLE] keyword and basically it is a collection of modules and items which described below.

Module

You may use shorter name for modules for simplicity and define comprehensive title with MODULE.title: TITLE statement.

adia.print('''
    diagram: foo
    sequence:
    foo.title: Mr Foo
    foo -> bar: hello!
''')
DIAGRAM: foo

+---------+     +-----+
| Mr Foo  |     | bar |
+---------+     +-----+
     |             |
     |~~~hello!~~~>|
     |             |
     |<------------|
     |             |
+---------+     +-----+
| Mr Foo  |     | bar |
+---------+     +-----+

Note

You can put note anywhere and at every indentation level. see below to learn about the Single-Module and Multi-Module notes.

Single-Module Note

adia.print('''
    diagram: foo
    sequence:
    @foo: Over the foo->bar
    foo -> bar
      bar -> baz
        @baz: Inside the bar->baz
      @bar: Under the bar->baz
''')
DIAGRAM: foo

+-----+              +-----+               +-----+
| foo |              | bar |               | baz |
+-----+              +-----+               +-----+
   |                    |                     |
---------------------   |                     |
| Over the foo->bar |   |                     |
---------------------   |                     |
   |                    |                     |
   |~~~~~~~~~~~~~~~~~~~>|                     |
   |                    |~~~~~~~~~~~~~~~~~~~~>|
   |                    |                     |
   |                    |                  -----------------------
   |                    |                  | Inside the bar->baz |
   |                    |                  -----------------------
   |                    |                     |
   |                    |<--------------------|
   |                    |                     |
   |                 ----------------------   |
   |                 | Under the bar->baz |   |
   |                 ----------------------   |
   |                    |                     |
   |<-------------------|                     |
   |                    |                     |
+-----+              +-----+               +-----+
| foo |              | bar |               | baz |
+-----+              +-----+               +-----+

Multi-Module Note

A Multi-Module Note may cover two or more modules.

adia.print('''
    diagram: foo
    sequence:
    @foo ~ bar: Lorem Ipsum
    foo -> bar
      bar -> baz
        @foo ~ baz: Lorem Ipsum
''')
DIAGRAM: foo

+-----+ +-----+ +-----+
| foo | | bar | | baz |
+-----+ +-----+ +-----+
   |       |       |
---------------    |
| Lorem Ipsum |    |
---------------    |
   |       |       |
   |~~~~~~>|       |
   |       |~~~~~~>|
   |       |       |
-----------------------
| Lorem Ipsum         |
-----------------------
   |       |       |
   |       |<------|
   |<------|       |
   |       |       |
+-----+ +-----+ +-----+
| foo | | bar | | baz |
+-----+ +-----+ +-----+

Call

A call is consists of CALLER -> CALLEE[: [FUNCTION] [=> RETURN]].

CALLER and CALLEE are modules which described above.

FUNCTION and RETURN can be any ASCII character.

Changed in version 1.0: -> RETURN is replaced by => RETURN.

adia.print('''
    diagram: foo
    sequence:

    @foo ~ bar: Without function name
    foo -> bar

    @foo ~ bar: With function name
    foo -> bar: init(options)

    @foo ~ bar: With function name & return value
    foo -> bar: init(options) => err

    @foo ~ bar: Only return value
    foo -> bar: => err
''')
DIAGRAM: foo

+-----+                       +-----+
| foo |                       | bar |
+-----+                       +-----+
   |                             |
-------------------------------------
| Without function name             |
-------------------------------------
   |                             |
   |~~~~~~~~~~~~~~~~~~~~~~~~~~~~>|
   |                             |
   |<----------------------------|
   |                             |
-------------------------------------
| With function name                |
-------------------------------------
   |                             |
   |~~~init(options)~~~~~~~~~~~~>|
   |                             |
   |<----------------------------|
   |                             |
-------------------------------------
| With function name & return value |
-------------------------------------
   |                             |
   |~~~init(options)~~~~~~~~~~~~>|
   |                             |
   |<--err-----------------------|
   |                             |
-------------------------------------
| Only return value                 |
-------------------------------------
   |                             |
   |~~~~~~~~~~~~~~~~~~~~~~~~~~~~>|
   |                             |
   |<--err-----------------------|
   |                             |
+-----+                       +-----+
| foo |                       | bar |
+-----+                       +-----+

Self Call

adia.print('''
    diagram: foo
    sequence:
    foo -> foo
    foo -> foo: self_test() => Result
''')
DIAGRAM: foo

+-----+
| foo |
+-----+
   |
   |~~~~~~+
   |      |
   |<-----+
   |
   |~~~self_test()~~~+
   |                 |
   |<--Result--------+
   |
+-----+
| foo |
+-----+

Callstack

Use one indentation level to put one or more item inside another.

Consider these Python modules: foo.py and bar.py.

foo.py

import bar


bat.init()

bar.py

import baz
import qux

def prepare():
    ...

def init():
  prepare()
  baz.init()
  qux.init()

ADia representation of the codes above would be something like this:

adia.print('''
    diagram: foo
    sequence:
    foo -> bar: init()
      bar -> bar: prepare()
      bar -> baz: init()
      bar -> qux: init()
''')
DIAGRAM: foo

+-----+       +-----+            +-----+ +-----+
| foo |       | bar |            | baz | | qux |
+-----+       +-----+            +-----+ +-----+
   |             |                  |       |
   |~~~init()~~~>|                  |       |
   |             |~~~prepare()~~~+  |       |
   |             |               |  |       |
   |             |<--------------+  |       |
   |             |                  |       |
   |             |~~~init()~~~~~~~~>|       |
   |             |                  |       |
   |             |<-----------------|       |
   |             |                  |       |
   |             |~~~init()~~~~~~~~~~~~~~~~>|
   |             |                  |       |
   |             |<-------------------------|
   |<------------|                  |       |
   |             |                  |       |
+-----+       +-----+            +-----+ +-----+
| foo |       | bar |            | baz | | qux |
+-----+       +-----+            +-----+ +-----+

Condition

adia.print('''
    diagram: foo
    sequence:
    foo -> bar: init(force, full)
      if: force
        bar -> baz: force_init()
      elif: full
        bar -> baz: full_init()
      else:
        bar -> baz: init()
''')
DIAGRAM: foo

+-----+                  +-----+             +-----+
| foo |                  | bar |             | baz |
+-----+                  +-----+             +-----+
   |                        |                   |
   |~~~init(force, full)~~~>|                   |
   |                        |                   |
   |                     ***************************
   |                     * if force                *
   |                     ***************************
   |                        |                   |
   |                        |~~~force_init()~~~>|
   |                        |                   |
   |                        |<------------------|
   |                        |                   |
   |                     ***************************
   |                     * elif full               *
   |                     ***************************
   |                        |                   |
   |                        |~~~full_init()~~~~>|
   |                        |                   |
   |                        |<------------------|
   |                        |                   |
   |                     ***************************
   |                     * else                    *
   |                     ***************************
   |                        |                   |
   |                        |~~~init()~~~~~~~~~>|
   |                        |                   |
   |                        |<------------------|
   |                        |                   |
   |                     ***************************
   |                     * end if                  *
   |                     ***************************
   |                        |                   |
   |<-----------------------|                   |
   |                        |                   |
+-----+                  +-----+             +-----+
| foo |                  | bar |             | baz |
+-----+                  +-----+             +-----+

Loop

For Loop

adia.print('''
    diagram: foo
    sequence:
    foo -> bar: init(forks)
      for: i in range(forks)
        bar -> baz: fork(i)
''')
DIAGRAM: foo

+-----+            +-----+           +-----+
| foo |            | bar |           | baz |
+-----+            +-----+           +-----+
   |                  |                 |
   |~~~init(forks)~~~>|                 |
   |                  |                 |
   |               *************************
   |               * for i in range(forks) *
   |               *************************
   |                  |                 |
   |                  |~~~fork(i)~~~~~~>|
   |                  |                 |
   |                  |<----------------|
   |                  |                 |
   |               *************************
   |               * end for               *
   |               *************************
   |                  |                 |
   |<-----------------|                 |
   |                  |                 |
+-----+            +-----+           +-----+
| foo |            | bar |           | baz |
+-----+            +-----+           +-----+

While Loop

adia.print('''
    diagram: foo
    sequence:
    while: True
      foo -> bar: accept() => socket
''')
DIAGRAM: foo

+-----+         +-----+
| foo |         | bar |
+-----+         +-----+
   |               |
***********************
* while True          *
***********************
   |               |
   |~~~accept()~~~>|
   |               |
   |<--socket------|
   |               |
***********************
* end while           *
***********************
   |               |
+-----+         +-----+
| foo |         | bar |
+-----+         +-----+