Skip to content

Latest commit

 

History

History
83 lines (62 loc) · 3.05 KB

pn.md

File metadata and controls

83 lines (62 loc) · 3.05 KB

The Puppet Extended S-Expression Notation (PN)

Objective

The primary objective for this format is to provide a short but precise human readable format of the puppet language AST. This format is needed to write tests that verifies the parser's function.

Another objective is to provide easy transport of the AST using JSON or similar data formats that are constrained to boolean, number, string, undef, array, and object data types. The PN conversion to Data was specifically designed with this objective in mind.

Format

A PN forms a directed acyclig graph of nodes. There are five types of nodes:

  • Literal: A boolean, integer, float, string, or undef
  • List: An ordered list of nodes
  • Map: An ordered map of string to node associations
  • Call: A named list of nodes.

PN represented as Data

A PN can represent itself as the Puppet Data type and will then use the following conversion rules:

PN Node Data type
Literal Boolean, Integer, Float, String, and Undef
List Array[Data]
Map Struct['#', Array[Data]]
Call Struct['^', Tuple[String[1], Data, 1]]

The Map is converted into a single element Hash with using the key '#' and then an array with an even number of elements where an evenly positioned element is the key for the value at the next position. The reason for this is that JSON (and other formats) will not retain the order of a hash and in Puppet that order is significant.

A Call is similar to a Map but uses the key '^'. The first element of the associated array is the name of the function and any subsequent elements are arguments to that function.

PN represented as String

The native textual representation of a PN is similar to Clojure.

PN Node Sample string representation
Literal boolean true, false
Literal integer 834, -123, 0
Literal float 32.28, -1.0, 33.45e18
Literal string "plain", "quote \\"", "tab \\t", "return \\r", "newline \\n", "control \\u{14}"
Literal undef nil
List ["a" "b" 32 true]
Map {:a 2 :b 3 :c true}
Call (myFunc 1 2 "b")

PN represented as JSON or YAML

When representing PN as JSON or YAML, it must first be converted to Data as described in section PN represented as Data above.

Examples:

PN class PN JSON
List [1, 2, "a"] [1, 2, "a"]
Map {:a 2 :b 3 :c true} { "#": ["a", 2, "b", 3, "c", true] }
Call (myFunc 1 2 "b") { "^": [ "myFunc", 1, 2, "b" ] }

Puppet Expression transformed into PN and JSON

The Abstract Syntax Tree (AST) that is the result of parsing a Puppet Expression can be transformed into a PN.

Examples:

Puppet Expression PN JSON
1 + 2 * 3 (+ 1 (* 2 3)) { "^": [ "+", 1, { "^": [ "*", 2, 3 ]} ]}
a * (2 + 3) (* (qn "a") (paren (+ 2 3))) { "^": [ "*", { "^": [ "paren", { "^": [ "+", 1, 2 ]} ]} ]}
"hello ${var}" (concat "hello " (str (var "var"))) { "^": [ "concat", "hello ", { "^": [ "str", { "^": [ "var", "var" ]} ]} ]}