Author image Jürgen Weigert
and 1 contributors


License::Syntax - Coding and Decoding of License strings using SPDX and SUSE syntax.


Version 0.13


This implements the SUSE License Syntax.

    use License::Syntax;

    my $obj = new License::Syntax licensemap => 'licenselist.csv;as';
    my $obj = new License::Syntax map => { 'GNU General Public License V2.0' => 'GPLv2' };
    my $obj = new License::Syntax 'pathname.sqlite;table(alias,name)';
    $obj->loadmap_sqlite($filename_sqlite, $table_name, $alias_col, $name_col);
    $obj->savemap_csv($filename_csv, scalar(localtime));
    $obj->savemap_sqlite($filename_sqlite, $table_name, $alias_col, $name_col, 'TRUNCATE');
    $obj->add_alias($alias, $canonical_name);
    $name = $obj->canonical_name($alias, $disambiguate);
    $tree = $obj->tokenize('GPLv2 & Apache 1.1; LGPLv2.1 | BSD4c<<ex(UCB); Any Noncommercial', $disambiguate);
    $name = $obj->format_tokens($tree);



License::Syntax is an object oriented module. When constructing new License::Syntax objects, you can provide a mapping table for license names. The table is used for recognizing alternate alias names for the licenses (left hand side) and also defines the canonical short names of the licenses (right hand side). The mapping table is consulted twice, before and after decoding the syntax. (Thus non-terminal mappings may actually be followed.)

The mapping table can be provided either

  • as a CSV files of two columns. Column seperator is a comma (,)

  • as a hash, or

  • as table in an sqlite database using the given columns as left hand side and right hand side respectivly.

As an alternative to specifying a mapping with new(), or additionally, mappings can also be provided via loadmap_sqlite(), loadmap_csv(), or add_alias() methods. Earlier mappings take precedence over later mappings.


    $name = $obj->canonical_name($alias);
is equivalent to
    $name = $obj->format_tokens($obj->tokenize($alias));


$obj->savemap_csv('filename.csv', scalar(localtime));

Writes the current mapping table as a comma seperated file.


$obj->set_rejects('REJECT', ...);

define the license names to be rejected. Per default, exactly one name 'REJECT' is rejected.


$obj->add_alias($alias,$name); $obj->add_alias(undef,$name); $obj->add_alias('',$name);

adds $name (and optionally $alias) to the objects licensemap. Both, lower case and exact mappings are maintained. (add_url is used in loadmap_csv)

add_alias() takes care to extend to the right. That is, if it's right hand side parameter is already known to be an alias, the new alias is added pointing to the old alias's canonical name (rahter than to the old alias that the caller provided).

CAVEAT: add_alias() does not maintain full tranitivity, as it does not extend to the left. If its left hand side is already known to be a canonical name, a warning is issued, but the situation cannot be corrected, as this would require rewriting existing entries. This is non-obvious, as mappings are applied more than once during format_tokens(), so indirect mappings involving non-terminal names, may or may not work. A two step mapping currently works reliably, though.

add_alias() does nothing, if it would directly redo an existing mapping.

See also new() for more details about mappings.


$obj->add_url($urls, $name);

Add one or multiple URLs to the canonical license name. URLs can be seperated by comma or whitespace. May be called multiple times for the same name, and fills an array of urls. (add_url is used in loadmap_csv)

set_compat_class $obj->set_compat_class($cc, $name);

Specify the compatibility class, for a canonical license name. compatibility classes are numerical. These classes allow to derive certain compatibility issues amongst liceses. Some classes are always incompatible (even amongst themselves), other classes are always comaptible, and for some other classses, compatibility is uncertain. The exact semantics are to be defined. (set_compat_class is used in loadmap_csv).


$obj->savemap_sqlite('filename.sqlite', 'lic_map', 'alias', 'shortname', $trunc_flag);

        # sqlite3 filename.sqlite
        sqlite> select * from lic_map
        alias | shortname

If $trunc_flag is true and the table previously exists, the table is truncated before it is written to; otherwise new contents merges over old contents, if any.


See also new() for more details about mappings.


$tree_arr = $obj->tokenize($complex_license_expr); $tree_arr = $obj->tokenize($complex_license_expr, 1);

Returns an array reference containing tokens and sub-arrays, describing how the $complex_license_expr is parsed. If a second parameter disambiguate is provided and is true, extra parenthesis are inserted to unambiguiusly show how the complex expression is interpreted. If names have been loaded with add_alias, before calling tokenize, all names and aliases are recognized as one token. E.g. "GPL 2.0 or later" would be split as ["GPL 2.0", "or", "later"] otherwise. No name mapping is performed here.


reverse operation of tokenize()


$obj->loadmap_csv('license_map.csv', 'as'); $obj->loadmap_csv('synopsis.csv', 'lauaas#c');

Object method to load (or merge) contents of a CVS table into the object. This uses a trivial csv parser. Field seperator must be ; linebreaks are record seperators, and the first line is ignored, if it starts with '#'. Fields can be surrounded by doublequotes, if a comma may be embedded.

The second parameter is a field template, defining what the meaning of the fields is. l Long name (none or once). This is a speaking name of the License: Example "Creative Commons Attribution 1.0" a Alias name (any number). Any other name by which the license is known: Example: "CC-BY 1.0" s Short name (once). The canonical (unique) short license identifiner: Example: "CC-BY-1" u URL (any). Multiple URLs can also be written in one filed, seperated by whitespace. # License classification number (none or once). (1..5) c Comment (none or once) The default template is "as", an alias, followed by the canonical short name. Empty fields are ignored, as well as fields that contian only one '?'. Thus you can use records like "","Name" to pass in a valid name without an alias.

See also new() for more details about mappings.


Juergen Weigert, <jw at>


This module defines a different syntax than

Please report any bugs or feature requests to bug-rpm-license at, or through the web interface at I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.


You can find documentation for this module with the perldoc command.

    perldoc License::Syntax

You can also look for information at:



Copyright 2009 Juergen Weigert.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See for more information.