carbon-compiler 0.2.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/.gitattributes +17 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.rubocop.yml +39 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +9 -0
- data/Vagrantfile +84 -0
- data/carbon-compiler.gemspec +28 -0
- data/lib/carbon/compiler.rb +20 -0
- data/lib/carbon/compiler/directive.rb +48 -0
- data/lib/carbon/compiler/directive/import.rb +17 -0
- data/lib/carbon/compiler/errors.rb +7 -0
- data/lib/carbon/compiler/location.rb +136 -0
- data/lib/carbon/compiler/metanostic.rb +123 -0
- data/lib/carbon/compiler/metanostic/defaults.rb +41 -0
- data/lib/carbon/compiler/metanostic/defaults.yml +138 -0
- data/lib/carbon/compiler/metanostic/diagnostic.rb +112 -0
- data/lib/carbon/compiler/metanostic/list.rb +109 -0
- data/lib/carbon/compiler/metanostic/mode.rb +162 -0
- data/lib/carbon/compiler/metanostic/state.rb +174 -0
- data/lib/carbon/compiler/metanostic/template.erb +11 -0
- data/lib/carbon/compiler/node.rb +18 -0
- data/lib/carbon/compiler/node/base.rb +213 -0
- data/lib/carbon/compiler/node/definition.rb +19 -0
- data/lib/carbon/compiler/node/definition/class.rb +24 -0
- data/lib/carbon/compiler/node/definition/class/element.rb +18 -0
- data/lib/carbon/compiler/node/definition/directive.rb +22 -0
- data/lib/carbon/compiler/node/definition/directive/function.rb +18 -0
- data/lib/carbon/compiler/node/definition/enum.rb +20 -0
- data/lib/carbon/compiler/node/definition/enum/element.rb +17 -0
- data/lib/carbon/compiler/node/definition/function.rb +44 -0
- data/lib/carbon/compiler/node/definition/function/body.rb +17 -0
- data/lib/carbon/compiler/node/definition/function/name.rb +18 -0
- data/lib/carbon/compiler/node/definition/function/parameter.rb +18 -0
- data/lib/carbon/compiler/node/definition/function/parameters.rb +17 -0
- data/lib/carbon/compiler/node/definition/module.rb +23 -0
- data/lib/carbon/compiler/node/definition/struct.rb +24 -0
- data/lib/carbon/compiler/node/definition/struct/element.rb +18 -0
- data/lib/carbon/compiler/node/etype.rb +66 -0
- data/lib/carbon/compiler/node/etype/option.rb +25 -0
- data/lib/carbon/compiler/node/etype/star.rb +13 -0
- data/lib/carbon/compiler/node/expression.rb +18 -0
- data/lib/carbon/compiler/node/expression/assignment.rb +22 -0
- data/lib/carbon/compiler/node/expression/call.rb +22 -0
- data/lib/carbon/compiler/node/expression/call/access.rb +24 -0
- data/lib/carbon/compiler/node/expression/call/attribute.rb +23 -0
- data/lib/carbon/compiler/node/expression/call/enum.rb +25 -0
- data/lib/carbon/compiler/node/expression/call/module.rb +24 -0
- data/lib/carbon/compiler/node/expression/call/parameters.rb +17 -0
- data/lib/carbon/compiler/node/expression/call/self.rb +17 -0
- data/lib/carbon/compiler/node/expression/call/unified.rb +27 -0
- data/lib/carbon/compiler/node/expression/literal.rb +83 -0
- data/lib/carbon/compiler/node/expression/operation.rb +20 -0
- data/lib/carbon/compiler/node/expression/operation/and.rb +20 -0
- data/lib/carbon/compiler/node/expression/operation/neq.rb +21 -0
- data/lib/carbon/compiler/node/expression/operation/normal.rb +20 -0
- data/lib/carbon/compiler/node/expression/operation/or.rb +20 -0
- data/lib/carbon/compiler/node/expression/unit.rb +16 -0
- data/lib/carbon/compiler/node/name.rb +27 -0
- data/lib/carbon/compiler/node/root.rb +23 -0
- data/lib/carbon/compiler/node/statement.rb +24 -0
- data/lib/carbon/compiler/node/statement/catch.rb +20 -0
- data/lib/carbon/compiler/node/statement/condition.rb +14 -0
- data/lib/carbon/compiler/node/statement/else.rb +17 -0
- data/lib/carbon/compiler/node/statement/elsif.rb +18 -0
- data/lib/carbon/compiler/node/statement/finally.rb +17 -0
- data/lib/carbon/compiler/node/statement/for.rb +18 -0
- data/lib/carbon/compiler/node/statement/if.rb +18 -0
- data/lib/carbon/compiler/node/statement/let.rb +18 -0
- data/lib/carbon/compiler/node/statement/match.rb +14 -0
- data/lib/carbon/compiler/node/statement/return.rb +17 -0
- data/lib/carbon/compiler/node/statement/try.rb +19 -0
- data/lib/carbon/compiler/node/statement/while.rb +19 -0
- data/lib/carbon/compiler/parser.rb +63 -0
- data/lib/carbon/compiler/parser/common.rb +79 -0
- data/lib/carbon/compiler/parser/expressions.rb +39 -0
- data/lib/carbon/compiler/parser/expressions/precedence.rb +134 -0
- data/lib/carbon/compiler/parser/expressions/primary.rb +120 -0
- data/lib/carbon/compiler/parser/firsts.rb +74 -0
- data/lib/carbon/compiler/parser/helpers.rb +61 -0
- data/lib/carbon/compiler/parser/root.rb +57 -0
- data/lib/carbon/compiler/parser/root/class.rb +34 -0
- data/lib/carbon/compiler/parser/root/directive.rb +87 -0
- data/lib/carbon/compiler/parser/root/enum.rb +45 -0
- data/lib/carbon/compiler/parser/root/function.rb +90 -0
- data/lib/carbon/compiler/parser/root/struct.rb +34 -0
- data/lib/carbon/compiler/parser/root/trait.rb +44 -0
- data/lib/carbon/compiler/parser/statements.rb +86 -0
- data/lib/carbon/compiler/parser/statements/if.rb +50 -0
- data/lib/carbon/compiler/parser/statements/match.rb +39 -0
- data/lib/carbon/compiler/parser/statements/try.rb +49 -0
- data/lib/carbon/compiler/project.rb +37 -0
- data/lib/carbon/compiler/project/file.rb +64 -0
- data/lib/carbon/compiler/scanner.rb +82 -0
- data/lib/carbon/compiler/scanner/main.rb +76 -0
- data/lib/carbon/compiler/scanner/token.rb +58 -0
- data/lib/carbon/compiler/version.rb +8 -0
- data/lib/carbon/compiler/visitor.rb +13 -0
- data/lib/carbon/compiler/visitor/base.rb +52 -0
- data/lib/carbon/compiler/visitor/generation.rb +45 -0
- data/lib/carbon/compiler/visitor/generation/asserts.rb +30 -0
- data/lib/carbon/compiler/visitor/generation/class.rb +93 -0
- data/lib/carbon/compiler/visitor/generation/context.rb +75 -0
- data/lib/carbon/compiler/visitor/generation/expressions.rb +82 -0
- data/lib/carbon/compiler/visitor/generation/expressions/assignment.rb +105 -0
- data/lib/carbon/compiler/visitor/generation/expressions/calls.rb +89 -0
- data/lib/carbon/compiler/visitor/generation/function.rb +68 -0
- data/lib/carbon/compiler/visitor/generation/statements.rb +131 -0
- data/lib/carbon/compiler/visitor/generation/struct.rb +115 -0
- data/lib/carbon/compiler/visitor/preparation.rb +86 -0
- data/lib/carbon/compiler/visitor/preparation/expressions.rb +26 -0
- data/lib/carbon/compiler/visitor/preparation/function.rb +55 -0
- data/lib/carbon/compiler/visitor/preparation/statements.rb +73 -0
- data/lib/carbon/compiler/visitor/preparation/struct.rb +37 -0
- data/program.ca +16 -0
- data/test.rb +21 -0
- metadata +234 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "carbon/compiler/parser/expressions/precedence"
|
5
|
+
require "carbon/compiler/parser/expressions/primary"
|
6
|
+
|
7
|
+
module Carbon
|
8
|
+
module Compiler
|
9
|
+
class Parser
|
10
|
+
# Parses expressions.
|
11
|
+
module Expressions
|
12
|
+
include Precedence
|
13
|
+
include Primary
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
PRECEDENCE = {
|
18
|
+
"=": 1,
|
19
|
+
"||": 2,
|
20
|
+
"&&": 3,
|
21
|
+
"|": 4,
|
22
|
+
"^": 5,
|
23
|
+
"&": 6,
|
24
|
+
"===": 7, "==": 7, "!=": 7,
|
25
|
+
"<": 8, ">": 8, "<=": 8, ">=": 8,
|
26
|
+
"<<": 9, ">>": 9,
|
27
|
+
"+": 10, "-": 10,
|
28
|
+
"*": 11, "/": 11, "%": 11,
|
29
|
+
".": 12, "[": 12
|
30
|
+
}.freeze
|
31
|
+
RIGHT = [:"=", :"."].freeze
|
32
|
+
|
33
|
+
def parse_expression
|
34
|
+
parse_precedence(parse_expression_primary, 0)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
class Parser
|
7
|
+
module Expressions
|
8
|
+
# Parses precedence rules for expressions.
|
9
|
+
module Precedence
|
10
|
+
protected
|
11
|
+
|
12
|
+
def parse_precedence(expr, prec)
|
13
|
+
left = expr
|
14
|
+
while PRECEDENCE[peek.type] && PRECEDENCE[peek.type] >= prec
|
15
|
+
op = expect peek.type
|
16
|
+
left =
|
17
|
+
case op.type
|
18
|
+
when :< then parse_precedence_less(left)
|
19
|
+
when :"." then parse_precedence_period(left)
|
20
|
+
when :"[" then parse_precedence_access(left)
|
21
|
+
else
|
22
|
+
parse_precedence_op([left, op, parse_expression_primary])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
left
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse_precedence_less(left)
|
30
|
+
default = proc {
|
31
|
+
parse_precedence_op([left, :<, parse_expression_primary]) }
|
32
|
+
return default.call unless first(:type).include?(peek.type) &&
|
33
|
+
left.respond_to?(:generics)
|
34
|
+
position = @enum.dup
|
35
|
+
name = parse_type
|
36
|
+
case peek.type
|
37
|
+
when :>, :",", :":" then parse_precendence_generic(left, name)
|
38
|
+
else
|
39
|
+
@enum = position
|
40
|
+
parse_precedence_op([left, :<, parse_expression_primary])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse_precedence_generic(left, name)
|
45
|
+
children = [name]
|
46
|
+
until peek? :>
|
47
|
+
children << Concrete::Type::Generic.new(parse_module_name, [])
|
48
|
+
break unless peek? :","
|
49
|
+
expect :","
|
50
|
+
end
|
51
|
+
expect :>
|
52
|
+
|
53
|
+
if peek?(:"(") # if this is a call, our left should be an attribute
|
54
|
+
children = []
|
55
|
+
until peek? :")"
|
56
|
+
children << parse_expression
|
57
|
+
break unless peek? :","
|
58
|
+
expect :","
|
59
|
+
end
|
60
|
+
expect :")"
|
61
|
+
|
62
|
+
arguments = Node::Expression::Call::Parameters.new(children)
|
63
|
+
Node::Expression::Call::Unified.new([left.expression, left.name,
|
64
|
+
arguments, generics])
|
65
|
+
else
|
66
|
+
left.merge(generics: children)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def parse_precedence_period(left)
|
71
|
+
name = parse_name
|
72
|
+
generics = peek?(:<) ? parse_module_generics : []
|
73
|
+
|
74
|
+
if peek?(:"(")
|
75
|
+
parse_precedence_period_call(left, name, generics)
|
76
|
+
else
|
77
|
+
Node::Expression::Call::Attribute.new([left, name, generics])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def parse_precedence_access(left, generics = [])
|
82
|
+
children = []
|
83
|
+
until peek? :"]"
|
84
|
+
children << parse_expression
|
85
|
+
break unless peek? :","
|
86
|
+
expect :","
|
87
|
+
end
|
88
|
+
expect :"]"
|
89
|
+
|
90
|
+
arguments = Node::Expression::Call::Parameters.new(children)
|
91
|
+
Node::Expression::Call::Access.new([left, arguments, generics])
|
92
|
+
end
|
93
|
+
|
94
|
+
def parse_precedence_period_call(left, name, generics)
|
95
|
+
l = expect :"("
|
96
|
+
children = []
|
97
|
+
until peek? :")"
|
98
|
+
children << parse_expression
|
99
|
+
break unless peek? :","
|
100
|
+
expect :","
|
101
|
+
end
|
102
|
+
r = expect :")"
|
103
|
+
|
104
|
+
arguments = Node::Expression::Call::Parameters.new(children)
|
105
|
+
Node::Expression::Call::Unified.new([left, name, arguments,
|
106
|
+
generics], components: [left, name, l, r])
|
107
|
+
end
|
108
|
+
|
109
|
+
def parse_precedence_op(data)
|
110
|
+
left, op, right = *data
|
111
|
+
oprec = PRECEDENCE.fetch(op.type)
|
112
|
+
while PRECEDENCE[peek.type] && (PRECEDENCE[peek.type] > oprec ||
|
113
|
+
(RIGHT.include?(peek.type) && PRECEDENCE[peek.type] == oprec))
|
114
|
+
right = parse_precedence(right, PRECEDENCE[peek.type])
|
115
|
+
end
|
116
|
+
|
117
|
+
case op.type
|
118
|
+
when :"="
|
119
|
+
Node::Expression::Assignment.new([left, op, right])
|
120
|
+
when :"&&"
|
121
|
+
Node::Expression::Operation::And.new([left, op, right])
|
122
|
+
when :"||"
|
123
|
+
Node::Expression::Operation::Or.new([left, op, right])
|
124
|
+
when :"!="
|
125
|
+
Node::Expression::Operation::Neq.new([left, op, right])
|
126
|
+
else
|
127
|
+
Node::Expression::Operation::Normal.new([left, op, right])
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
class Parser
|
7
|
+
module Expressions
|
8
|
+
# Parses primary expressions, e.g. literals, module calls, etc.
|
9
|
+
module Primary
|
10
|
+
protected
|
11
|
+
|
12
|
+
FUNCTION_NAMES = Set[:|, :&, :"^", :===, :==, :<, :>, :<=, :>=,
|
13
|
+
:<=>, :<<, :>>, :+, :-, :*, :/, :%, :[], :[]=]
|
14
|
+
Parser.first(:module, [:MNAME])
|
15
|
+
Parser.first(:literal, [:NUMBER, :FLOAT, :STRING])
|
16
|
+
Parser.first(:unit, [:"("])
|
17
|
+
Parser.first(:expression, Parser.first(:module) |
|
18
|
+
Parser.first(:literal) | Parser.first(:unit) |
|
19
|
+
Parser.first(:name))
|
20
|
+
Parser.first(:call, Parser.first(:name))
|
21
|
+
def parse_expression_primary
|
22
|
+
if first(:module).include?(peek.type)
|
23
|
+
parse_expression_module
|
24
|
+
elsif first(:literal).include?(peek.type)
|
25
|
+
parse_expression_literal
|
26
|
+
elsif first(:unit).include?(peek.type)
|
27
|
+
parse_expression_unit
|
28
|
+
elsif first(:name).include?(peek.type)
|
29
|
+
parse_expression_name
|
30
|
+
else
|
31
|
+
error(first(:expression))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_expression_module
|
36
|
+
mname = parse_module_name
|
37
|
+
case peek.type
|
38
|
+
when :"."
|
39
|
+
parse_expression_call(mname)
|
40
|
+
else
|
41
|
+
error([:"."])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def parse_expression_name
|
46
|
+
name = parse_name
|
47
|
+
return name unless peek? :"("
|
48
|
+
l = expect :"("
|
49
|
+
children = []
|
50
|
+
until peek? :")"
|
51
|
+
children << parse_expression
|
52
|
+
break unless peek? :","
|
53
|
+
expect :","
|
54
|
+
end
|
55
|
+
r = expect :")"
|
56
|
+
|
57
|
+
arguments = Node::Expression::Call::Parameters.new(children,
|
58
|
+
components: [l, r])
|
59
|
+
Node::Expression::Call::Self.new([name, arguments])
|
60
|
+
end
|
61
|
+
|
62
|
+
def parse_expression_call_name
|
63
|
+
if first(:name).include?(peek.type)
|
64
|
+
parse_name
|
65
|
+
elsif peek?(:MNAME)
|
66
|
+
expect :MNAME
|
67
|
+
else
|
68
|
+
error(first(:name) | [:MNAME])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def parse_expression_call(mname)
|
73
|
+
expect :"."
|
74
|
+
name = parse_expression_call_name
|
75
|
+
generics = peek?(:<) ? parse_module_generics : []
|
76
|
+
|
77
|
+
l = expect :"("
|
78
|
+
children = []
|
79
|
+
until peek? :")"
|
80
|
+
children << parse_expression
|
81
|
+
break unless peek? :","
|
82
|
+
expect :","
|
83
|
+
end
|
84
|
+
r = expect :")"
|
85
|
+
|
86
|
+
arguments = Node::Expression::Call::Parameters.new(children,
|
87
|
+
components: [l, r])
|
88
|
+
Node::Expression::Call::Module.new([mname, name, arguments,
|
89
|
+
generics])
|
90
|
+
end
|
91
|
+
|
92
|
+
def parse_expression_unit
|
93
|
+
expect :"("
|
94
|
+
children = []
|
95
|
+
until peek? :")"
|
96
|
+
children << parse_expression
|
97
|
+
break unless peek? :","
|
98
|
+
expect :","
|
99
|
+
end
|
100
|
+
expect :")"
|
101
|
+
Node::Expression::Unit.new(children)
|
102
|
+
end
|
103
|
+
|
104
|
+
def parse_expression_literal
|
105
|
+
case peek.type
|
106
|
+
when :NUMBER
|
107
|
+
Node::Expression::Literal.new([expect(:NUMBER)])
|
108
|
+
when :FLOAT
|
109
|
+
Node::Expression::Literal.new([expect(:FLOAT)])
|
110
|
+
when :STRING
|
111
|
+
Node::Expression::Literal.new([expect(:STRING)])
|
112
|
+
else
|
113
|
+
error first(:literal)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require "set"
|
4
|
+
|
5
|
+
module Carbon
|
6
|
+
module Compiler
|
7
|
+
class Parser
|
8
|
+
# Manages first sets for the parser. This is only for internal
|
9
|
+
# reference to make parsing easier.
|
10
|
+
module Firsts
|
11
|
+
# The class methods that should be placed on the parser.
|
12
|
+
module ClassMethods
|
13
|
+
# The first sets. The key is the name of a node, and the value
|
14
|
+
# is a set of all tokens that can be at the start of that node.
|
15
|
+
#
|
16
|
+
# @return [{Symbol => Set<Symbol>}]
|
17
|
+
def firsts
|
18
|
+
@firsts ||= Hash.new { |h, k| h[k] = Set.new }
|
19
|
+
end
|
20
|
+
|
21
|
+
# @overload first(name)
|
22
|
+
# Retrieves the first set for the given node name. If none exists,
|
23
|
+
# a `KeyError` is raised.
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
# @param name [::Symbol] The name of the node to look up the first
|
27
|
+
# set for.
|
28
|
+
# @return [Set<::Symbol>] The first set
|
29
|
+
# @raise [KeyError] If the node has no defined first set.
|
30
|
+
# @overload first(name, tokens)
|
31
|
+
# Merges the given tokens into the first set of the name of the
|
32
|
+
# node given.
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
# @param name [::Symbol] The name of the node that the first set is
|
36
|
+
# for.
|
37
|
+
# @param tokens [<::Symbol>] The tokens that act as the first set
|
38
|
+
# for the node.
|
39
|
+
# @return [void]
|
40
|
+
def first(name, tokens = nil)
|
41
|
+
if tokens
|
42
|
+
firsts[name].merge(tokens)
|
43
|
+
else
|
44
|
+
firsts.fetch(name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# The instance methods that should be placed in the parser.
|
50
|
+
module InstanceMethods
|
51
|
+
# Retrieves the first set for the given node name.
|
52
|
+
#
|
53
|
+
# @param name [Symbol]
|
54
|
+
# @return [Set<Symbol>]
|
55
|
+
def first(name)
|
56
|
+
self.class.firsts.fetch(name)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Includes the {ClassMethods} and {InstanceMethods} into the
|
61
|
+
# parser or whatever base includes it.
|
62
|
+
#
|
63
|
+
# @param base [Parser]
|
64
|
+
# @api private
|
65
|
+
def self.included(base)
|
66
|
+
base.extend ClassMethods
|
67
|
+
base.send :include, InstanceMethods
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
include Firsts
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
class Parser
|
7
|
+
# helpers that manage the state of the parser. This can be things like
|
8
|
+
# peeking, shifting, and erroring.
|
9
|
+
module Helpers
|
10
|
+
# Peeks to the next token. If peeking would cause a `StopIteration`
|
11
|
+
# error, it instead returns the last value that was peeked.
|
12
|
+
#
|
13
|
+
# @return [Scanner::Token]
|
14
|
+
def peek
|
15
|
+
value = @enum.peek
|
16
|
+
@_last = value
|
17
|
+
rescue StopIteration
|
18
|
+
@_last
|
19
|
+
end
|
20
|
+
|
21
|
+
# Checks to see if any of the given types includes the next token.
|
22
|
+
#
|
23
|
+
# @param types [Symbol] The possible types.
|
24
|
+
# @return [Boolean]
|
25
|
+
def peek?(*types)
|
26
|
+
types.include?(peek.type)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Shifts to the next token, and returns the old token.
|
30
|
+
#
|
31
|
+
# @return [Scanner::Token]
|
32
|
+
def shift
|
33
|
+
@enum.next
|
34
|
+
end
|
35
|
+
|
36
|
+
# Sets up an expectation for a given token. If the next token is
|
37
|
+
# an expected token, it shifts, returning the token; otherwise,
|
38
|
+
# it {#error}s with the token information.
|
39
|
+
#
|
40
|
+
# @param tokens [Symbol] The expected tokens.
|
41
|
+
# @return [Scanner::Token]
|
42
|
+
def expect(*tokens)
|
43
|
+
return shift if peek?(*tokens)
|
44
|
+
error(tokens)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Errors, noting the expected tokens, the given token, the location
|
48
|
+
# of given tokens. It does this by emitting a diagnostic. The
|
49
|
+
# diagnostic is only allowed to be a {Metanostic::Mode::PANIC}
|
50
|
+
# diagnostic, so this is garenteed to error.
|
51
|
+
#
|
52
|
+
# @param tokens [<Symbol>] The expected tokens.
|
53
|
+
# @return [void]
|
54
|
+
def error(tokens)
|
55
|
+
@file.emit("Syntax/Token/Unexpected", peek.location,
|
56
|
+
[peek.type.inspect, tokens.map(&:inspect).join(", ")])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
4
|
+
|
5
|
+
require "carbon/compiler/parser/root/class"
|
6
|
+
require "carbon/compiler/parser/root/directive"
|
7
|
+
require "carbon/compiler/parser/root/enum"
|
8
|
+
require "carbon/compiler/parser/root/function"
|
9
|
+
require "carbon/compiler/parser/root/struct"
|
10
|
+
require "carbon/compiler/parser/root/trait"
|
11
|
+
|
12
|
+
module Carbon
|
13
|
+
module Compiler
|
14
|
+
class Parser
|
15
|
+
# Parses root definitions, like functions and enums.
|
16
|
+
module Root
|
17
|
+
include Class
|
18
|
+
include Directive
|
19
|
+
include Enum
|
20
|
+
include Function
|
21
|
+
include Struct
|
22
|
+
include Trait
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
Parser.first(:root, [:":", :module, :struct, :class, :trait, :enum,
|
27
|
+
:def])
|
28
|
+
def parse_root
|
29
|
+
children = []
|
30
|
+
until peek? :EOF
|
31
|
+
children <<
|
32
|
+
case peek.type
|
33
|
+
when :":" then parse_directive
|
34
|
+
when :module then parse_module
|
35
|
+
when :struct then parse_struct
|
36
|
+
when :class then parse_class
|
37
|
+
when :trait then parse_trait
|
38
|
+
when :enum then parse_enum
|
39
|
+
when :def then parse_function
|
40
|
+
else error first(:root)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Node::Root.new(children)
|
45
|
+
end
|
46
|
+
|
47
|
+
def parse_module
|
48
|
+
expect :module
|
49
|
+
name = parse_module_name
|
50
|
+
expect :"."
|
51
|
+
|
52
|
+
Node::Definition::Module.new([name])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|