mvsk 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d25c6ee53316bfdf1a6b23855d7df851b1db4ab27dc8d08b3564bc03e05dabf
4
- data.tar.gz: 2e892657a1b4c1cbb43f5843b380af172d0e9c2a9b50ef656a0f4743ca47660b
3
+ metadata.gz: f04de2ea639c5201033077c0853085693663dcb0c8ffe2bcc4dde87ae0824fc2
4
+ data.tar.gz: 609ab7ff6ef10298d6d263a77b6594f4575e16c967116ace4bc2d4c328ab5fb5
5
5
  SHA512:
6
- metadata.gz: ddf0fa19233e74a7165e37cc867bf2829971f18ebd353e253cf4338ea790387fb0722b080740fb9d309b99aa561f65dbd2e6eaa83035da7ee11a83e2cd4006ee
7
- data.tar.gz: e9e5e64332ab975c498782d94bd84efb4a0265d3cfa20a7087c6b3a4b7fba5547466d46da08615ca524a80f5cc2cc9bf2311957be836d903951c01fede0a7ecf
6
+ metadata.gz: 25dd4c8a0a1a9891f287ec03bfe849556994e5c6ba34e374cf2abd01d2e38f949d8fd766b7f190735bb132b15d4c79ff0b9755f9b4d997db35bd2ead960a9535
7
+ data.tar.gz: 8691243c770fb63eb12eb502a9dbd09b7448d6d7808b0ca5680efa7868f639916b358533fa89a5b1f102faac7c1cc591908ab38eb2565443219326c5cf2f7015
data/bin/mvsk ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ require 'musk'
3
+
4
+ args = ARGV.reject { |s| s.start_with?('-') }
5
+ opts = ARGV - args
6
+
7
+ if args.length == 1 and opts.empty?
8
+ Musk.run_file(args.first)
9
+ elsif ARGV.length.zero?
10
+ Musk.run_prompt
11
+ else
12
+ require 'pastel'
13
+ require 'optparse'
14
+
15
+ OptionParser.new do |op|
16
+ op.version = Musk::VERSION
17
+ op.banner = <<~USAGE
18
+ #{0}
19
+
20
+ Usage:
21
+
22
+ mvsk <file> [options]
23
+
24
+ Options:
25
+ USAGE
26
+
27
+ op.on '--tokens', 'print tokens' do
28
+ puts 'tokens'
29
+ end
30
+
31
+ op.on '--nodes', 'print nodes' do
32
+ puts 'nodes'
33
+ end
34
+
35
+ op.summary_width = 22
36
+
37
+ if args.length > 1
38
+ puts op
39
+ exit
40
+ end
41
+ end.parse!
42
+ end
@@ -0,0 +1,27 @@
1
+ module Musk
2
+ class Lexer
3
+ module Helper
4
+ def is_alpha_numeric(char)
5
+ is_alpha(char) || is_digit(char)
6
+ end
7
+
8
+ def is_alpha(char)
9
+ ('A' <= char && char <= 'Z') ||
10
+ ('a' <= char && char <= 'z') ||
11
+ ('_' == char)
12
+ end
13
+
14
+ def is_digit(char)
15
+ '0' <= char && char <= '9'
16
+ end
17
+
18
+ def is_bool(str)
19
+ str == 'true' || str == 'false'
20
+ end
21
+
22
+ def is_nil(str)
23
+ str == 'nil'
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,51 @@
1
+ module Musk
2
+ class Lexer
3
+ module Keywords
4
+ RESERVED_WORDS = {
5
+ :if => Token::If,
6
+ :else => Token::Else,
7
+ :switch => Token::Switch,
8
+ :case => Token::Case,
9
+ :default => Token::Default,
10
+ :for => Token::For,
11
+ :in => Token::In,
12
+ :loop => Token::Loop,
13
+ :break => Token::Break,
14
+ :continue => Token::Continue,
15
+ :class => Token::Class,
16
+ :extends => Token::Extends,
17
+ :super => Token::Super,
18
+ :self => Token::Self,
19
+ :get => Token::Get,
20
+ :set => Token::Set,
21
+ :fun => Token::Fun,
22
+ :return => Token::Return,
23
+ :let => Token::Let,
24
+ :mut => Token::Mut,
25
+ :and => Token::And,
26
+ :or => Token::Or,
27
+ :is => Token::Is,
28
+ :not => Token::Not,
29
+ :import => Token::Import,
30
+ :as => Token::As,
31
+ :throw => Token::Throw,
32
+ :try => Token::Try
33
+ }
34
+ end
35
+ end
36
+ end
37
+
38
+ # var tokens = [...]string{
39
+ # Int: "<int>",
40
+ # Float: "<float>",
41
+ # Identifier: "Identifier",
42
+ # String: "<string>",
43
+ # Rune: "<rune>",
44
+ # Bool: "<bool>",
45
+ # Nil: "nil",
46
+ # HashBang: "#!",
47
+ # Pipeline: "|>",
48
+ # Tilde: "~",
49
+ # Println: "println",
50
+ # Illegal: "Illegal",
51
+ # EOF: "EOF",
data/lib/musk/lexer.rb ADDED
@@ -0,0 +1,309 @@
1
+ require 'musk/lexer/keywords'
2
+ require 'musk/lexer/helper'
3
+
4
+ module Musk
5
+ class Lexer
6
+ include Helper
7
+ include Keywords
8
+
9
+ attr_reader :tokens
10
+
11
+ def initialize(code)
12
+ @tokens = []
13
+ @input = code
14
+ @line = 1
15
+ @start = 0
16
+ @current = 0
17
+ end
18
+
19
+ def scan_tokens
20
+ until at_end?
21
+ @start = @current
22
+ scan_token
23
+ end
24
+
25
+ add_token(Token::EOF, '')
26
+ @tokens
27
+ end
28
+
29
+ def next_token
30
+ until at_end?
31
+ @start = @current
32
+ break if scan_token
33
+ end
34
+
35
+ @token_i = 0 if @token_i.nil?
36
+ @token_i += 1
37
+
38
+ if @token_i <= @tokens.size
39
+ @tokens.last
40
+ else
41
+ nil
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def scan_token
48
+ char = advance
49
+
50
+ return false if skip_whitespace(char)
51
+ return false if skip_comment(char)
52
+
53
+ single_token(char) ||
54
+ double_token(char) ||
55
+ triple_token(char) ||
56
+ string_token(char) ||
57
+ number_token(char) ||
58
+ identifier_token(char)
59
+ end
60
+
61
+ def skip_whitespace(char)
62
+ if char == "\n"
63
+ @line += 1
64
+ return true
65
+ end
66
+
67
+ char == "\r" ||
68
+ char == "\t" ||
69
+ char == ' '
70
+ end
71
+
72
+ def skip_comment(char)
73
+ if char == '/' && match?('/')
74
+ until peek == "\n" || at_end?
75
+ advance
76
+ end
77
+
78
+ true
79
+ else
80
+ false
81
+ end
82
+ end
83
+
84
+ def identifier_token(char)
85
+ if is_alpha(char)
86
+ while is_alpha_numeric(peek)
87
+ advance
88
+ end
89
+
90
+ lexeme = @input[@start...@current]
91
+
92
+ if is_bool(lexeme)
93
+ add_token_bool(lexeme)
94
+ elsif is_nil(lexeme)
95
+ add_token(Token::Nil, 'nil')
96
+ else
97
+ if type = RESERVED_WORDS[lexeme.to_sym]
98
+ add_token(type, lexeme)
99
+ else
100
+ add_token(Token::Identifier, lexeme)
101
+ end
102
+ end
103
+
104
+ true
105
+ else
106
+ add_token(Token::Illegal, nil, "unexpected '#{char}'")
107
+ false
108
+ end
109
+ end
110
+
111
+ def string_token(char)
112
+ if char == '"'
113
+ until peek == '"' || at_end?
114
+ if peek == "\n"
115
+ @line += 1
116
+ end
117
+
118
+ advance
119
+ end
120
+
121
+ if at_end?
122
+ add_token(Token::Illegal, nil, 'unterminated string')
123
+ return false
124
+ end
125
+
126
+ advance
127
+ add_token_string(@input[@start...@current])
128
+
129
+ true
130
+ else
131
+ false
132
+ end
133
+ end
134
+
135
+ def number_token(char)
136
+ if is_digit(char)
137
+ while is_digit(peek)
138
+ advance
139
+ end
140
+
141
+ if peek == '.' && is_digit(peek_next)
142
+ advance
143
+
144
+ while is_digit(peek)
145
+ advance
146
+ end
147
+
148
+ add_token_float(@input[@start...@current])
149
+ else
150
+ add_token_int(@input[@start...@current])
151
+ end
152
+
153
+ true
154
+ else
155
+ false
156
+ end
157
+ end
158
+
159
+ def single_token(char)
160
+ case char
161
+ when '+' then add_token(Token::Plus)
162
+ when '-' then add_token(Token::Minus)
163
+ when '*' then add_token(Token::Star)
164
+ when '/' then add_token(Token::Slash)
165
+ when '%' then add_token(Token::Modulo)
166
+ when ',' then add_token(Token::Comma)
167
+ when ':' then add_token(Token::Colon)
168
+ when ';' then add_token(Token::Semi)
169
+ when '.' then add_token(Token::Dot)
170
+ when '{' then add_token(Token::LeftBrace)
171
+ when '}' then add_token(Token::RightBrace)
172
+ when '[' then add_token(Token::LeftSquare)
173
+ when ']' then add_token(Token::RightSquare)
174
+ when '(' then add_token(Token::LeftParen)
175
+ when ')' then add_token(Token::RightParen)
176
+ else
177
+ return false
178
+ end
179
+
180
+ true
181
+ end
182
+
183
+ def double_token(char)
184
+ case char
185
+ when '!'
186
+ if match?('=')
187
+ add_token(Token::BangEq)
188
+ else
189
+ add_token(Token::Bang)
190
+ end
191
+ when '='
192
+ if match?('=')
193
+ add_token(Token::EqualEq)
194
+ else
195
+ add_token(Token::Equal)
196
+ end
197
+ when '>'
198
+ if match?('=')
199
+ add_token(Token::GreaterEq)
200
+ else
201
+ add_token(Token::Greater)
202
+ end
203
+ when '<'
204
+ if match?('=')
205
+ add_token(Token::LessEq)
206
+ else
207
+ add_token(Token::Less)
208
+ end
209
+ when '?'
210
+ if match?('.')
211
+ add_token(Token::QuestionDot)
212
+ else
213
+ add_token(Token::Question)
214
+ end
215
+ else
216
+ return false
217
+ end
218
+
219
+ true
220
+ end
221
+
222
+ def triple_token(char)
223
+ case char
224
+ when '&'
225
+ if match?('&')
226
+ if match?('=')
227
+ add_token(Token::Illegal)
228
+ else
229
+ add_token(Token::And)
230
+ end
231
+ else
232
+ add_token(Token::BitwiseAnd)
233
+ end
234
+ when '|'
235
+ if match?('|')
236
+ if match?('=')
237
+ add_token(Token::Illegal)
238
+ else
239
+ add_token(Token::Or)
240
+ end
241
+ else
242
+ if match?('>')
243
+ add_token(Token::Pipeline)
244
+ else
245
+ add_token(Token::BitwiseOr)
246
+ end
247
+ end
248
+ else
249
+ return false
250
+ end
251
+
252
+ true
253
+ end
254
+
255
+ def add_token_bool(lexeme)
256
+ value = lexeme.eql?('true')
257
+ add_token(Token::Bool, lexeme, value)
258
+ end
259
+
260
+ def add_token_string(lexeme)
261
+ value = lexeme[1, lexeme.length - 2]
262
+ add_token(Token::String, lexeme, value)
263
+ end
264
+
265
+ def add_token_float(lexeme)
266
+ add_token(Token::Float, lexeme, lexeme.to_f)
267
+ end
268
+
269
+ def add_token_int(lexeme)
270
+ add_token(Token::Int, lexeme, lexeme.to_i)
271
+ end
272
+
273
+ def add_token(type, lexeme = nil, literal = nil)
274
+ lexeme = @input[@start...@current] if lexeme.nil?
275
+ @tokens.push(Token.new(type, lexeme, literal, @line))
276
+ end
277
+
278
+ def match?(char)
279
+ return false if at_end?
280
+ return false if @input[@current] != char
281
+
282
+ @current += 1
283
+ true
284
+ end
285
+
286
+ def peek
287
+ return "\0" if at_end?
288
+ @input[@current]
289
+ end
290
+
291
+ def peek_next
292
+ if @current + 1 < @input.length
293
+ @input[@current + 1]
294
+ else
295
+ "\0"
296
+ end
297
+ end
298
+
299
+ def advance
300
+ char = @input[@current]
301
+ @current += 1
302
+ char
303
+ end
304
+
305
+ def at_end?
306
+ @current >= @input.length
307
+ end
308
+ end
309
+ end
data/lib/musk/nodes.rb ADDED
@@ -0,0 +1,214 @@
1
+ module Musk
2
+ module Nodes
3
+ class Node
4
+ def accept(visitor)
5
+ raise NotImplementedError
6
+ end
7
+ end
8
+
9
+ class Program < Node; end
10
+ class Expression < Node; end
11
+ class Statement < Node; end
12
+ class Declaration < Statement; end
13
+
14
+ class BlockStatement < Statement
15
+ attr_reader :statements
16
+
17
+ def initialize(statements:)
18
+ @statements = statements
19
+ end
20
+
21
+ def accept(visitor)
22
+ visitor.visit_block_stmt(self)
23
+ end
24
+ end
25
+
26
+ class IfStatement < Statement
27
+ # // Condition Expression
28
+ # // Then Statement
29
+ # // Else Statement
30
+ end
31
+
32
+ class ForStatement < Statement
33
+ end
34
+
35
+ class LoopStatement < Statement
36
+ # // Condition Expression
37
+ # // Body Statement
38
+ end
39
+
40
+ class ContinueStatement < Statement
41
+ # Label Expression
42
+ end
43
+
44
+ class BreakStatement < Statement
45
+ # Label Expression
46
+ end
47
+
48
+ class ReturnStatement < Statement
49
+ attr_reader :keyword, :value
50
+
51
+ def initialize(keyword:, value:)
52
+ @keyword = keyword
53
+ @value = value
54
+ # Argument Expression
55
+ end
56
+
57
+ def accept(visitor)
58
+ visitor.visit_return_stmt(self)
59
+ end
60
+ end
61
+
62
+ class ExpressionStatement < Statement
63
+ attr_reader :expression
64
+
65
+ def initialize(expression:)
66
+ @expression = expression
67
+ end
68
+
69
+ def accept(visitor)
70
+ visitor.visit_expression_stmt(self)
71
+ end
72
+ end
73
+
74
+ class ClassDeclaration < Declaration
75
+ # // Name token.Token
76
+ # // Methods []ClassMethod
77
+ # // SuperClass *VariableExpression
78
+ end
79
+
80
+ class VariableDeclaration < Declaration
81
+ # // Name token.Token
82
+ # // Initializer Expression
83
+ end
84
+
85
+ class FunctionDeclaration < Declaration
86
+ attr_reader :name, :params, :body
87
+
88
+ def initialize(name:, params:, body:)
89
+ @name = name
90
+ @params = params
91
+ @body = body
92
+ end
93
+
94
+ def accept(visitor)
95
+ visitor.visit_function_stmt(self)
96
+ end
97
+ end
98
+
99
+ class Function < Expression
100
+ attr_reader :params, :body
101
+
102
+ def initialize(params:, body:)
103
+ @params = params
104
+ @body = body
105
+ end
106
+ end
107
+
108
+ class Assignment < Expression
109
+ # Operator token.Token
110
+ # Right Expression
111
+ # Left Expression
112
+ # //> expr-assign
113
+ # static class Assign extends Expr {
114
+ # Assign(Token name, Expr value) {
115
+ # this.name = name;
116
+ # this.value = value;
117
+ # <R> R accept(Visitor<R> visitor) {
118
+ # return visitor.visitAssignExpr(this);
119
+ # final Token name;
120
+ # final Expr value;
121
+ end
122
+
123
+ # type Variable struct {
124
+ # Name string
125
+ # Expression
126
+ # }
127
+
128
+ # type Identifier struct {
129
+ # Name string
130
+ # Expression
131
+ # }
132
+
133
+ class Call < Expression
134
+ attr_reader :callee, :args
135
+
136
+ def initialize(callee:, args:)
137
+ @callee = callee
138
+ @args = args
139
+ # final Token paren;
140
+ # this.paren = paren;
141
+ end
142
+
143
+ def accept(visitor)
144
+ visitor.visit_call_expr(self)
145
+ end
146
+ end
147
+
148
+ class Logical < Expression
149
+ attr_reader :left, :operator, :right
150
+
151
+ def initialize(left:, operator:, right:)
152
+ @left = left
153
+ @operator = operator
154
+ @right = right
155
+ end
156
+
157
+ def accept(visitor)
158
+ visitor.visit_logical_expr(self)
159
+ end
160
+ end
161
+
162
+ class Grouping < Expression
163
+ attr_reader :expr
164
+
165
+ def initialize(expr:)
166
+ @expr = expr
167
+ end
168
+
169
+ def accept(visitor)
170
+ visitor.visit_grouping_expr(self)
171
+ end
172
+ end
173
+
174
+ class Binary < Expression
175
+ attr_reader :left, :operator, :right
176
+
177
+ def initialize(left:, operator:, right:)
178
+ @left = left
179
+ @operator = operator
180
+ @right = right
181
+ end
182
+
183
+ def accept(visitor)
184
+ visitor.visit_binary_expr(self)
185
+ end
186
+ end
187
+
188
+ class Unary < Expression
189
+ attr_reader :operator, :right
190
+
191
+ def initialize(operator:, right:)
192
+ @operator = operator
193
+ @right = right
194
+ end
195
+
196
+ def accept(visitor)
197
+ visitor.visit_unary_expr(self)
198
+ end
199
+ end
200
+
201
+ class Literal < Expression
202
+ attr_reader :type, :value
203
+
204
+ def initialize(type:, value:)
205
+ @type = type
206
+ @value = value
207
+ end
208
+
209
+ def accept(visitor)
210
+ visitor.visit_literal_expr(self)
211
+ end
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,170 @@
1
+ module Musk
2
+ class Parser
3
+ def initialize(tokens)
4
+ @tokens = tokens
5
+ @current = 0
6
+ end
7
+
8
+ def parse
9
+ statements = []
10
+ statements.push(declaration) until at_end?
11
+ # statements.add(statement());
12
+ statements
13
+ end
14
+
15
+ private
16
+
17
+ def declaration
18
+ begin
19
+ # if (match(CLASS)) return classDeclaration();
20
+ # if (match(FUN)) return function("function");
21
+ # if (match(VAR)) return varDeclaration();
22
+ statement
23
+ rescue ParseError
24
+ synchronize
25
+ nil
26
+ end
27
+ end
28
+
29
+ def statement
30
+ return if_statement if match?(Token::If)
31
+ return for_statement if match?(Token::For)
32
+ return loop_statement if match?(Token::Loop)
33
+ return return_statement if match?(Token::Return)
34
+
35
+ # if (match(LEFT_BRACE)) return new Stmt.Block(block());
36
+ # return expressionStatement();
37
+ end
38
+
39
+ # private Stmt expressionStatement() {
40
+ # Expr expr = expression();
41
+ # consume(SEMICOLON, "Expect ';' after expression.");
42
+ # return new Stmt.Expression(expr);
43
+ # }
44
+
45
+
46
+ def synchronize
47
+ advance
48
+
49
+ until at_end?
50
+ return if previous.type == Token::Semi
51
+ return if peek.type == Token::Class
52
+ return if peek.type == Token::Fun
53
+ return if peek.type == Token::Return
54
+ return if peek.type == Token::Let
55
+ return if peek.type == Token::If
56
+ return if peek.type == Token::Switch
57
+ return if peek.type == Token::For
58
+ return if peek.type == Token::Loop
59
+
60
+ advance
61
+ end
62
+ end
63
+
64
+
65
+ def expression
66
+ assignment
67
+ end
68
+
69
+ def assignment
70
+
71
+ end
72
+
73
+ # private Expr unary() {
74
+ # if (match(BANG, MINUS)) {
75
+ # Token operator = previous();
76
+ # Expr right = unary();
77
+ # return new Expr.Unary(operator, right);
78
+ # }
79
+ # return call();
80
+ # }
81
+
82
+ def primary
83
+ return literal(previous) if match?(Token::Nil, Token::Bool)
84
+ return literal(previous) if match?(Token::Int, Token::Float)
85
+ return literal(previous) if match?(Token::String)
86
+
87
+ if match?(Token::Super)
88
+ # Token keyword = previous();
89
+ consume(Token::Dot, "expect '.' after 'super'")
90
+ method = consume(Token::Identifier, 'expect superclass method name')
91
+ return Nodes::Super.new()
92
+ # .(keyword, method);
93
+ # .{Method: tok.Value}
94
+ end
95
+
96
+ if match?(Token::Self)
97
+ return Nodes::Self.new(previous)
98
+ end
99
+
100
+ if match?(Token::Identifier)
101
+ # tok := p.previous()
102
+ # return ast.Variable{Name: tok.Value}
103
+ # return new Expr.Variable(previous());
104
+ end
105
+
106
+ if match?(Token::LeftParen)
107
+ exp = primary
108
+ # expr = expression();
109
+ consume(Token::RightParen, "expect ')' after expression")
110
+ return Nodes::Grouping.new(expr: exp)
111
+ end
112
+
113
+ # // panic(ParseError{token: p.peek(), message: "Expect expression"})
114
+ # panic("error")
115
+ # }
116
+ # throw error(peek(), "Expect expression.");
117
+ end
118
+
119
+ def literal(token)
120
+ Nodes::Literal.new(type: token.type, value: token.literal)
121
+ end
122
+
123
+ def consume(type, message)
124
+ return advance if check?(type)
125
+ error peek, message
126
+ raise ParseError
127
+ end
128
+
129
+ def error(tok, message)
130
+ if tok.type == Token::EOF
131
+ # report(token.line, " at end", message);
132
+ else
133
+ # report(token.line, " at '" + token.lexeme + "'", message);
134
+ end
135
+ end
136
+
137
+ def match?(*types)
138
+ types.each do |type|
139
+ if check?(type)
140
+ advance
141
+ return true
142
+ end
143
+ end
144
+
145
+ false
146
+ end
147
+
148
+ def check?(type)
149
+ return false if at_end?
150
+ peek.type == type
151
+ end
152
+
153
+ def advance
154
+ @current += 1 unless at_end?
155
+ previous
156
+ end
157
+
158
+ def previous
159
+ @tokens[@current - 1]
160
+ end
161
+
162
+ def peek
163
+ @tokens[@current]
164
+ end
165
+
166
+ def at_end?
167
+ peek.type == Token::EOF
168
+ end
169
+ end
170
+ end
data/lib/musk/token.rb ADDED
@@ -0,0 +1,48 @@
1
+ module Musk
2
+ class Token
3
+ class << self
4
+ def token_type(*types)
5
+ types.each do |type|
6
+ const_set type, type.to_s
7
+ end
8
+ end
9
+ end
10
+
11
+ attr_reader :type, :lexeme, :literal, :line
12
+
13
+ token_type :Plus, :Minus, :Star, :Slash, :Modulo,
14
+ :Comma, :Colon, :Semi, :Dot,
15
+ :LeftBrace, :RightBrace,
16
+ :LeftSquare, :RightSquare,
17
+ :LeftParen, :RightParen
18
+
19
+ token_type :Bang, :BangEq, :Equal, :EqualEq,
20
+ :Greater, :GreaterEq, :Less, :LessEq,
21
+ :BitwiseAnd, :BitwiseOr, :And, :Or,
22
+ :Question, :QuestionDot,
23
+ :Pipeline
24
+
25
+ token_type :Int, :Float, :String, :Char, :Bool, :Nil,
26
+ :Identifier, :Illegal, :EOF
27
+
28
+ token_type :If, :Else, :Switch, :Case, :Default,
29
+ :For, :In, :Loop, :Break, :Continue,
30
+ :Class, :Extends, :Super, :Self,
31
+ :Get, :Set, :Fun, :Return,
32
+ :Let, :Mut, :Is, :Not,
33
+ :Import, :As,
34
+ :Throw, :Try
35
+
36
+ def initialize(type, lexeme, literal = nil, line)
37
+ @type = type
38
+ @lexeme = lexeme
39
+ @literal = literal
40
+ @line = line
41
+ end
42
+
43
+ def to_s
44
+ return @type if @literal.nil?
45
+ "#{@type} #{@lexeme} #{@literal}"
46
+ end
47
+ end
48
+ end
data/lib/musk/types.rb ADDED
@@ -0,0 +1,24 @@
1
+ module Musk
2
+ module Types
3
+ class List
4
+ end
5
+
6
+ class Int
7
+ end
8
+
9
+ class Float
10
+ end
11
+
12
+ class String
13
+ end
14
+
15
+ class Char
16
+ end
17
+
18
+ class Bool
19
+ end
20
+
21
+ class Nil
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module Musk
2
+ VERSION = '1.0.2'
3
+ end
data/lib/musk.rb ADDED
@@ -0,0 +1,79 @@
1
+ require 'musk/version'
2
+ require 'musk/token'
3
+ require 'musk/lexer'
4
+ require 'musk/nodes'
5
+ require 'musk/parser'
6
+
7
+ module Musk
8
+ class ParseError < RuntimeError; end
9
+
10
+ module_function
11
+
12
+ def run_prompt
13
+ require 'pastel'
14
+ require 'readline'
15
+
16
+ stty_save = `stty -g`.chomp
17
+
18
+ begin
19
+ while buf = Readline.readline('> ', true)
20
+ break if buf.nil?
21
+ break if buf.strip == 'exit'
22
+
23
+ print run(buf), "\n"
24
+ # run(line); //> reset-had-error
25
+ # hadError = false;
26
+ end
27
+ rescue Interrupt
28
+ system 'stty', stty_save
29
+ ensure
30
+ puts
31
+ exit
32
+ end
33
+ end
34
+
35
+ def run_file(path)
36
+ if File.exist?(path) && File.file?(path)
37
+ puts 'fiasd'
38
+ else
39
+ warn "No such file #{path}"
40
+ end
41
+
42
+ # run(File.read(path))
43
+ # # if (hadError) System.exit(65);
44
+ # # if (hadRuntimeError) System.exit(70);
45
+ end
46
+
47
+ def run(code)
48
+ lexer = Lexer.new(code)
49
+ tokens = lexer.scan_tokens
50
+ tokens.each { |token| puts token }
51
+ end
52
+ end
53
+
54
+ # ["And",
55
+ # "Class",
56
+ # "Else",
57
+ # "False",
58
+ # "Fun",
59
+ # "For",
60
+ # "If",
61
+ # "Nil",
62
+ # "Or",
63
+ # "Print",
64
+ # "Return",
65
+ # "Super",
66
+ # "This",
67
+ # "True",
68
+ # "Var",
69
+ # "While"]
70
+ # Int
71
+ # Float
72
+ # Bool
73
+ # String
74
+ # Char
75
+ # Unit
76
+ # Tuple
77
+ # List
78
+ # Array
79
+ # Function
data/lib/mvsk.rb CHANGED
@@ -1,2 +1 @@
1
- module Musk
2
- end
1
+ # https://elm-lang.org/docs/syntax
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mvsk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - razeos at tossdev
@@ -9,13 +9,38 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2023-07-18 00:00:00.000000000 Z
12
- dependencies: []
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pastel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.8.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.8.0
13
27
  description:
14
28
  email:
15
- executables: []
29
+ executables:
30
+ - mvsk
16
31
  extensions: []
17
32
  extra_rdoc_files: []
18
33
  files:
34
+ - bin/mvsk
35
+ - lib/musk.rb
36
+ - lib/musk/lexer.rb
37
+ - lib/musk/lexer/helper.rb
38
+ - lib/musk/lexer/keywords.rb
39
+ - lib/musk/nodes.rb
40
+ - lib/musk/parser.rb
41
+ - lib/musk/token.rb
42
+ - lib/musk/types.rb
43
+ - lib/musk/version.rb
19
44
  - lib/mvsk.rb
20
45
  homepage:
21
46
  licenses:
@@ -39,5 +64,5 @@ requirements: []
39
64
  rubygems_version: 3.1.2
40
65
  signing_key:
41
66
  specification_version: 4
42
- summary: mvsk at tossdev
67
+ summary: A simple programming language
43
68
  test_files: []