carbon-compiler 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|