// Atlas Grammar
// ============
//
// Based on the JSON example Grammar from PEG.js examples
//

Atlas_text = ws value:value ws { return value; }

begin_object    = ws "(" ws
end_object      = ws ")" ws
name_separator  = ws "=" ws
value_separator = ws "," ws

ws "whitespace" = [ \t\n\r]*

// ----- Values -----

value = false / null / true / object / array / number / stringval / class / empty

empty = "" { return undefined; }
null  = "None"  { return null;  }
false = "False" { return false; }
true  = "True"  { return true;  }

// ----- Objects -----

object
  = begin_object
    members:(
      head:member
      tail:(value_separator m:member { return m; })*
      {
        var result = {};

        [head].concat(tail).forEach(function(element) {
          result[element.name] = element.value;
        });

        return result;
      }
    )?
    end_object
    { return members !== null ? members: {}; }

member
  = name:stringkey name_separator value:value {
      return { name: name, value: value };
    }

// ----- Arrays -----

array
  = begin_object
    values:(
      head:value
      tail:(value_separator v:value { return v; })*
      { return [head].concat(tail); }
    )?
    end_object
    { return values !== null ? values : []; }

// ----- Numbers -----

number "number"
  = minus? int frac? exp? { return parseFloat(text()); }

decimal_point
  = "."

digit1_9
  = [1-9]

e
  = [eE]

exp
  = e (minus / plus)? DIGIT+

frac
  = decimal_point DIGIT+

int
  = zero / (digit1_9 DIGIT*)

minus
  = "-"

plus
  = "+"

zero
  = "0"

// ----- Strings -----

stringkey "string key" = sequence:keychar* { return sequence.join(""); }

stringval "string value"
  = quotation_mark chars:char* quotation_mark { return chars.join(""); }

class = key:stringkey singlequote_mark chars:pathchar* singlequote_mark { return [ key, chars.join("") ]; }

keychar =  sequence:( [a-zA-Z0-9] / "_" ) { return sequence; }

pathchar = sequence:(
         [a-zA-Z0-9]
        / "_"
        / "."
        / "/"
    )
    { return sequence; }

char
  = unescaped
  / escape
    sequence:(
        '"'
      / "\\"
      / "/"
      / "b" { return "\b"; }
      / "f" { return "\f"; }
      / "n" { return "\n"; }
      / "r" { return "\r"; }
      / "t" { return "\t"; }
      / "u" digits:$(HEXDIG HEXDIG HEXDIG HEXDIG) {
          return String.fromCharCode(parseInt(digits, 16));
        }
    )
    { return sequence; }

escape
  = "\\"

quotation_mark
  = '"'

singlequote_mark = "'"

unescaped
  = [^\0-\x1F\x22\x5C]

// ----- Core ABNF Rules -----

// See RFC 4234, Appendix B (http://tools.ietf.org/html/rfc4234).
DIGIT  = [0-9]
HEXDIG = [0-9a-f]i