/
expensivecamera.st
149 lines (124 loc) · 3.57 KB
/
expensivecamera.st
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"
Expensivecamera to JavaScript parser+translator
2013 Minori Yamashita <ympbyc@gmail.com>
"
| Packrat |
Packrat := require value: '../lib/Packrat'.
Packrat subclass:#Excam variables: #().
!Excam space
self cache: #space aParser: [
self regex: (RegExp new: '^[\\s\\n\\t]+')]!.
!Excam skipSpace
self optional: [self space]!.
!Excam symbol
self cache: #symbol aParser: [
self regex: (RegExp new: '^[a-zA-Z_$][a-zA-Z0-9_$]*')]!.
!Excam identifier
self cache: #identifier aParser: [
self many1:[self satisfyChar: [ :c | (c search: </[\s\n\t\(\)]/>) === -1 ]]]!.
!Excam equal
self cache: #equal aParser: [
self string: '==']!.
!Excam rightArrow
self cache: #rightArrow aParser: [
self string: '->']!.
!Excam lambda
self cache: #lambda aParser: [
self between: [ self chr: '[' ]
and: [ self skipSpace. self chr:']' ]
accept: [
self try_: #(
[|s| s := 'function () { return ' + self expression + ' }'. self skipSpace. self followedBy:[self chr:']']. s]
[self lambdaBody ])]]!.
!Excam lambdaBody
"Curry"
self cache: #lambdaBody aParser: [| exp |
self skipSpace.
self try_: #(
[| f |
f := 'function (' + self symbol + ') { return '.
self skipSpace.
self rightArrow.
f += (self lambdaBody + ' }').
f]
[self expression])]!.
!Excam primary
self cache: #primary aParser: [
self try_: #(
[self symbol]
[self literal]
[self lambda])]!.
!Excam selector
self cache: #selector aParser: [
self chr: '.'.
'\'' + self identifier + '\'']!.
!Excam methodInvocation
self cache: #methodInvocation aParser: [| selector arg |
self skipSpace.
selector := self selector.
arg := self optional: [self space. self expression].
self skipSpace.
'[' + selector + '](' + arg + ')']!.
!Excam funcall
self cache: #funcall aParser: [| arg |
self skipSpace.
arg := self expression.
'(' + arg + ')']!.
!Excam message
"function application inclusive-or method invocation"
self cache: #message aParser: [| receiver mes |
self chr: '('.
self skipSpace.
receiver := self primary.
self space.
mes := self many: [
self try_: #(
[self methodInvocation]
[self funcall])].
self skipSpace.
self chr: ')'.
receiver + mes]!.
!Excam expression
self cache: #expression aParser: [
self try_: #(
[ self message ]
[ self primary ])]!.
!Excam numberLit
self cache: #numberLit aParser: [
self regex: (RegExp new: '^-?[0-9]+(\\.?[0-9]+)?')]!.
!Excam stringLit
self cache: #stringLit aParser: [| str |
str := (self
between: [self chr: '\'']
and: [self chr: '\'']
accept: [| c |
c := self anyChar.
c === '\\' ifTrue: [c + self anyChar]
ifFalse:[ c ]]).
str := str rep:</\n/g> lace:'\\n'.
'\'' + str + '\'']!.
!Excam literal
self cache: #literal aParser: [
self try_: #(
[self numberLit]
[self stringLit])]!.
!Excam declaration
self cache: #declaration aParser: [| v exp |
self skipSpace.
v := self symbol.
self skipSpace.
self string: '=='.
self skipSpace.
exp := self expression.
'var ' + v + ' = ' + exp + ';']!.
!Excam program
self cache: #program aParser: [| decs exp |
decs := self many: [self declaration].
self skipSpace.
exp := (self optional: [self expression]) || ''.
decs + exp]!.
Excam at: #parse put: [ :str | | excam |
excam := Excam new: str.
excam program].
module at: #exports put: Excam.
Excam