-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy patheg_phone_num.py
78 lines (64 loc) · 2.23 KB
/
eg_phone_num.py
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
"""
The phone-number example at the top of
https://github.com/modernserf/little-language-lab
"""
from parson import Grammar
# const join = (...values) => values.join("")
# const phone = lang`
# Root = ~("+"? "1" _)? AreaCode ~(_ "-"? _) Exchange ~(_ "-"? _) Line
# ${(areaCode, exchange, line) => ({ areaCode, exchange, line })}
# AreaCode = "(" _ (D D D ${join}) _ ")" ${(_, __, digits) => digits}
# | D D D ${join}
# Exchange = D D D ${join}
# Line = D D D D ${join}
# D = %digit
# _ = %whitespace*
# `
# phone.match("+1 (800) 555-1234")
# // { ok: true, value: { areaCode: "800", exchange: "555", line: "1234" } }
# Version 1: just gimme the data.
grammar1 = r"""
Root : ('+'? '1' _)? AreaCode _ '-'? _ Exchange _ '-'? _ Line.
AreaCode : '(' _ {D D D} _ ')'
| {D D D}.
Exchange : {D D D}.
Line : {D D D D}.
D = /\d/.
_ = /\s*/.
"""
g1 = Grammar(grammar1)()
## g1.Root("+1 (800) 555-1234")
#. ('800', '555', '1234')
# Version 2, returning a dict.
# We have to pass the dict constructor in as a semantic parameter, since
# Python lacks template strings.
grammar2 = r"""
Root : ('+'? '1' _)? AreaCode _ '-'? _ Exchange _ '-'? _ Line :hug :dict.
AreaCode : :'areaCode' ('(' _ {D D D} _ ')'
| {D D D}) :hug.
Exchange : :'exchange' {D D D} :hug.
Line : :'line' {D D D D} :hug.
D = /\d/.
_ = /\s*/.
"""
parse_phone_number2 = Grammar(grammar2)(dict=dict).Root.expecting_one_result()
## parse_phone_number2("+1 (800) 555-1234")
#. {'areaCode': '800', 'line': '1234', 'exchange': '555'}
# Version 3, more my usual style.
# (Pass in semantic actions for the main productions
# and avoid the _ noise using a FNORD production.)
from structs import Struct
class PhoneNumber(Struct('area_code exchange line')):
pass
grammar3 = r"""
Root : /[+]?1/? AreaCode '-'? Exchange '-'? Line :PhoneNumber.
AreaCode : '(' AreaDigits ')' | AreaDigits.
AreaDigits ~: /(\d\d\d)/.
Exchange ~: /(\d\d\d)/.
Line ~: /(\d\d\d\d)/.
FNORD ~: /\s*/.
"""
g3 = Grammar(grammar3)(PhoneNumber=PhoneNumber)
parse_phone_number3 = g3.Root.expecting_one_result()
## parse_phone_number3("+1 (800) 555-1234")
#. PhoneNumber('800', '555', '1234')