mvsk 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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: []