File: parslet.rb

package info (click to toggle)
ruby-toml 0.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 296 kB
  • sloc: ruby: 666; sh: 7; makefile: 4
file content (114 lines) | stat: -rw-r--r-- 3,341 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
module TOML
  class Parslet < ::Parslet::Parser
    rule(:document) {
      all_space >>
      (comment_line | table | table_array | key_value).repeat >>
      all_space
    }
    root :document

    rule(:value) {
      array |
      string |
      datetime.as(:datetime) |
      datetime_rfc3339.as(:datetime_rfc3339) |
      float.as(:float) |
      integer.as(:integer) |
      boolean
    }

    # Finding comments in multiline arrays requires accepting a bunch of
    # possible newlines and stuff before the comment
    rule(:array_comments) { (all_space >> comment_line).repeat }

    rule(:array) {
      str("[") >> all_space >> array_comments >>
      ( array_comments >> # Match any comments on first line
        all_space >> value >> array_comments >>
        (
          # Separator followed by any comments
          all_space >> str(",") >> array_comments >>
          # Value followed by any comments
          all_space >> value >> array_comments
        ).repeat >>
        (all_space >> str(",")).maybe >> # possible trailing comma
        all_space >> array_comments # Grab any remaining comments just in case
      ).maybe.as(:array) >> str("]")
    }

    rule(:key_value) {
      space >> key.as(:key) >>
      space >> str("=") >>
      space >> value.as(:value) >>
      space >> comment.maybe >> newline >> all_space
    }
    rule(:table) {
      space >> str("[") >>
        table_name.as(:table) >>
      str("]") >>
      space >> comment.maybe >> newline >> all_space
    }
    rule(:table_array) {
      space >> str("[[") >>
        table_name.as(:table_array) >>
      str("]]") >>
      space >> comment.maybe >> str("\n") >> all_space
    }

    rule(:key) { match["^. \t\\]"].repeat(1) }
    rule(:table_name) { key.as(:key) >> (str(".") >> key.as(:key)).repeat }

    rule(:comment_line) { comment >> newline >> all_space }
    rule(:comment) { str("#") >> match["^\n"].repeat }

    rule(:space) { match[" \t"].repeat }
    rule(:all_space) { match[" \t\r\n"].repeat }
    rule(:newline) { str("\r").maybe >> str("\n") | str("\r") >> str("\n").maybe }

    rule(:string) {
      str('"') >> (
      match["^\"\\\\"] |
      (str("\\") >> match["0tnr\"\\\\"])
      ).repeat.as(:string) >> str('"')
    }

    rule(:sign) { str("-") }
    rule(:sign?) { sign.maybe }

    rule(:integer) {
      str("0") | sign? >>
      (match["1-9"] >> (match["_"].maybe >> match["0-9"]).repeat)
    }
    rule(:float) {
      sign? >>
      (match["0-9"] >> (match["_"].maybe >> match["0-9"]).repeat) >> str(".") >>
      (match["0-9"] >> (match["_"].maybe >> match["0-9"]).repeat)
    }

    rule(:boolean) { str("true").as(:true) | str("false").as(:false) }

    rule(:date) {
      match["0-9"].repeat(4,4) >> str("-") >>
      match["0-9"].repeat(2,2) >> str("-") >>
      match["0-9"].repeat(2,2)
    }

    rule(:time) {
      match["0-9"].repeat(2,2) >> str(":") >>
      match["0-9"].repeat(2,2) >> str(":") >>
      match["0-9"].repeat(2,2)
    }

    rule(:timezone) {
      match["0-9"].repeat(2,2) >> str(":") >>
      match["0-9"].repeat(2,2)
    }

    rule(:datetime) { date >> str("T") >> time >> str("Z") }

    rule(:datetime_rfc3339) {
      # rfc3339 section 5.6 allows replacing 'T' with a space.
      date >> (str("T") | str(" ")) >> time >> (str("+") | str("-")) >> timezone
    }
  end
end