File: parsley.parsley

package info (click to toggle)
python-parsley 1.3-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,048 kB
  • sloc: python: 9,897; makefile: 127
file content (115 lines) | stat: -rw-r--r-- 3,915 bytes parent folder | download | duplicates (2)
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
115
comment = '#' (~'\n' anything)*
hspace = ' ' | '\t' | comment
vspace =  '\r\n' | '\r' | '\n'
ws = (hspace | vspace | comment)*

emptyline = hspace* vspace
indentation = emptyline* hspace+
noindentation = emptyline* ~~~hspace

number = ws
               ('-' barenumber:x  -> t.Exactly(-x, span=self.getSpan())
                    |barenumber:x -> t.Exactly(x, span=self.getSpan()))
barenumber = '0' (('x'|'X') <hexdigit+>:hs -> int(hs, 16)
                    |<octaldigit+>:ds -> int(ds, 8))
               |<digit+>:ds -> int(ds)
octaldigit = :x ?(x in '01234567' ) -> x
hexdigit = :x ?(x in '0123456789ABCDEFabcdef') -> x

escapedChar = '\\' ('n' -> "\n"
                     |'r' -> "\r"
                     |'t' -> "\t"
                     |'b' -> "\b"
                     |'f' -> "\f"
                     |'"' -> '"'
                     |'\'' -> "'"
                     |'x' <hexdigit hexdigit>:d -> chr(int(d, 16))
                     |'\\' -> "\\")

character = ws '\'' (~'\'' (escapedChar | anything))+:c
            ws '\'' -> t.Exactly(''.join(c), span=self.getSpan())

string = ws '"' (escapedChar | ~('"') anything)*:c
         ws '"' -> t.Token(''.join(c), span=self.getSpan())

name = <letter ('_' |letterOrDigit)*>

args = ('(' !(self.applicationArgs(finalChar=')')):args ')'
            -> args
          | -> [])

application = indentation? name:name args:args
                -> t.Apply(name, self.rulename, args, span=self.getSpan())

foreignApply = indentation? name:grammar_name '.' name:rule_name args:args
                -> t.ForeignApply(grammar_name, rule_name, self.rulename, args, span=self.getSpan())

traceable = !(self.startSpan())
          (  foreignApply
          | application
          | ruleValue
          | semanticPredicate
          | semanticAction
          | number:n !(self.isTree()) -> n
          | character
          | string)

expr1 = traceable
      | ws '(' expr:e ws ')' -> e
      | ws '<' expr:e ws '>'
         -> t.ConsumedBy(e)
      | ws '[' expr?:e ws ']' !(self.isTree())
         -> t.List(e) if e else t.List()

expr2 = (ws '~' ('~' expr2:e -> t.Lookahead(e)
                |    expr2:e -> t.Not(e)
                )
        |expr1)

repeatTimes = (barenumber:x -> int(x)) | name

expr3 = (expr2:e
                      ('*' -> t.Many(e)
                      |'+' -> t.Many1(e)
                      |'?' -> t.Optional(e)
                      |customLabel:l -> t.Label(e, l)
                      |'{' ws repeatTimes:start ws (
                      (',' ws repeatTimes:end ws '}'
                           -> t.Repeat(start, end, e))
                         | ws '}'
                           -> t.Repeat(start, start, e))
                      | -> e
)):r
           (':' name:n -> t.Bind(n, r)
           | ':(' name:n (',' ws name)*:others ws ')'
                (-> [n] + others if others else n):n -> t.Bind(n, r)
           | -> r)
          |ws ':' name:n
          -> t.Bind(n, t.Apply("anything", self.rulename, []))

expr4 = expr3+:es -> es[0] if len(es) == 1 else t.And(es)

expr = expr4:e (ws '|' expr4)*:es
          -> t.Or([e] + es) if es else e

ruleValue = ws '->' -> self.ruleValueExpr(True)

customLabel = (ws '^' ws '(' <(~')' anything)+>:e ')' -> e) ^ (customLabelException)

semanticPredicate = ws '?(' -> self.semanticPredicateExpr()

semanticAction = ws '!(' -> self.semanticActionExpr()

ruleEnd = ((hspace* vspace+) | end) ^ (rule end)

rulePart :requiredName = noindentation name:n ?(n == requiredName)
                            !(setattr(self, "rulename", n))
                            expr4?:args
                            (ws '=' expr:e ruleEnd
                               -> t.And([args, e]) if args else e
                            | ruleEnd -> args)

rule = noindentation ~~(name:n) rulePart(n)+:rs -> t.Rule(n, t.Or(rs))


grammar = rule*:rs ws -> t.Grammar(self.name, self.tree_target, rs)