arpaka 0.1.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 +7 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +302 -0
- data/Rakefile +39 -0
- data/assets/arpaka-logo.svg +209 -0
- data/examples/calculator.y +13 -0
- data/examples/calculator_ast.y +13 -0
- data/exe/arpaka +6 -0
- data/lib/arpaka/BSDL +22 -0
- data/lib/arpaka/COPYING +58 -0
- data/lib/arpaka/actions.rb +656 -0
- data/lib/arpaka/cli.rb +60 -0
- data/lib/arpaka/generator.rb +43 -0
- data/lib/arpaka/ruby_grammar.rb +170 -0
- data/lib/arpaka/runtime/ast.rb.erb +35 -0
- data/lib/arpaka/runtime/builder.rb.erb +247 -0
- data/lib/arpaka/runtime/frontend.rb.erb +37 -0
- data/lib/arpaka/runtime/lexer.rb.erb +1371 -0
- data/lib/arpaka/source.json +11 -0
- data/lib/arpaka/upstream_rules.json +10202 -0
- data/lib/arpaka.rb +20 -0
- data/lib/lrama/ruby/action_code.rb +55 -0
- data/lib/lrama/ruby/action_scanner.rb +353 -0
- data/lib/lrama/ruby/backend.rb +103 -0
- data/lib/lrama/ruby/generator.rb +38 -0
- data/lib/lrama/ruby/parser.rb.erb +127 -0
- data/lib/lrama/ruby/version.rb +7 -0
- data/lib/lrama/ruby.rb +28 -0
- data/sig/arpaka.rbs +15 -0
- data/sig/lrama/ruby.rbs +17 -0
- metadata +86 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Generated by Arpaka/Lrama. Do not edit.
|
|
4
|
+
<% if recognizer -%>
|
|
5
|
+
# Recognition only: C actions and support code are omitted.
|
|
6
|
+
# Supply pre-tokenized input; acceptance returns true. No error recovery.
|
|
7
|
+
<% end -%>
|
|
8
|
+
class <%= class_name %>
|
|
9
|
+
class ParseError < StandardError
|
|
10
|
+
attr_reader :token, :state
|
|
11
|
+
|
|
12
|
+
def initialize(token, state)
|
|
13
|
+
@token = token
|
|
14
|
+
@state = state
|
|
15
|
+
super("Unexpected token #{token.inspect} in state #{state}")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
TOKENS = <%= tokens.inspect %>.freeze
|
|
20
|
+
<% %i[yytranslate yypact yydefact yypgoto yydefgoto yytable yycheck yyr1 yyr2].each do |name| -%>
|
|
21
|
+
<%= name.upcase %> = <%= context.public_send(name).inspect %>.freeze
|
|
22
|
+
<% end -%>
|
|
23
|
+
YYFINAL = <%= context.yyfinal %>
|
|
24
|
+
YYNTOKENS = <%= context.yyntokens %>
|
|
25
|
+
YYPACT_NINF = <%= context.yypact_ninf %>
|
|
26
|
+
YYTABLE_NINF = <%= context.yytable_ninf %>
|
|
27
|
+
|
|
28
|
+
attr_accessor :lexical_context
|
|
29
|
+
attr_reader :parse_trace, :lookahead_token, :lookahead_value, :lookahead_state
|
|
30
|
+
|
|
31
|
+
# tokens yields [token name or numeric ID, semantic value] pairs.
|
|
32
|
+
# Exhaustion is EOF; [0, nil] can also terminate the stream explicitly.
|
|
33
|
+
def parse(tokens)
|
|
34
|
+
@parse_trace = []
|
|
35
|
+
input = tokens.to_enum
|
|
36
|
+
states = [0]
|
|
37
|
+
values = []
|
|
38
|
+
lookahead = nil
|
|
39
|
+
token = nil
|
|
40
|
+
value = nil
|
|
41
|
+
@lookahead_token = nil
|
|
42
|
+
@lookahead_value = nil
|
|
43
|
+
@lookahead_state = nil
|
|
44
|
+
|
|
45
|
+
while true
|
|
46
|
+
state = states.last
|
|
47
|
+
return <%= recognizer ? "true" : "values[-2]" %> if state == YYFINAL
|
|
48
|
+
|
|
49
|
+
action = nil
|
|
50
|
+
base = YYPACT[state]
|
|
51
|
+
unless base == YYPACT_NINF
|
|
52
|
+
if lookahead.nil?
|
|
53
|
+
pair = begin
|
|
54
|
+
input.next
|
|
55
|
+
rescue StopIteration
|
|
56
|
+
[0, nil]
|
|
57
|
+
end
|
|
58
|
+
unless pair.is_a?(Array) && pair.length == 2
|
|
59
|
+
raise ArgumentError, "Each token must be a [name or ID, value] pair"
|
|
60
|
+
end
|
|
61
|
+
token, value = pair
|
|
62
|
+
@parse_trace << [:read, token, state].freeze
|
|
63
|
+
@lookahead_token = token
|
|
64
|
+
@lookahead_value = value
|
|
65
|
+
@lookahead_state = state
|
|
66
|
+
id = token.is_a?(Integer) ? token : TOKENS[token.to_s]
|
|
67
|
+
lookahead = id && id >= 0 ? (YYTRANSLATE[id] || 2) : 2
|
|
68
|
+
# The reserved error symbol is internal to recovery, never lexer input.
|
|
69
|
+
raise ParseError.new(token, state) if lookahead == 1
|
|
70
|
+
end
|
|
71
|
+
index = base + lookahead
|
|
72
|
+
if index >= 0 && index < YYCHECK.length && YYCHECK[index] == lookahead
|
|
73
|
+
action = YYTABLE[index]
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
if action.nil?
|
|
78
|
+
rule = YYDEFACT[state]
|
|
79
|
+
raise ParseError.new(token, state) if rule.zero?
|
|
80
|
+
elsif action.positive?
|
|
81
|
+
@parse_trace << [:shift, token, state, action].freeze
|
|
82
|
+
@lexical_context&.parser_shift(token, value, state, action)
|
|
83
|
+
states << action
|
|
84
|
+
values << value
|
|
85
|
+
lookahead = nil
|
|
86
|
+
@lookahead_token = nil
|
|
87
|
+
@lookahead_value = nil
|
|
88
|
+
@lookahead_state = nil
|
|
89
|
+
next
|
|
90
|
+
elsif action.zero? || action == YYTABLE_NINF
|
|
91
|
+
raise ParseError.new(token, state)
|
|
92
|
+
else
|
|
93
|
+
rule = -action
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
length = YYR2[rule]
|
|
97
|
+
@parse_trace << [:reduce, rule, state].freeze
|
|
98
|
+
@lexical_context&.parser_reduce(rule, state)
|
|
99
|
+
result = reduce(rule, values, length)
|
|
100
|
+
states.pop(length)
|
|
101
|
+
values.pop(length)
|
|
102
|
+
lhs = YYR1[rule] - YYNTOKENS
|
|
103
|
+
index = YYPGOTO[lhs] + states.last
|
|
104
|
+
next_state = if index >= 0 && index < YYCHECK.length && YYCHECK[index] == states.last
|
|
105
|
+
YYTABLE[index]
|
|
106
|
+
else
|
|
107
|
+
YYDEFGOTO[lhs]
|
|
108
|
+
end
|
|
109
|
+
states << next_state
|
|
110
|
+
values << result
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
def reduce(rule, values, length)
|
|
117
|
+
yyval = length.zero? ? nil : values[-length]
|
|
118
|
+
<% unless actions.empty? -%>
|
|
119
|
+
case rule
|
|
120
|
+
<%= actions %>
|
|
121
|
+
else
|
|
122
|
+
# The default action is $$ = $1 (nil for an empty production).
|
|
123
|
+
end
|
|
124
|
+
<% end -%>
|
|
125
|
+
yyval
|
|
126
|
+
end
|
|
127
|
+
end
|
data/lib/lrama/ruby.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "ruby/version"
|
|
4
|
+
|
|
5
|
+
module Lrama
|
|
6
|
+
module Ruby
|
|
7
|
+
class Error < StandardError; end
|
|
8
|
+
|
|
9
|
+
def self.generate(source, filename: "(grammar)", class_name: "Parser", mode: :parser, allow_error_rules: false)
|
|
10
|
+
Generator.new.generate(source, filename: filename, class_name: class_name,
|
|
11
|
+
mode: mode, allow_error_rules: allow_error_rules)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.compile(source, filename: "(grammar)", class_name: "Parser", mode: :parser, allow_error_rules: false)
|
|
15
|
+
code = generate(source, filename: filename, class_name: class_name,
|
|
16
|
+
mode: mode, allow_error_rules: allow_error_rules)
|
|
17
|
+
box = ::Ruby::Box.new
|
|
18
|
+
begin
|
|
19
|
+
box.eval(code)
|
|
20
|
+
rescue SyntaxError => error
|
|
21
|
+
raise Error, "Invalid generated Ruby for #{filename}: #{error.message}"
|
|
22
|
+
end
|
|
23
|
+
box.const_get(class_name, false)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
require_relative "ruby/generator"
|
data/sig/arpaka.rbs
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Arpaka
|
|
2
|
+
interface _Program
|
|
3
|
+
def statements: () -> Array[untyped]
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
interface _Frontend
|
|
7
|
+
def parse: (String source, ?filename: String) -> _Program
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.generate: (ruby_source: String, ?class_name: String) -> String
|
|
11
|
+
def self.compile: (ruby_source: String, ?class_name: String) -> _Frontend
|
|
12
|
+
|
|
13
|
+
class Error < ::Lrama::Ruby::Error
|
|
14
|
+
end
|
|
15
|
+
end
|
data/sig/lrama/ruby.rbs
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Lrama
|
|
2
|
+
module Ruby
|
|
3
|
+
VERSION: String
|
|
4
|
+
|
|
5
|
+
class Error < StandardError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.generate: (String source, ?filename: String, ?class_name: String, ?mode: (:parser | :recognizer), ?allow_error_rules: bool) -> String
|
|
9
|
+
def self.compile: (String source, ?filename: String, ?class_name: String, ?mode: (:parser | :recognizer), ?allow_error_rules: bool) -> Class
|
|
10
|
+
|
|
11
|
+
class Generator
|
|
12
|
+
def initialize: () -> void
|
|
13
|
+
def generate: (String source, ?filename: String, ?class_name: String, ?mode: (:parser | :recognizer), ?allow_error_rules: bool) -> String
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: arpaka
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- MATSUMOTO, Katsuyoshi
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: lrama
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 0.8.0
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 0.8.0
|
|
26
|
+
description: A Ruby parser frontend and Ruby output backend for Lrama.
|
|
27
|
+
email:
|
|
28
|
+
- github@katsyoshi.org
|
|
29
|
+
executables:
|
|
30
|
+
- arpaka
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- CHANGELOG.md
|
|
35
|
+
- LICENSE.txt
|
|
36
|
+
- README.md
|
|
37
|
+
- Rakefile
|
|
38
|
+
- assets/arpaka-logo.svg
|
|
39
|
+
- examples/calculator.y
|
|
40
|
+
- examples/calculator_ast.y
|
|
41
|
+
- exe/arpaka
|
|
42
|
+
- lib/arpaka.rb
|
|
43
|
+
- lib/arpaka/BSDL
|
|
44
|
+
- lib/arpaka/COPYING
|
|
45
|
+
- lib/arpaka/actions.rb
|
|
46
|
+
- lib/arpaka/cli.rb
|
|
47
|
+
- lib/arpaka/generator.rb
|
|
48
|
+
- lib/arpaka/ruby_grammar.rb
|
|
49
|
+
- lib/arpaka/runtime/ast.rb.erb
|
|
50
|
+
- lib/arpaka/runtime/builder.rb.erb
|
|
51
|
+
- lib/arpaka/runtime/frontend.rb.erb
|
|
52
|
+
- lib/arpaka/runtime/lexer.rb.erb
|
|
53
|
+
- lib/arpaka/source.json
|
|
54
|
+
- lib/arpaka/upstream_rules.json
|
|
55
|
+
- lib/lrama/ruby.rb
|
|
56
|
+
- lib/lrama/ruby/action_code.rb
|
|
57
|
+
- lib/lrama/ruby/action_scanner.rb
|
|
58
|
+
- lib/lrama/ruby/backend.rb
|
|
59
|
+
- lib/lrama/ruby/generator.rb
|
|
60
|
+
- lib/lrama/ruby/parser.rb.erb
|
|
61
|
+
- lib/lrama/ruby/version.rb
|
|
62
|
+
- sig/arpaka.rbs
|
|
63
|
+
- sig/lrama/ruby.rbs
|
|
64
|
+
homepage: https://github.com/katsyoshi/arpaka
|
|
65
|
+
licenses:
|
|
66
|
+
- MIT
|
|
67
|
+
metadata:
|
|
68
|
+
homepage_uri: https://github.com/katsyoshi/arpaka
|
|
69
|
+
rdoc_options: []
|
|
70
|
+
require_paths:
|
|
71
|
+
- lib
|
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: 4.0.0
|
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
requirements: []
|
|
83
|
+
rubygems_version: 4.0.20
|
|
84
|
+
specification_version: 4
|
|
85
|
+
summary: Ruby language parser frontend and Lrama output backend
|
|
86
|
+
test_files: []
|