added CHANGELOG.md
 
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [0.0.2] - 2023-07-24
6
+
7
+ ### Bug Fixes
8
+
9
+ - Allow warnings
10
+ - Formatting
11
+
12
+ ### Features
13
+
14
+ - Add identifiers (names)
15
+ - Support reserved identifiers
16
+ - Add keywords
17
+ - Add punctuation
18
+ - Add operators
19
+
20
+ ### Refactor
21
+
22
+ - Make sections obvious
23
+
24
+ ## [0.0.1] - 2023-07-20
25
+
26
+ ### Bug Fixes
27
+
28
+ - Register lexer correctly
29
+
30
+ ### Features
31
+
32
+ - Add `Makeup.Lexer` boilerplate implementation
33
+ - Add literals, comments, whitespace
34
+
35
+ ### Miscellaneous Tasks
36
+
37
+ - Generate new mix project
38
+ - Prepare for publishing
39
+ - Add CI
40
+ - Add format config
41
+ - Add ex_doc package
42
+
43
+ ### Refactor
44
+
45
+ - Remove unused combinators
46
+
47
+ <!-- generated by git-cliff -->
changed hex_metadata.config
 
@@ -7,7 +7,7 @@
7
7
<<"lib/makeup/lexers/swift_lexer.ex">>,<<"lib/makeup/lexers/swift_lexer">>,
8
8
<<"lib/makeup/lexers/swift_lexer/testing.ex">>,
9
9
<<"lib/makeup/lexers/swift_lexer/application.ex">>,<<".formatter.exs">>,
10
- <<"mix.exs">>,<<"README.md">>,<<"LICENSE">>]}.
10
+ <<"mix.exs">>,<<"README.md">>,<<"LICENSE">>,<<"CHANGELOG.md">>]}.
11
11
{<<"licenses">>,[<<"MIT">>]}.
12
12
{<<"links">>,[{<<"GitHub">>,<<"https://github.com/jesse-c/makeup_swift">>}]}.
13
13
{<<"name">>,<<"makeup_swift">>}.
 
@@ -22,4 +22,4 @@
22
22
{<<"optional">>,false},
23
23
{<<"repository">>,<<"hexpm">>},
24
24
{<<"requirement">>,<<"~> 1.3">>}]]}.
25
- {<<"version">>,<<"0.0.1">>}.
25
+ {<<"version">>,<<"0.0.2">>}.
changed lib/makeup/lexers/swift_lexer.ex
 
@@ -19,7 +19,9 @@ defmodule Makeup.Lexers.SwiftLexer do
19
19
20
20
@inline Application.compile_env(:makeup_html, :inline, false)
21
21
22
+ # -----------------------------------------------------------------------------
22
23
# Lines
24
+ # -----------------------------------------------------------------------------
23
25
24
26
# LF/U+000A
25
27
line_feed = ascii_char([?\n])
 
@@ -33,10 +35,14 @@ defmodule Makeup.Lexers.SwiftLexer do
33
35
concat(line_feed, carriage_return)
34
36
])
35
37
38
+ # -----------------------------------------------------------------------------
36
39
# Whitespace
40
+ # -----------------------------------------------------------------------------
41
+
37
42
whitespace_item = [?\r, ?\s, ?\n, ?\f]
38
43
whitespace = whitespace_item |> ascii_string(min: 1) |> token(:whitespace)
39
44
45
+ # -----------------------------------------------------------------------------
40
46
# Literals
41
47
#
42
48
# A literal is the source code representation of a value of a type, such as a number or string.
 
@@ -48,6 +54,7 @@ defmodule Makeup.Lexers.SwiftLexer do
48
54
# "Hello, world!" // String literal
49
55
# /Hello, .*/ // Regular expression literal
50
56
# true // Boolean literal
57
+ # -----------------------------------------------------------------------------
51
58
52
59
## String
53
60
quoted_text_item = utf8_string([], 1)
 
@@ -102,7 +109,10 @@ defmodule Makeup.Lexers.SwiftLexer do
102
109
numeric_literal
103
110
])
104
111
112
+ # ------------------------------------------------------------------------------
105
113
# Comments
114
+ # ------------------------------------------------------------------------------
115
+
106
116
comment_text = utf8_string([], 1)
107
117
108
118
## Inline
 
@@ -119,7 +129,73 @@ defmodule Makeup.Lexers.SwiftLexer do
119
129
|> many_surrounded_by("/*", "*/")
120
130
|> token(:comment_multiline)
121
131
132
+ # -----------------------------------------------------------------------------
133
+ # Identifiers
134
+ # -----------------------------------------------------------------------------
135
+
136
+ backtick = utf8_char([?`])
137
+
138
+ identifier_head = utf8_char([?a..?z, ?A..?Z, ?_])
139
+
140
+ identifier_character = choice([identifier_head, utf8_char([?0..?9])])
141
+
142
+ identifier_characters = repeat(identifier_character)
143
+
144
+ identifier =
145
+ optional(backtick)
146
+ |> concat(identifier_head)
147
+ |> concat(optional(identifier_characters))
148
+ |> concat(optional(backtick))
149
+ |> token(:name)
150
+
151
+ # -----------------------------------------------------------------------------
152
+ # Keywords
153
+ # -----------------------------------------------------------------------------
154
+
155
+ @keywords_declarations ~w[associatedtype class deinit enum extension fileprivate func import init inout internal let open operator private precedencegroup protocol public rethrows static struct subscript typealias var]
156
+ @keywords_statements ~w[break case catch continue default defer do else fallthrough for guard if in repeat return throw switch where while]
157
+ @keywords_expressions_and_types ~w[Any as await catch false is nil rethrows self Self super throw throws true try]
158
+ @keywords_begin_with_a_number_sign ~w[#available #colorLiteral #elseif #else #endif #if #imageLiteral #keyPath #selector #sourceLocation]
159
+ @keywords List.flatten([
160
+ @keywords_declarations,
161
+ @keywords_statements,
162
+ @keywords_expressions_and_types,
163
+ @keywords_begin_with_a_number_sign
164
+ ])
165
+
166
+ keyword =
167
+ @keywords
168
+ |> word_from_list()
169
+ # A naïve way to avoid identifiers of reserved keywords
170
+ |> lookahead_not(backtick)
171
+ |> token(:keyword)
172
+
173
+ # -----------------------------------------------------------------------------
174
+ # Punctuation
175
+ # -----------------------------------------------------------------------------
176
+
177
+ punctuation =
178
+ choice([
179
+ ascii_char([?(, ?), ?{, ?}, ?[, ?], ?., ?,, ?:, ?;, ?=, ?@, ?#, ?&, ?`, ??, ?!]),
180
+ string("->")
181
+ ])
182
+ |> token(:punctuation)
183
+
184
+ # -----------------------------------------------------------------------------
185
+ # Operators
186
+ # -----------------------------------------------------------------------------
187
+
188
+ operator_head = ascii_char([?/, ?=, ?-, ?+, ?!, ?*, ?%, ?<, ?>, ?&, ?|, ?^, ?~, ??])
189
+ operator_character = operator_head
190
+ operator_characters = operator_character |> concat(optional(operator_character))
191
+ operator = operator_head |> concat(optional(operator_characters)) |> token(:operator)
192
+ infix_operator = operator
193
+ prefix_operator = operator
194
+ postfix_operator = operator
195
+
196
+ # -----------------------------------------------------------------------------
122
197
# Root
198
+ # -----------------------------------------------------------------------------
123
199
124
200
root_element_combinator =
125
201
choice([
 
@@ -129,20 +205,30 @@ defmodule Makeup.Lexers.SwiftLexer do
129
205
literal,
130
206
# Comments
131
207
inline_comment,
132
- multiline_comment
208
+ multiline_comment,
209
+ # Keywords,
210
+ keyword,
211
+ # Identifiers
212
+ identifier,
213
+ # Punctuation
214
+ punctuation,
215
+ # Operators
216
+ infix_operator,
217
+ prefix_operator,
218
+ postfix_operator
133
219
])
134
220
135
- @doc false
136
- def __as_swift_language__({ttype, meta, value}) do
137
- {ttype, Map.put(meta, :language, :swift), value}
138
- end
139
-
140
221
##############################################################################
141
222
# Semi-public API: these two functions can be used by someone who wants to
142
223
# embed this lexer into another lexer, but other than that, they are not
143
224
# meant to be used by end-users
144
225
##############################################################################
145
226
227
+ @doc false
228
+ def __as_swift_language__({ttype, meta, value}) do
229
+ {ttype, Map.put(meta, :language, :swift), value}
230
+ end
231
+
146
232
@impl Makeup.Lexer
147
233
defparsec(
148
234
:root_element,
changed mix.exs
 
@@ -4,7 +4,7 @@ defmodule MakeupSwift.MixProject do
4
4
def project do
5
5
[
6
6
app: :makeup_swift,
7
- version: "0.0.1",
7
+ version: "0.0.2",
8
8
elixir: "~> 1.14",
9
9
start_permanent: Mix.env() == :prod,
10
10
deps: deps(),