AlgPseudocode and Language Variants

Hint

The reST source of this documentation page can be found here.

These lexers are heavily inspired by CTAN’s Algpseudocodex. They recognize all sorts of single- and multi-line comments in addition to expressions and commands that are inspired by Algpseudocodex.

They are used in Sphinx using their aliases. The code block:

.. code-block:: algpseudocode

   \PROGRAM {The Pseudoprogram} \IS

   \END PROGRAM {The Pseudoprogram}

will be rendered as:

PROGRAM The Pseudoprogram IS

END OF PROGRAM The Pseudoprogram

And the same code block with the german variant (using .. code-block:: algpseudocode-de as language alias):

PROGRAMM The Pseudoprogram IST

ENDE DES PROGRAMMS The Pseudoprogram

States

The AlgPseudocode lexer and its language variants AlgPseudocodeDE and AlgPseudocodeFR basically work in three states (aka modes or contexts): default, expression and text.

In expressions it automatically recognizes:

  • Strings (single-quote, double-quote, triple-single-quote, triple-double-quote, Python style)

  • Numbers (also Python style)

  • (Mathematical) operators and symbols

  • \TEXT{...} or \T{...}

    Used to switch to a text-mode that prohibits automatic expression highlighting.

    A closing curly brace can be quoted with \} to not end the text mode prematurely.

  • \EXPR, \EXPRESSION or \E as nested construct

  • \NAME, \CALL and \GETS

  • \REM and \REMARK for remarks (aka comments)

  • Names (Name.Entity)

  • Explicit Token Types

The default-mode is an extension of expression: in addition to expressions it recognizes all sorts of single- and multi-line comments and commands that are inspired by Algpseudocodex.

In text context it recognizes:

  • \EXPRESSION, \EXPR or \E

    Use to switch to expression-mode.

    A closing curly brace can be quoted with \} to not end the expression mode prematurely.

  • \TEXT (aka \T) as nested construct

  • \REM and \REMARK for remarks (aka comments)

  • Explicit Token Types

Lexer Options

prohibit_raiseonerror_filter

Type: bool

Default: None

If True the raiseonerror filter is not allowed to be applied by Sphinx when Lexer.add_filter() is called.

This setting does not apply to filters that are set by the standard lexer option filters.

no_end

Type: bool

Default: False

If True all the \ENDxxx commands will be skipped and yield no output.

strict_tokentype

Type:: bool

Default: True

Control whether Explicit Token Types yield pygments.token.Token.Generic.Error tokens (when True, this is the default) or a token type that is synthesized on the fly by pygments.token.string_to_tokentype() (when False).

gets

Type: str or None

Default: None (yields )

The operator symbol to be printed by the command \GETS.

An often used alternative is :=.

remark

Type: str or None

Default: None (yields )

The symbol to be printed as when starting comments with \REMARK or \REM.

To use a lexer with non-default options in Sphinx see section Customized Lexers in Sphinx.

Comments

  • with the \REMARK or \REM keywords (until the end of the line; the output includes a leading symbol, by default )

  • multi-line comments with /* ... */; they can be nested

  • multi-line comments with (* ... *); they can be nested

  • single-line comments with // or # (until the end of the line)

/*
 * A single multiline comment
 */

/*
 * A multiline comment
 *
 * /* This is a nested multi-line comment */
 *
 */

(*
 * A multiline comment
 *
 * (* This is a nested multi-line comment *)
 *
 *)

// A single-line comment

# A single-line comment

▷ A remark is a single-line comment with a leading symbol

Literals

Strings and numbers as in Python. String prefixes u and b are supported—prefixes r, f and t are not supported.

To have non-string-delimiting single- and double-quotes in the output you have to escape them using \' or \". This must be used to typeset something as f'(x) = 0.

0  1234567890 0xdead 0b100001 0o720  2.7 2.7e-54

"A string with an escaped double-quote \" "

'Another string with an escaped single-quote \' '

"""A multiline
string
"""

'''Another multiline string

'''

b"A \x20 byte string"

u'An explicit Unicode \u1234 string'

"  a non string

'  a non string also

(Mathematical) Symbols and Operators

Some ASCII symbol combinations are recognized and replaced by a Unicode symbol:

<=>    
<->    
<-     
->     
=>     
<=     
>=     
<>     
!=     
:=     ∶=
=:     =∶
?=     

Unicode codepoints with property Sm are recognized as mathematical symbols and highlighted accordingly.

Punctuation

Runs of dots ., .., ..., ...., … are handled properly in expressions and yield a punctuation token. They are not replaced by corresponding Unicode symbols.

Commands

  • Start with a backslash character \

  • Case-insensitive

  • Yield mostly the pygments.token.Token.Keyword token type

  • Translated if a translation is found

  • Depending on the command—may have required or optional parameters

    Parameter handling is as follows:

    • Parameters are enclosed in curly braces { and }

    • Escaping within the braces is possible using the backslash \ as escape character

    • Parameters are separated from the keyword/command by a (possibly empty) run of space or TAB characters. This is true for required and optional parameters.

  • Unrecognized commands typically result in a pygments.token.Token.Error token.

More on escaping rules you can find in this chapter.

Commands With Required Parameters

\PROGRAM {A Program}  or  \PROG {A Program}                                    PROGRAM A Program
\ALGORITHM{An Algorithm}  or  \ALGO{An Algorithm}                              ALGORITHM An Algorithm
\PROCEDURE{A Procedure}  or  \PROC{A Procedure}                                PROCEDURE A Procedure
\FUNCTION{A Function}  or  \FUNC{A Function}  or  \FN{A Function}              FUNCTION A Function
\CLASS{A Class}                                                                CLASS A Class

\STATEMENT{the expression}  \STATE{the expression}  \BLOCK{the expression}     ◆ the expression

expr1: \EXPRESSION{expression a in b}   expr2: \EXPR{expression b in a}        expr1: expression a in b   expr2: expression b in a

\TEXTSTATEMENT{the text}  \TEXTSTATE{the text}  \TSTATEMENT{the text}  \TSTATE{the text}  \TEXTBLOCK{the text}  \TBLOCK{the text}             ▪ the text

\INPUT{Input 1}                            Input: Input 1
\INPUTS{Input 2}                           Inputs: Input 2

\OUTPUT{Output 1}                          Output: Output 1
\OUTPUTS{Output 2}                         Outputs: Output 2

\ENSURE{Whatever should be ensured!}       Ensure: Whatever should be ensured!

\REQUIRE{Whatever should be required.}     Require: Whatever should be required.

\RETURNS{Return 2}                         Returns: Return 2

\CALL{a function}(p1, p2)                  a function(p1, p2)

\NAME{an entity name}                      an entity name

For a special command with two required parameters see Explicit Token Types.

Commands With Optional Parameters

Some END-commands have optional parameters:

\ENDPROGRAM  \ENDPROG              END OF PROGRAM
\ENDALGORITHM  \ENDALGO            END OF ALGORITHM
\ENDPROCEDURE  \ENDPROC            END OF PROCEDURE
\ENDFUNCTION  \ENDFUNC  \ENDFN     END OF FUNCTION
\ENDCLASS                          END OF CLASS

They are used like this:

\CLASS{Foo Bar Class} ... \END CLASS {Foo Bar Class}   yields   CLASS Foo Bar Class ... END OF CLASS Foo Bar Class

\CLASS{Foo Bar Class} ... \END CLASS                   yields   CLASS Foo Bar Class ... END OF CLASS

See also

For other syntax variants concerning END see also section END-Commands.

Commands Without Parameters

“Normal” Commands

\IF                                IF
\THEN                              THEN
\ELSE                              ELSE
\ELSEIF or \ELSIF  or  \ELIF       ELSE IF or ELSE IF or ELSE IF
\DO                                DO
\WHILE                             WHILE
\FORALL                            FOR ALL
\FOR                               FOR
\FROM                              FROM
\TO                                TO
\STEP                              STEP
\IN                                IN
\LOOP                              LOOP
\REPEAT                            REPEAT
\UNTIL                             UNTIL

\RETURN                            RETURN

\BEGIN                             BEGIN
\END                               END

\IS                                IS
\WITH                              WITH

\GETS                              

\REMARK   or   \REM                ▷ A comment with a leading symbol

\REMARK or \REM is special: all characters to the end of the line are taken as comment; curly braces are not needed—in fact: they are interpreted to be part of the comment.

END-Commands

The separator character can be empty, a run of ASCII spaces, a run of TAB characters, a single underscore _ or a single hyphen -.

All of the following examples are equally valid and result in the same output:

\ENDIF, \END IF, \END-IF, \END_IF or \END IF

\ENDIF             END IF     ▷ empty

\END IF            END IF     ▷ a single space

\END  IF           END IF     ▷ two spaces

\END-IF            END IF     ▷ a single hyphen

\END_IF            END IF     ▷ a single underscore

\END   IF          END IF     ▷ a single TAB character

The list of END-commands (here always just with - as separator):

\END-PROGRAM  \END-PROG              END OF PROGRAM
\END-ALGORITHM  \END-ALGO            END OF ALGORITHM
\END-PROCEDURE  \END-PROC            END OF PROCEDURE
\END-FUNCTION  \END-FUNC  \END-FN    END OF FUNCTION
\END-CLASS                           END OF CLASS
\END-IF                              END IF
\END-WHILE                           END WHILE
\END-FOR                             END FOR
\END-FORALL                          END FOR ALL
\END-LOOP                            END LOOP

Note

The output of these END-commands can be suppressed by setting the lexer option no_end to True.

Names and Entities

In an expression context all other words are interpreted as entity names (token type pygments.token.Token.Name.Entity).

Allowed characters in the words follow the corresponding Python rules. As such, many Unicode characters are allowed.

To highlight entity names with whitespace or other “special” characters in it use the NAME command.

entity_name_1          entity_name_1

entity_name_2          entity_name_2

\NAME{entity-name 3}   entity-name 3

München                München

Genève                 Genève

Note

Should you want to change the token type and the associated highlighting you may want to have a look at TokenReplaceFilter.

Explicit Token Types

They allow to handle keywords and operators that are not recognized by default. And they allow the user to explicitely highlight some input text with a low-level command.

They are implemented with the \ttX{ARG1}{ARG2} command.

This command has two required parameters:

  1. The content of the first argument ARG1 can be one of

    • A value in the pygments.token.STANDARD_TYPES dict.

      Its corresponding token type (the associated key in this dictionary) will be used as token type for the token.

    • A string representation of an existing token type without the Token. prefix (e.g. String, Generic, Generic.EmphStrong, Text, Text.Multiline).

    If a corresponding token type is not found the lexer’s behaviour depends on the lexer option strict_tokentype (see Lexer Options):

    If True (the default) the command yields a pygments.token.Token.Generic.Error token type for the given command’s content.

    If False then the Pygments function pygments.token.string_to_tokentype() will be called. This function returns either an existing token type or synthesizes a new one on the fly. The associated highlighting with freshly created token types in the output may not be well defined.

    For this argument escaping is neither needed nor supported.

  2. The content of the second argument will given the token type of the first parameter.

    Standard Escaping Rules apply to this argument!

Note

The command for explicit token types is case-sensitive.

Examples:

• \ttX{}{token}                 token     ▷ just a base "Token"

• \ttX{kc}{C}                   C         ▷ C as Keyword.Constant
• \ttX{Keyword.Constant}{C}     C         ▷ C as Keyword.Constant
• \ttX{ow}{∈}                            ▷ ∈ as Operator.Word
• \ttX{Operator.Word}{∈}                 ▷ ∈ as Operator.Word
• \ttX{kc}{A Constant Keyword}  A Constant Keyword  ▷ An explicit Keyword.Constant
• \ttX{nv}{A Variable Name}     A Variable Name     ▷ An explicit Name.Variable
• \ttX{ni}{An Entity*Name}      An Entity*Name      ▷ An explicit Name.Entity
• \ttX{k}{∈ ∌}     ∈ ∌       ▷ ∈ and ∌ as (ordinary) Keywords
• \ttX{o}{∈ ∌}     ∈ ∌       ▷ ∈ and ∌ as (ordinary) Operators
  /*
   * The line below has ∈_∌ as (peculiar) function name.
   * Their params are automatic (i.e. a normal expression).
   */
• \ttX{nf}{∈_∌}(p1, p2)               ∈_∌(p1, p2)
• \ttX{Name.Function}{∈_∌}(p1, p2)    ∈_∌(p1, p2)
  /*
   * The line below has ∈_∌ as (peculiar) decorator name (as used in Python).
   * Their params are automatic (i.e. a normal expression).
   */
• \ttX{nd}{∈_∌}(p1, p2)               ∈_∌(p1, p2)
• \ttX{Name.Decorator}{∈_∌}(p1, p2)   ∈_∌(p1, p2)
  /*
   * Normal emphasis ("strong")
   */
• \ttX{gs}{this is strong}                       this is strong
• \ttX{Generic.Strong}{this is strong}           this is strong
  /*
   * A strong emphasis.
   */
• \ttX{ges}{A Strong Emphasis!}                  A Strong Emphasis!
• \ttX{Generic.EmphStrong}{A Strong Emphasis!}   A Strong Emphasis!
  /*
   * Escaping is allowed and needed for the closing brace!
   * The example token type is a "String".
   */
• \ttX{s}{Escaping brace \} and backslash \\!}   Escaping brace } and backslash \!
  /*
   * This is a non-existing token type:
   * by default you get some generic error markup with a Generic.Error
   * token and no expansion.
   * See also `Lexer Options` and `strict_tokentype`.
   */
• \ttX{NON-EXISTING}{∈_∌}(p1, p2)     \ttX{NON-EXISTING}{∈_∌}(p1, p2)

An example with a lexer and strict_tokentype=False (highlighting obviously is like standard text with the templates used):

• \ttX{Generic.Not.Yet.Existing}{∈_∌}(p1, p2)     ∈_∌(p1, p2)

Note

Explicit token types work in all expression and text contexts.

Note

Nesting of explicit token types is not supported.

Escaping Rules

The escape character is a backslash \.

A backslash can be escaped with \\ and yields a single backslash token.

Within parameters a closing curly brace } ends the current parameters environment. It must be escaped using \} if a closing curly brace is part of the argument content.

A single backslash yields a pygments.token.Token.Generic.Error token when in default and expression states (and also in Explicit Token Types). Contrary—in text contexts a single backslash character that does not introduce a command yields a normal text token.

In all contexts a backslash that would normally introduce a known command must be escaped if the content should not recognized as a command.

Single- and double-quotes must be escaped also (\" or \') in default and expression contexts when they should not introduce a string token.

Customized Lexers in Sphinx

Defining lexers with non-default options in Sphinx can be done in its configuration file conf.py.

The first option is to apply the Sphinx config value highlight_options properly. An existing lexer can be customized by options.

A more flexible alternative is to define a new lexer in the Sphinx application. The very same lexer class can be used with different options:

from functools import partial
from pygments_lexer_pseudocode2.lexers.algpseudocode import AlgPseudocodeLexer

def setup(app):

    #
    # Add a custom lexer: AlgPseudocodeLexer with custom init
    # option "no_end".
    #
    # In modern Sphinx versions given lexer must be callable and may
    # not be a lexer instance. So use an indirection with "partial"
    # here.
    #
    app.add_lexer("noend-algpseudocode",
                  partial(AlgPseudocodeLexer, no_end=True))

Note

Lexers in Sphinx are instantiated with the raiseonerror filter applied by default. This is also true for custom lexers that are added by Sphinx.add_lexer(). Using the filters option the user can associate custom filters with a lexer. These filters have precedence over the default raiseonerror filter.

Lexer instances that are added to sphinx.highlighting.lexers somehow are taken as is by Sphinx and are not augmented with any default filters.

See also chapter Filters.

For older Sphinx versions your mileage may vary.

Some Examples

Synthetic Example

The first example is a synthetic example with many features.

Its source code is in examples/example-1.pseudocode.

PROGRAM The Pseudocode Lexer IS

  /*
   * The program is here, but it also could be an \ALGORITHM
   *
   * /* YES! Nested multi-line comments work! */
   */

  PROCEDURE A Procedure name IS A text block 1
    ▪ A text block 2 with a nested expression: flag is FALSE 
        ▷  A remark on its own line within a "BLOCK"
    
  END OF PROCEDURE A Procedure name

  FUNCTION A Function with {escaped} text IS
    (1234567890  what) or a and b xor (c in d)   ▷ this is another remark foo is not bar 2 + 6 = 1 (mod 7)

    IF a is nil THEN
      Set something
    ELSE IF
      Set some other thing
    END IF
  END OF FUNCTION A Function with {escaped} text

  CLASS A Class IS
    // This is a one-line comment
    a and b xor (c in d)      ▷ this is another remark

    # This is another one-line comment

    (* Here is a "block" of expressions.
       A block has a leading symbol. *) foo  bar
      Bär  Maus
        and Bär  Maus a 1.2 {x in X} c
    (* Analogous there is a variant that is in text-mode by default.
       It has an other leading symbol. *) We will compute next a xor b or (set X is Empty) ▷ without c!
      or multiply it the \ttx-ges/other/ way.

    ▪ foo bar     ▷ A remark within a text statement until LF!
      nextfoo nextbar
      nextnextfoo nextnextbar
  END OF CLASS A Class

  @A_XXX
  FOO BAR
END OF PROGRAM

The highlighted output with a customized AlgPseudocodeLexer and its no_end option set to True:

PROGRAM The Pseudocode Lexer IS

  /*
   * The program is here, but it also could be an \ALGORITHM
   *
   * /* YES! Nested multi-line comments work! */
   */

  PROCEDURE A Procedure name IS A text block 1
    ▪ A text block 2 with a nested expression: flag is FALSE 
        ▷  A remark on its own line within a "BLOCK"
    
  

  FUNCTION A Function with {escaped} text IS
    (1234567890  what) or a and b xor (c in d)   ▷ this is another remark foo is not bar 2 + 6 = 1 (mod 7)

    IF a is nil THEN
      Set something
    ELSE IF
      Set some other thing
    
  

  CLASS A Class IS
    // This is a one-line comment
    a and b xor (c in d)      ▷ this is another remark

    # This is another one-line comment

    (* Here is a "block" of expressions.
       A block has a leading symbol. *) foo  bar
      Bär  Maus
        and Bär  Maus a 1.2 {x in X} c
    (* Analogous there is a variant that is in text-mode by default.
       It has an other leading symbol. *) We will compute next a xor b or (set X is Empty) ▷ without c!
      or multiply it the \ttx-ges/other/ way.

    ▪ foo bar     ▷ A remark within a text statement until LF!
      nextfoo nextbar
      nextnextfoo nextnextbar
  

  @A_XXX
  FOO BAR

Dinic’s Algorithm

The second example is Wikipedia’s description of Dinic’s Algorithm (see https://en.wikipedia.org/wiki/Dinic%27s_algorithm).

Its source code is in examples/algorithm-dinic.pseudocode.

ALGORITHM Dinic's Algorithm WITH
  Input: A network G = ((V , E), c, s, t).
  Output: An st flow f of maximum value.
IS
  1. Set f(e) = 0 for each e  E.
  2. Construct G_L from G_f of G.
     If dist(t) = , stop and output f.
  3. Find a blocking flow f' in G_L.
  4. Augment flow f by f' and go back to step 2.
END OF ALGORITHM

Ford–Fulkerson Algorithm

The third example is Wikipedia’s pseudocode of the Ford–Fulkerson Algorithm (see https://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm).

Its source code is in examples/algorithm-ford-fulkerson.pseudocode.

ALGORITHM Ford–Fulkerson WITH
  Inputs: Given a network G = (V, E) with flow capacity c, a source node s, and a sink node t
  Output: Compute a flow f from s to t of maximum value
IS
  1. f(u, v)  0 for all edges (u, v)

  2. While there is a path p from s to t in G_f,
     such that c_f(u, v) > 0 for all edges (u, v)  p:

     1. Find c_f(p) = min{c_f(u, v): (u, v)  p}

     2. For each edge (u, v)  p

        1. f(u, v)  f(u, v) + c_f(p)   ▷ Send flow along the path

	2. f(v, u)  f(v, u) - c_f(p)   ▷ The flow might be "returned" later

END OF ALGORITHM Ford–Fulkerson

Edmonds–Karp Algorithm

The fourth example is Wikipedia’s pseudocode of the Edmonds–Karp Algorithm (see https://en.wikipedia.org/wiki/Edmonds%E2%80%93Karp_algorithm) with a custom lexer which skips all ENDxxx keywords.

Its source code is in examples/algorithm-edmonds-karp.pseudocode.

ALGORITHM Edmonds–Karp WITH
    Input: 
      graph:  graph[v] should be the list of edges coming out of vertex v in the
              original graph and their corresponding constructed reverse edges
              which are used for push-back flow.
              Each edge should have a capacity cap, flow, source s and sink t 
              as parameters, as well as a pointer to the reverse edge rev.
      s:      Source vertex
      t:      Sink vertex
    Output: 
      flow:  Value of maximum flow)
IS
    flow ∶= 0
    REPEAT
        /* Run a breadth-first search (bfs) to find the shortest s-t path.
           We use 'pred' to store the edge taken to get to each vertex,
           so we can recover the path afterwards. */
        q ∶= queue()
        q.push(s)
        pred ∶= array(graph.length)
        WHILE not empty(q) and pred[t] = null DO
            cur ∶= q.pop()
            FOR Edge e in graph[cur] DO
                IF pred[e.t] = null and e.t  s and e.cap > e.flow THEN
                    pred[e.t] ∶= e
                    q.push(e.t)
                
            
        
        IF not (pred[t] = null) THEN
            /* We found an augmenting path.
               See how much flow we can send */
            df ∶= 
            FOR (e ∶= pred[t]; e  null; e ∶= pred[e.s]) DO
                df ∶= min(df, e.cap - e.flow)
            
            /* And update edges by that amount */
            FOR (e ∶= pred[t]; e  null; e ∶= pred[e.s]) DO
                e.flow  ∶= e.flow + df
                e.rev.flow ∶= e.rev.flow - df
            
            flow ∶= flow + df
        
    UNTIL pred[t] = null      ▷ i.e., until no augmenting path was found
    RETURN flow

And now the Edmonds–Karp Algorithm with french keywords:

ALGORITHME Edmonds–Karp AVEC
    Input: 
      graph:  graph[v] should be the list of edges coming out of vertex v in the
              original graph and their corresponding constructed reverse edges
              which are used for push-back flow.
              Each edge should have a capacity cap, flow, source s and sink t 
              as parameters, as well as a pointer to the reverse edge rev.
      s:      Source vertex
      t:      Sink vertex
    Output: 
      flow:  Value of maximum flow)
EST
    flow ∶= 0
    RÉPÉTER
        /* Run a breadth-first search (bfs) to find the shortest s-t path.
           We use 'pred' to store the edge taken to get to each vertex,
           so we can recover the path afterwards. */
        q ∶= queue()
        q.push(s)
        pred ∶= array(graph.length)
        TANTQUE not empty(q) and pred[t] = null FAIRE
            cur ∶= q.pop()
            POUR Edge e in graph[cur] FAIRE
                SI pred[e.t] = null and e.t  s and e.cap > e.flow ALORS
                    pred[e.t] ∶= e
                    q.push(e.t)
                END IF
            FIN POUR
        FIN TANTQUE
        SI not (pred[t] = null) ALORS
            /* We found an augmenting path.
               See how much flow we can send */
            df ∶= 
            POUR (e ∶= pred[t]; e  null; e ∶= pred[e.s]) FAIRE
                df ∶= min(df, e.cap - e.flow)
            FIN POUR
            /* And update edges by that amount */
            POUR (e ∶= pred[t]; e  null; e ∶= pred[e.s]) FAIRE
                e.flow  ∶= e.flow + df
                e.rev.flow ∶= e.rev.flow - df
            FIN POUR
            flow ∶= flow + df
        END IF
    JUSQUACEQUE pred[t] = null      ▷ i.e., until no augmenting path was found
    RENVOYER flow
FIN D'ALGORITHME Edmonds–Karp

And again the Edmonds–Karp Algorithm with german keywords:

ALGORITHMUS Edmonds–Karp MIT
    Input: 
      graph:  graph[v] should be the list of edges coming out of vertex v in the
              original graph and their corresponding constructed reverse edges
              which are used for push-back flow.
              Each edge should have a capacity cap, flow, source s and sink t 
              as parameters, as well as a pointer to the reverse edge rev.
      s:      Source vertex
      t:      Sink vertex
    Output: 
      flow:  Value of maximum flow)
IST
    flow ∶= 0
    WIEDERHOLE
        /* Run a breadth-first search (bfs) to find the shortest s-t path.
           We use 'pred' to store the edge taken to get to each vertex,
           so we can recover the path afterwards. */
        q ∶= queue()
        q.push(s)
        pred ∶= array(graph.length)
        SOLANGE not empty(q) and pred[t] = null DO
            cur ∶= q.pop()
            FÜR Edge e in graph[cur] DO
                WENN pred[e.t] = null and e.t  s and e.cap > e.flow DANN
                    pred[e.t] ∶= e
                    q.push(e.t)
                ENDE WENN
            ENDE FÜR
        ENDE SOLANGE
        WENN not (pred[t] = null) DANN
            /* We found an augmenting path.
               See how much flow we can send */
            df ∶= 
            FÜR (e ∶= pred[t]; e  null; e ∶= pred[e.s]) DO
                df ∶= min(df, e.cap - e.flow)
            ENDE FÜR
            /* And update edges by that amount */
            FÜR (e ∶= pred[t]; e  null; e ∶= pred[e.s]) DO
                e.flow  ∶= e.flow + df
                e.rev.flow ∶= e.rev.flow - df
            ENDE FÜR
            flow ∶= flow + df
        ENDE WENN
    BIS pred[t] = null      ▷ i.e., until no augmenting path was found
    RETURN flow
ENDE DES ALGORITHMUS Edmonds–Karp