ascode 0.4.2 → 0.5.0

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: 15e393eaf5cfaef02c4bf415e82300e47d1210106ff2c30cdb38f39a3e0c931c
4
- data.tar.gz: 03f293c11dee276ec902a35ff51fd31ff7bee3057eb8cdff79de8b53ea576c32
3
+ metadata.gz: d7d02a2015c6ea648b76aedd3144765b8f130376016b865026aaae8f15a1fb38
4
+ data.tar.gz: fbc32bb909699a1ed819612b0f7e190d1d1c794bffffe7f5b653bffd1083fd23
5
5
  SHA512:
6
- metadata.gz: 3d8ebacbec4a7289af7ee40ec2cf15dd95cf4d052b43d3d88fa56594e6e52ff0698b5a0e4b0cd68f1ab5bacec5b1d5821d9d89d30b3e62e8c17456d49127d39e
7
- data.tar.gz: e79edd415b548b685571241ddab7b93f9976c560759381f84d1e94c99876707a219f085d46ca02ec55f5cb4d212320fb7bae42dee654dc4aa623a4fe4791c399
6
+ metadata.gz: 34f50589e7fb8dbee4c2c766611fc5ebd91c19fc7fd6c6eb82e80de0b5034d449fb50a6bb08efb4422d2b8bf707a03a0f46b173574bc35f5fca50fa10bdd79ad
7
+ data.tar.gz: b68e5200f7f82852ac04d74d85ed59a5ab40b0feadeec83048f6c411c406ae8062c8df2f2044717a2d3ffec1bd759786e421b19a3ec1a0796288594dee71da3a
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
1
  # ascode
2
2
  [![RubyGem Version](https://img.shields.io/gem/v/ascode.svg?style=flat-square)](https://rubygems.org/gems/ascode) [![RubyGem Downloads](https://img.shields.io/gem/dt/ascode.svg?style=flat-square)](https://rubygems.org/gems/ascode)
3
3
 
4
- > Esoteric golfing language
5
-
4
+ > **Esoteric golfing language**
6
5
  > In active development, so behavior may be changed without prior notice.
7
6
 
8
7
  - [Getting Started](#getting-started)
@@ -18,8 +17,8 @@ gem install ascode
18
17
 
19
18
  ###### Run
20
19
 
21
- Function documentation is available in [`lib/ascode/functions.md
22
- `](https://github.com/sudoio/ascode/blob/master/lib/ascode/functions.md).
20
+ Function reference is available in [`lib/ascode/parser/functions.md
21
+ `](https://github.com/sudoio/ascode/blob/master/lib/ascode/parser/functions.md).
23
22
 
24
23
  At this moment, the only way to play with `ascode` is `irb`.
25
24
 
@@ -37,5 +36,5 @@ irb(main):003:0> Ascode.run "1.1*"
37
36
 
38
37
  ### Features
39
38
  - Implicit input/output
40
- - If you did not output anything, `>` (`output` function) will be called at the end of the program.
41
- - During `pop`, if the value is not in the stack, it will be grabbed via `<` (`input` function).
39
+ - If you did not output anything, `O` (`output` function) will be called at the end of the program.
40
+ - During `pop`, if the value is not in the stack, it will be grabbed via `I` (`input` function).
@@ -0,0 +1,67 @@
1
+ module Ascode
2
+ module Parser
3
+ class ConditionBlock
4
+ attr_reader :block
5
+
6
+ def initialize(code, block_begin)
7
+ @code = code
8
+ @begin = block_begin + 1
9
+
10
+ @true = ""
11
+ @false = ""
12
+ end
13
+
14
+ def parse
15
+ @block = @code[@begin..-1]
16
+
17
+ @end = find "]"
18
+ raise "Unmatched '[' detected." if @end == -1
19
+
20
+ @block = @block[0..(@end - 1)]
21
+
22
+ @split_pos = find ":"
23
+ split
24
+
25
+ ast_action
26
+ end
27
+
28
+ def find(what)
29
+ # TODO: Ignore '[', ':', ']' when in string
30
+ level = 0
31
+ @block.split("").to_enum.each_with_index do |char, index|
32
+ return index if char == what && level.zero?
33
+ level += 1 if char == "["
34
+ level -= 1 if char == "]"
35
+ end
36
+
37
+ -1
38
+ end
39
+
40
+ def split
41
+ if @split_pos == -1
42
+ @true = @block
43
+ elsif @split_pos.zero?
44
+ @false = @block
45
+ else
46
+ @true = @block[0..(@split_pos - 1)]
47
+ @false = @block[(@split_pos + 1)..-1]
48
+ end
49
+
50
+ @true = parse_part(@true)
51
+ @false = parse_part(@false)
52
+ end
53
+
54
+ def parse_part(part)
55
+ (Main.new part, false).parse
56
+ end
57
+
58
+ def ast_action
59
+ @ast = {
60
+ action: "condition",
61
+ true_block: @true,
62
+ false_block: @false
63
+ }
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,47 @@
1
+ module Ascode
2
+ module Parser
3
+ class Function
4
+ attr_reader :csv_data
5
+
6
+ def initialize
7
+ @csv_data = []
8
+
9
+ filename = File.join(File.dirname(__FILE__), "functions.md")
10
+ File.open(filename, "r") do |file|
11
+ read_csv file
12
+ end
13
+
14
+ @csv_data.delete_at 0
15
+ @csv_data.delete_at 0
16
+ end
17
+
18
+ def parse(char)
19
+ function = @csv_data.to_enum.find do |value|
20
+ value[:short] == char
21
+ end
22
+
23
+ raise "Unexpected function: '#{char}'" unless function
24
+
25
+ {
26
+ action: function[:long]
27
+ }
28
+ end
29
+
30
+ def read_csv(file)
31
+ until (line = file.gets).nil?
32
+ src = line.strip.split("|")
33
+
34
+ @csv_data.push(
35
+ short: clear_quotes(src[0]),
36
+ long: clear_quotes(src[1])
37
+ )
38
+ end
39
+ end
40
+
41
+ def clear_quotes(str)
42
+ return str unless str
43
+ str.delete("`")
44
+ end
45
+ end
46
+ end
47
+ end
@@ -4,7 +4,7 @@ Character|Name|`pop`s|`push`es|Description
4
4
  `O`|`output`|`a`||`a` -> `stdout`
5
5
  `P`|`pop`|`a`||
6
6
  `[`|`condition_begin`|`a`|| If `a` = `0`, `nil` or `false`, then part after `~` is executed
7
- `~`|`condition_else`|||
7
+ `:`|`condition_else`|||
8
8
  `]`|`condition_end`|||
9
9
  `+`|`plus`|`a`, `b`|`c`|`c` = `a` + `b`
10
10
  `-`|`minus`|`a`, `b`|`c`|`c` = `a` - `b`
@@ -0,0 +1,46 @@
1
+ require_relative "../converter"
2
+
3
+ module Ascode
4
+ module Parser
5
+ class Literal
6
+ attr_reader :literal
7
+
8
+ def initialize(code, literal_begin)
9
+ @code = code
10
+ @begin = literal_begin
11
+ end
12
+
13
+ def parse
14
+ @quoted = @code[@begin] == '"'
15
+ @begin += 1 if @quoted
16
+ @literal = @code[@begin..-1]
17
+
18
+ @end = find_end
19
+ @literal = @literal[0..(@end - 1)]
20
+
21
+ @literal = Converter.convert @literal
22
+ ast
23
+ end
24
+
25
+ def find_end
26
+ escape = false
27
+ @literal.split("").each_with_index do |char, index|
28
+ if @quoted
29
+ return index if char == '"' && !escape
30
+ escape = char == "\\"
31
+ else
32
+ return index unless char =~ /[0-9.]/
33
+ end
34
+ end
35
+ -1
36
+ end
37
+
38
+ def ast
39
+ @ast = {
40
+ action: "push",
41
+ what: @literal
42
+ }
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,67 @@
1
+ require_relative "condition_block"
2
+ require_relative "function"
3
+ require_relative "literal"
4
+
5
+ module Ascode
6
+ module Parser
7
+ class Main
8
+ def initialize(code, impl_o = true)
9
+ @function = Function.new
10
+ @code = code
11
+
12
+ @do_implicit_output = impl_o
13
+ end
14
+
15
+ def parse
16
+ @ast = []
17
+ @skip_chars = 0
18
+ @implicit_output = @do_implicit_output
19
+
20
+ @code.split("").to_enum.each_with_index do |char, index|
21
+ if @skip_chars > 0
22
+ @skip_chars -= 1
23
+ next
24
+ end
25
+
26
+ character char, index
27
+ end
28
+
29
+ @ast.push(action: "output") if @implicit_output
30
+
31
+ @ast
32
+ end
33
+
34
+ def character(char, index)
35
+ if char == "\""
36
+ literal(index, false)
37
+ elsif char =~ /[0-9.]/
38
+ literal(index, true)
39
+ elsif char == "["
40
+ block index
41
+ else
42
+ function char
43
+ end
44
+ end
45
+
46
+ def literal(index, num)
47
+ add = num ? 0 : 1
48
+
49
+ literal = Literal.new @code, index
50
+ @ast.push literal.parse
51
+ @skip_chars = literal.literal.to_s.length + add
52
+ end
53
+
54
+ def block(index)
55
+ block = ConditionBlock.new @code, index
56
+ @ast.push block.parse
57
+ @skip_chars = block.block.length
58
+ end
59
+
60
+ def function(char)
61
+ function = @function.parse char
62
+ @implicit_output = false if function[:action] == "output"
63
+ @ast.push function
64
+ end
65
+ end
66
+ end
67
+ end
data/lib/ascode.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  require_relative "ascode/interpreter"
2
- require_relative "ascode/parser"
2
+ require_relative "ascode/parser/main"
3
3
 
4
4
  module Ascode
5
5
  def self.run(code)
6
- parser = Parser.new code
6
+ parser = Parser::Main.new code
7
7
  ast = parser.parse
8
8
 
9
9
  interpreter = Interpreter.new ast
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ascode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Artem Varaksa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-16 00:00:00.000000000 Z
11
+ date: 2018-01-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Esoteric golfing language. In active development, so behavior may be
14
14
  changed without prior notice.
@@ -21,10 +21,12 @@ files:
21
21
  - README.md
22
22
  - lib/ascode.rb
23
23
  - lib/ascode/converter.rb
24
- - lib/ascode/functions.md
25
- - lib/ascode/functions.rb
26
24
  - lib/ascode/interpreter.rb
27
- - lib/ascode/parser.rb
25
+ - lib/ascode/parser/condition_block.rb
26
+ - lib/ascode/parser/function.rb
27
+ - lib/ascode/parser/functions.md
28
+ - lib/ascode/parser/literal.rb
29
+ - lib/ascode/parser/main.rb
28
30
  homepage: https://github.com/sudoio/ascode
29
31
  licenses:
30
32
  - MIT
@@ -1,33 +0,0 @@
1
- module Ascode
2
- class Functions
3
- attr_reader :csv_data
4
-
5
- def initialize
6
- @csv_data = []
7
-
8
- filename = File.join(File.dirname(__FILE__), "functions.md")
9
- File.open(filename, "r") do |file|
10
- read_csv file
11
- end
12
-
13
- @csv_data.delete_at 0
14
- @csv_data.delete_at 0
15
- end
16
-
17
- def read_csv(file)
18
- until (line = file.gets).nil?
19
- src = line.strip.split("|")
20
-
21
- @csv_data.push(
22
- short: clear_quotes(src[0]),
23
- long: clear_quotes(src[1])
24
- )
25
- end
26
- end
27
-
28
- def clear_quotes(str)
29
- return str unless str
30
- str.delete("`")
31
- end
32
- end
33
- end
data/lib/ascode/parser.rb DELETED
@@ -1,148 +0,0 @@
1
- require_relative "functions"
2
- require_relative "converter"
3
-
4
- module Ascode
5
- class Parser
6
- def initialize(code, impl_o = true)
7
- @fun = Functions.new
8
- @code = code
9
-
10
- @do_implicit_output = impl_o
11
- end
12
-
13
- def parse
14
- @ast = []
15
- @push_buffer = false
16
- @skip_chars = 0
17
- @is_quoted = false
18
- @escape = false
19
- @implicit_output = @do_implicit_output
20
-
21
- @code.split("").to_enum.each_with_index do |char, index|
22
- if @skip_chars > 0
23
- @skip_chars -= 1
24
- next
25
- else
26
- parse_character char, index
27
- end
28
- end
29
- ast_add_buffer
30
-
31
- ast_add_action "output" if @implicit_output
32
-
33
- @ast
34
- end
35
-
36
- def parse_condition_block(begin_index)
37
- block_code = @code[(begin_index + 1)..-1]
38
-
39
- end_index = (find_block_end block_code) + begin_index
40
- raise "Unmatched '[' at position #{begin_index}" if end_index == -1
41
-
42
- block_code = @code[(begin_index + 1)..(end_index + 1)]
43
-
44
- split_pos = find_block_split(block_code)
45
-
46
- if split_pos == -1
47
- true_block_ast = (Parser.new block_code).parse
48
- false_block_ast = []
49
- elsif split_pos.zero?
50
- true_block_ast = []
51
- false_block_ast = (Parser.new block_code[1..-1]).parse
52
- else
53
- true_block_ast = (Parser.new block_code[0..(split_pos - 1)], false).parse
54
- false_block_ast = (Parser.new block_code[(split_pos + 1)..-1], false).parse
55
- end
56
-
57
- @ast.push(action: "condition", true_block: true_block_ast, false_block: false_block_ast )
58
-
59
- end_index + 2
60
- end
61
-
62
- def find_block_end(block)
63
- end_index = -1
64
- block.split("").to_enum.with_index.reverse_each do |char, index|
65
- if char == "]"
66
- end_index = index
67
- break
68
- end
69
- end
70
-
71
- end_index - 1
72
- end
73
-
74
- def find_block_split(block)
75
- level = 0
76
- split_pos = -1
77
- block.split("").to_enum.each_with_index do |char, index|
78
- if char == "["
79
- level += 1
80
- elsif char == "]"
81
- level -= 1
82
- elsif char == "~" && level.zero?
83
- split_pos = index
84
- end
85
- end
86
-
87
- split_pos
88
- end
89
-
90
- def parse_character(char, index)
91
- if char == "\\"
92
- @escape = true
93
- return
94
- end
95
-
96
- if char == "\"" && !@escape
97
- ast_add_buffer if @is_quoted
98
- @is_quoted = !@is_quoted
99
- elsif @is_quoted || char =~ /[0-9.]/
100
- buffer_push char
101
- elsif char == "["
102
- end_index = parse_condition_block index
103
- @skip_chars = end_index - index
104
- elsif char == " "
105
- ast_add_buffer
106
- else
107
- ast_add_buffer
108
- parse_function char
109
- end
110
-
111
- @escape = false
112
- end
113
-
114
- def parse_function(char)
115
- function = @fun.csv_data.to_enum.find do |value|
116
- value[:short] == char
117
- end
118
-
119
- raise "Unexpected identifier: '#{char}'" unless function
120
- ast_add_action function[:long]
121
- end
122
-
123
- def buffer_push(char)
124
- if @push_buffer
125
- @push_buffer += char
126
- else
127
- @push_buffer = char
128
- end
129
- end
130
-
131
- def ast_add_buffer
132
- return unless @push_buffer
133
-
134
- @push_buffer = Converter.convert @push_buffer
135
-
136
- ast_add_action "push", @push_buffer
137
- @push_buffer = false
138
- end
139
-
140
- def ast_add_action(name, what = nil)
141
- @implicit_output = false if name == "output"
142
-
143
- data = { action: name }
144
- data[:what] = what if what
145
- @ast.push data
146
- end
147
- end
148
- end