ascode 0.4.2 → 0.5.0

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: 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