/ccs-cpp

CCS in C++

Primary LanguageC++MIT LicenseMIT

Build status Code coverage GitHub release GitHub license

CCS for C++

This is the C++ implementation of CCS.

CCS is a language for config files, and libraries to read those files and configure applications. The documentation is currently quite poor, but the Java and C++ implementations are mature and have been used in production for many years.

There's a presentation about the language here, but it's a little sketchy without someone talking along with it.

Building

CCS is built with CMake. You can set the usual options to control your compiler, build type, etc., but the crash course is:

$ git submodule update --init
$ mkdir build
$ cd build
$ cmake ..
$ make

You can run unit tests with pretty output using:

$ make unittest

CMake can install everything for you, but in any case the client-facing headers are in the api directory.

Syntax quick reference

@context (a.b c, d)

Sets "context" for the rest of the ruleset. Must appear prior to any other rules. Equivalent to:

a.b c, d { /* rest of file */ }

name = 123

Property definition. Property name will have the specified value in the current context. The syntax of values is conventional: true, false, 64-bit signed integers (may be specified in hex as 0x1a2bc), doubles, and strings.

'name with spaces' = 'value'

name may be enclosed in quotes and written as a string literal if it contains spaces or other non-identifier characters.

@override name = 123

Overriding property definition. For a given property, any definition marked @override will take precedence over any normal definition, regardless of the relative specificities of the two definitions. If more than one @override definition applies in a particular context, the most specific wins.

'VAR: ${VAR}'
"literal: ${VAR}"

Strings may be enclosed in single or double quotes. Environment variables may be interpolated with ${VAR}. Special characters may be escaped with a backslash. Recognized escape sequences include: \t \n \r \' \" \\ \$. A string may be broken across multiple lines by ending a line with a single backslash.

'double: ", single: ''
"double: ", single: '"

The non-delimiting quote character need not be escaped.

@import "..."
a b.c d : @import "..."

Import a ruleset into the current ruleset. The entire imported ruleset will be nested in the current context, so for example the second example above further constrains all imported settings to the context a b.c d.

@constrain a/b.c/d.e.f

Further constrain the context. This is equivalent to further constraining the context using the context.constrain(...) API call.

Of course, this is most useful when applied only in a particular selected context, in which case it allows for some additional reuse and modularity within CCS rulesets (activating additional sets of rules in particular cases, for example).

selector : @import "..."
selector : @constrain ...
selector : name = value
selector { rules }

Constrain rules to apply only in the selected context. rule is any of: an import, a property setting, a constraint, or a selector and further nested rules. Selector syntax is documented below...

a.b.c

Matches a constraint of type a with values b and c. Note that this matches only a single constraint with both values. Multiple constraints of the same type are allowed (thus preserving monotonicity), so a.b.c is not equivalent to a.b a.c in every case.

a/c

Rarely needed.

Matches a simultaneous occurence of constraints of type a and type c. Again, this is not generally equivalent to a c, as it only matches when the two constraints are applied in the same single step.

a.b c.d
a.b, c.d
a.b > c.d

Conjunction, disjunction, and descendant selection, respectively. The first form matches in any context containing both a.b and c.d. The second matches in any context containing either one.

The third form matches in any context containing c.d, itself in a context containing a.b. This form is infrequently used in CCS (although it is of course the default operator in CSS).

Precedence of operators is as follows, from highest to lowest:

  • > (descendant)
  • juxtaposition (conjunction)
  • , (disjunction)

Parentheses may be used to enforce grouping. So, for example, a, c > d e is equivalent to a, ((c > d) e). Since > is infrequently used, the rules are generally simple and intuitive.

Note that rules may be separated by semicolons for clarity, but this is always completely optional and will never affect the way the ruleset is parsed.

TODO

  • Aggregate values: lists, maps.
  • For aggregate values, allow modification of inherited value as well as replacement??