578 lines
21 KiB
Swift
578 lines
21 KiB
Swift
// p4rse, Copyright 2026, Will Hawkins
|
|
//
|
|
// This file is part of p4rse.
|
|
//
|
|
// This file is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
import Common
|
|
import SwiftTreeSitter
|
|
import TreeSitterP4
|
|
|
|
extension CST.Identifier: ParsableExpression {
|
|
public static func ParseExpression(
|
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
|
) -> Result<CST.AnExpression> {
|
|
|
|
#RequireNodeType<Node, CST.AnExpression>(
|
|
node: node, type: "identifier", nice_type_name: "Identifier")
|
|
|
|
/// TODO: If there is a value here, then we can make this a compile-time constant!
|
|
return .Ok(CST.Identifier(Common.Identifier(name: node.text!)))
|
|
}
|
|
}
|
|
|
|
extension P4BooleanValue: ParsableExpression {
|
|
public static func ParseExpression(
|
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
|
) -> Result<CST.AnExpression> {
|
|
let node = node.child(at: 0)!
|
|
#RequireNodeType<Node, CST.AnExpression>(
|
|
node: node, type: "booleanLiteralExpression", nice_type_name: "Boolean Literal Expression")
|
|
|
|
if node.text == "false" {
|
|
return .Ok(CST.Literal(P4Value(P4BooleanValue(withValue: false))))
|
|
} else if node.text == "true" {
|
|
return .Ok(CST.Literal(P4Value(P4BooleanValue(withValue: true))))
|
|
}
|
|
|
|
return .Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(),
|
|
withError: "Failed to parse boolean literal: \(node.text!)"))
|
|
}
|
|
}
|
|
|
|
extension P4IntValue: ParsableExpression {
|
|
public static func ParseExpression(
|
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
|
) -> Result<CST.AnExpression> {
|
|
let node = node.child(at: 0)!
|
|
|
|
#RequireNodesType<Node, CST.AnExpression>(
|
|
nodes: node, type: ["integer", "integer_elaborated"],
|
|
nice_type_names: ["Integer", "Elaborated Integer"])
|
|
|
|
var bit_width: BitWidth = BitWidth.Infinite
|
|
let value_source: String
|
|
if node.nodeType == "integer_elaborated" {
|
|
let re = /([0-9]+)([ws])([\-0-9]+)/
|
|
let integer_components = node.text!.matches(of: re)
|
|
|
|
if integer_components.isEmpty || integer_components.count > 1 {
|
|
return .Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(),
|
|
withError: "Failed to parse elaborated integer: \(node.text!)"))
|
|
}
|
|
|
|
let width_source = "\(integer_components[0].1)"
|
|
guard let width = Int(width_source) else {
|
|
return .Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(),
|
|
withError: "Failed to parse width from elaborated integer: \(width_source)"))
|
|
}
|
|
|
|
/// TODO: Handle signed vs. unsigned.
|
|
|
|
bit_width = BitWidth.Width(width)
|
|
value_source = "\(integer_components[0].3)"
|
|
} else {
|
|
value_source = node.text!
|
|
}
|
|
|
|
if let parsed_int = Int(value_source) {
|
|
return .Ok(CST.Literal(P4Value(P4IntValue(withValue: parsed_int, andWidth: bit_width))))
|
|
} else {
|
|
return .Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(),
|
|
withError: "Failed to parse integer: \(node.text!)"))
|
|
}
|
|
}
|
|
}
|
|
|
|
extension P4StringValue: ParsableExpression {
|
|
public static func ParseExpression(
|
|
node: SwiftTreeSitter.Node, withContext scopes: CSTCompilerContext
|
|
) -> Result<CST.AnExpression> {
|
|
let node = node.child(at: 0)!
|
|
#RequireNodeType<Node, CST.AnExpression>(
|
|
node: node, type: "string_literal", nice_type_name: "String Literal")
|
|
return .Ok(CST.Literal(P4Value(P4StringValue(withValue: node.text!))))
|
|
}
|
|
}
|
|
|
|
extension CST.Expression: Parsable {
|
|
public static func Parse(
|
|
node: Node, withContext context: CSTCompilerContext
|
|
) -> Result<CST.AnExpression> {
|
|
#RequireNodeType<Node, CST.AnExpression>(
|
|
node: node, type: "expression", nice_type_name: "expression")
|
|
|
|
let expression_node = node.child(at: 0)!
|
|
#RequireNodesType<Node, CST.AnExpression>(
|
|
nodes: expression_node, type: ["grouped_expression", "simple_expression"],
|
|
nice_type_names: ["grouped expression", "simple expression"])
|
|
|
|
// If this is a grouped expression, recurse!
|
|
if expression_node.nodeType == "grouped_expression" {
|
|
return CST.Expression.Parse(node: expression_node.child(at: 1)!, withContext: context)
|
|
}
|
|
|
|
let expression_parsers: [ParsableExpression.Type] = [
|
|
P4BooleanValue.self, P4StringValue.self, P4IntValue.self, CST.Identifier.self,
|
|
CST.BinaryOperatorExpression.self, CST.ArrayAccessExpression.self,
|
|
CST.FieldAccessExpression.self,
|
|
CST.FunctionCall.self,
|
|
]
|
|
|
|
for candidate_expression_parser in expression_parsers {
|
|
switch candidate_expression_parser.ParseExpression(
|
|
node: expression_node, withContext: context)
|
|
{
|
|
case .Ok(let parsed): return .Ok(parsed)
|
|
case .Error(let e): return .Error(e)
|
|
}
|
|
}
|
|
|
|
return Result.Error(Error(withMessage: "\(node.range): Could not parse into expression"))
|
|
}
|
|
}
|
|
|
|
extension CST.KeysetExpression: ParsableExpression {
|
|
public static func ParseExpression(
|
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
|
) -> Result<CST.AnExpression> {
|
|
let keyset_expression_node = node.child(at: 0)!
|
|
|
|
#RequireNodesType<Node, CST.AnExpression>(
|
|
nodes: keyset_expression_node, type: ["expression", "default_keyset"],
|
|
nice_type_names: ["expression", "default keyset"])
|
|
|
|
// If there is a default keyset, that's easy!
|
|
if keyset_expression_node.nodeType == "default_keyset" {
|
|
return .Ok(CST.KeysetExpression.Default)
|
|
}
|
|
|
|
// Compile the expression:
|
|
let maybe_compiled_set_expression = CST.Expression.Parse(
|
|
node: keyset_expression_node, withContext: context)
|
|
guard case .Ok(let compiled_expression) = maybe_compiled_set_expression else {
|
|
return .Error(maybe_compiled_set_expression.error()!)
|
|
}
|
|
|
|
return .Ok(CST.KeysetExpression.Value(compiled_expression))
|
|
}
|
|
}
|
|
|
|
extension CST.SelectExpression: ParsableExpression {
|
|
public static func ParseExpression(
|
|
node: Node, withContext context: CSTCompilerContext
|
|
) -> Result<CST.AnExpression> {
|
|
#RequireNodeType<Node, (CST.SelectExpression, CSTCompilerContext)>(
|
|
node: node, type: "selectExpression", nice_type_name: "parser select expression")
|
|
|
|
guard let selector_node = node.child(at: 2),
|
|
selector_node.nodeType == "expression"
|
|
else {
|
|
return .Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(), withError: "Could not find selector expression"))
|
|
}
|
|
|
|
guard let select_body_node = node.child(at: 5),
|
|
select_body_node.nodeType == "selectBody"
|
|
else {
|
|
return .Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(),
|
|
withError: "Could not find select expression body"))
|
|
}
|
|
|
|
let maybe_selector = CST.Expression.Parse(node: selector_node, withContext: context)
|
|
guard case .Ok(let selector) = maybe_selector else {
|
|
return .Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: selector_node.toSourceLocation(),
|
|
withError:
|
|
"Could not parse transition select expression selector expression: \(maybe_selector.error()!)"
|
|
))
|
|
}
|
|
|
|
var sces: [CST.SelectCaseExpression] = Array()
|
|
var sces_errors: (any Errorable)? = .none
|
|
|
|
select_body_node.enumerateNamedChildren { current_node in
|
|
let maybe_parsed_cse = CST.SelectCaseExpression.ParseExpression(
|
|
node: current_node, withContext: context)
|
|
switch maybe_parsed_cse {
|
|
case .Ok(let parsed_cse): sces.append(parsed_cse as! CST.SelectCaseExpression)
|
|
case .Error(let e):
|
|
sces_errors =
|
|
if let sces_errors = sces_errors {
|
|
sces_errors.append(error: Error(withMessage: "\(maybe_parsed_cse.error()!)"))
|
|
} else {
|
|
e
|
|
}
|
|
}
|
|
}
|
|
|
|
if let sces_errors = sces_errors {
|
|
return .Error(ErrorWithLabel("Error(s) parsing select cases", sces_errors))
|
|
}
|
|
|
|
return .Ok(
|
|
CST.SelectExpression(withSelector: selector, withSelectCaseExpressions: sces),
|
|
)
|
|
}
|
|
}
|
|
|
|
extension CST.SelectCaseExpression: ParsableExpression {
|
|
public static func ParseExpression(
|
|
node: Node, withContext context: CSTCompilerContext
|
|
) -> Result<CST.AnExpression> {
|
|
|
|
#RequireNodeType<Node, CST.AnExpression>(
|
|
node: node, type: "selectCase", nice_type_name: "Select Case")
|
|
|
|
guard let keysetexpression_node = node.child(at: 0),
|
|
keysetexpression_node.nodeType == "keysetExpression"
|
|
else {
|
|
return Result.Error(Error(withMessage: "Missing keyset expression in select case"))
|
|
}
|
|
|
|
guard let targetstate_node = node.child(at: 2),
|
|
targetstate_node.nodeType == "identifier"
|
|
else {
|
|
return Result.Error(Error(withMessage: "Missing target state in select case"))
|
|
}
|
|
|
|
let maybe_parsed_keysetexpression = CST.KeysetExpression.ParseExpression(
|
|
node: keysetexpression_node, withContext: context)
|
|
guard case Result.Ok(let maybe_keysetexpression) = maybe_parsed_keysetexpression else {
|
|
return Result.Error(maybe_parsed_keysetexpression.error()!)
|
|
}
|
|
|
|
let keysetexpression = maybe_keysetexpression as! CST.KeysetExpression
|
|
|
|
let maybe_parsed_targetstate = CST.Identifier.ParseExpression(
|
|
node: targetstate_node, withContext: context)
|
|
guard case .Ok(let targetstate) = maybe_parsed_targetstate else {
|
|
return Result.Error(maybe_parsed_targetstate.error()!)
|
|
}
|
|
|
|
return .Ok(
|
|
CST.SelectCaseExpression(
|
|
withKey: keysetexpression, withNextState: targetstate as! CST.Identifier)
|
|
)
|
|
}
|
|
}
|
|
|
|
extension CST.BinaryOperatorExpression: ParsableExpression {
|
|
public static func ParseExpression(
|
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
|
) -> Result<CST.AnExpression> {
|
|
let expression = node.child(at: 0)!
|
|
|
|
#RequireNodeType<Node, CST.AnExpression>(
|
|
node: expression, type: "binaryOperatorExpression",
|
|
nice_type_name: "Binary Operator Expression")
|
|
let binary_operator_expression_node = expression.child(at: 0)!
|
|
var walker = Walker(node: binary_operator_expression_node)
|
|
|
|
var current_node: Node? = .none
|
|
#MustOr(
|
|
result: current_node, thing: walker.getNext(),
|
|
or: Result<CST.AnExpression>.Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(), withError: "Malformed binary operator expression"
|
|
)))
|
|
|
|
/// TODO: This macro cannot handle new lines in the arrays
|
|
// swift-format-ignore
|
|
#RequireNodesType<Node, CST.AnExpression>(
|
|
nodes: binary_operator_expression_node,
|
|
type: ["binaryEqualOperatorExpression", "binaryLessThanOperatorExpression", "binaryLessThanEqualOperatorExpression", "binaryGreaterThanOperatorExpression", "binaryGreaterThanEqualOperatorExpression", "binaryAndOperatorExpression", "binaryOrOperatorExpression", "binaryAddOperatorExpression", "binarySubtractOperatorExpression", "binaryMultiplyOperatorExpression", "binaryDivideOperatorExpression"],
|
|
nice_type_names: [ "binary equal operator", "binary less than operator", "binary less than or equal to operator", "binary greater than operator", "binary greater than or equal to operator", "binary and operator", "binary or operator", "binary add operator", "binary subtract operator", "binary multiply operator", "binary divide operator"])
|
|
#MustOr(
|
|
result: current_node, thing: walker.getNext(),
|
|
or: Result<CST.AnExpression>.Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(),
|
|
withError: "Missing LHS for binary operator expression")))
|
|
|
|
let left_hand_side_raw = current_node!
|
|
|
|
walker.next()
|
|
#MustOr(
|
|
result: current_node, thing: walker.getNext(),
|
|
or: Result<CST.AnExpression>.Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(),
|
|
withError: "Missing binary operator for binary operator expression")))
|
|
|
|
walker.next()
|
|
#MustOr(
|
|
result: current_node, thing: walker.getNext(),
|
|
or: Result<CST.AnExpression>.Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(),
|
|
withError: "Missing RHS for binary operator expression")))
|
|
|
|
let right_hand_side_raw = current_node!
|
|
|
|
let maybe_left_hand_side = CST.Expression.Parse(
|
|
node: left_hand_side_raw, withContext: context)
|
|
guard case Result.Ok(let left_hand_side) = maybe_left_hand_side else {
|
|
return Result.Error(maybe_left_hand_side.error()!)
|
|
}
|
|
|
|
let maybe_right_hand_side = CST.Expression.Parse(
|
|
node: right_hand_side_raw, withContext: context)
|
|
guard case Result.Ok(let right_hand_side) = maybe_right_hand_side else {
|
|
return Result.Error(maybe_right_hand_side.error()!)
|
|
}
|
|
|
|
let evaluators: [String: (String, P4QualifiedType, CST.BinaryOperatorExpressionType)] = [
|
|
"binaryEqualOperatorExpression": (
|
|
"Binary Equal", P4QualifiedType(P4Boolean()),
|
|
CST.BinaryOperatorExpressionType.Eq
|
|
),
|
|
"binaryLessThanOperatorExpression": (
|
|
"Binary Less Than", P4QualifiedType(P4Boolean()),
|
|
CST.BinaryOperatorExpressionType.Lt
|
|
),
|
|
"binaryLessThanEqualOperatorExpression": (
|
|
"Binary Less Than Or Equal", P4QualifiedType(P4Boolean()),
|
|
CST.BinaryOperatorExpressionType.Lte
|
|
),
|
|
"binaryGreaterThanOperatorExpression": (
|
|
"Binary Greater Than", P4QualifiedType(P4Boolean()),
|
|
CST.BinaryOperatorExpressionType.Gt
|
|
),
|
|
"binaryGreaterThanEqualOperatorExpression": (
|
|
"Binary Greater Than Or Equal", P4QualifiedType(P4Boolean()),
|
|
CST.BinaryOperatorExpressionType.Gte
|
|
),
|
|
"binaryAndOperatorExpression": (
|
|
"Binary Or", P4QualifiedType(P4Boolean()),
|
|
CST.BinaryOperatorExpressionType.And
|
|
),
|
|
"binaryOrOperatorExpression": (
|
|
"Binary And", P4QualifiedType(P4Boolean()),
|
|
CST.BinaryOperatorExpressionType.Or
|
|
),
|
|
"binaryAddOperatorExpression": (
|
|
"Binary Add", P4QualifiedType(P4Int()),
|
|
CST.BinaryOperatorExpressionType.Add
|
|
),
|
|
"binarySubtractOperatorExpression": (
|
|
"Binary Subtract", P4QualifiedType(P4Int()),
|
|
CST.BinaryOperatorExpressionType.Subtract
|
|
),
|
|
"binaryMultiplyOperatorExpression": (
|
|
"Binary Multiply", P4QualifiedType(P4Int()),
|
|
CST.BinaryOperatorExpressionType.Multiply
|
|
),
|
|
"binaryDivideOperatorExpression": (
|
|
"Binary Divide", P4QualifiedType(P4Int()),
|
|
CST.BinaryOperatorExpressionType.Divide
|
|
),
|
|
]
|
|
|
|
guard let selected_evaluator = evaluators[binary_operator_expression_node.nodeType!] else {
|
|
return Result.Error(
|
|
Error(withMessage: "No evaluator for \(binary_operator_expression_node.nodeType!)"))
|
|
}
|
|
|
|
return .Ok(
|
|
CST.BinaryOperatorExpression(
|
|
withType: selected_evaluator.2,
|
|
withLhs: left_hand_side, withRhs: right_hand_side))
|
|
}
|
|
}
|
|
|
|
extension CST.ArrayAccessExpression: ParsableExpression {
|
|
public static func ParseExpression(
|
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
|
) -> Result<CST.AnExpression> {
|
|
let expression = node.child(at: 0)!
|
|
|
|
#RequireNodeType<Node, CST.AnExpression>(
|
|
node: expression, type: "arrayAccessExpression", nice_type_name: "Array Access Expression")
|
|
let array_access_expression_node = expression
|
|
|
|
var walker = Walker(node: array_access_expression_node)
|
|
var current_node: Node? = .none
|
|
|
|
#MustOr(
|
|
result: current_node, thing: walker.getNext(),
|
|
or: Result<CST.AnExpression>.Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(), withError: "Malformed array access expression")))
|
|
|
|
#RequireNodeType<Node, CST.AnExpression>(
|
|
node: current_node!, type: "expression",
|
|
nice_type_name: "array identifier expression")
|
|
let array_access_identifier_node = current_node!
|
|
|
|
walker.next()
|
|
#MustOr(
|
|
result: current_node, thing: walker.getNext(),
|
|
or: Result<CST.AnExpression>.Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(),
|
|
withError: "Missing [ for array access expression")))
|
|
|
|
walker.next()
|
|
|
|
#MustOr(
|
|
result: current_node, thing: walker.getNext(),
|
|
or: Result<CST.AnExpression>.Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(),
|
|
withError: "Missing indexor expression for array access expression")))
|
|
|
|
#RequireNodeType<Node, CST.AnExpression>(
|
|
node: current_node!, type: "expression",
|
|
nice_type_name: "array indexor expression")
|
|
|
|
let array_access_indexor_node = current_node!
|
|
|
|
let maybe_array_identifier = CST.Expression.Parse(
|
|
node: array_access_identifier_node, withContext: context)
|
|
guard case Result.Ok(let array_identifier) = maybe_array_identifier else {
|
|
return Result.Error(maybe_array_identifier.error()!)
|
|
}
|
|
|
|
let maybe_array_indexor = CST.Expression.Parse(
|
|
node: array_access_indexor_node, withContext: context)
|
|
guard case Result.Ok(let array_indexor) = maybe_array_indexor else {
|
|
return Result.Error(maybe_array_indexor.error()!)
|
|
}
|
|
|
|
return .Ok(
|
|
CST.ArrayAccessExpression(
|
|
withName: array_identifier, withIndexor: array_indexor))
|
|
}
|
|
}
|
|
|
|
extension CST.FieldAccessExpression: ParsableExpression {
|
|
public static func ParseExpression(
|
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
|
) -> Result<CST.AnExpression> {
|
|
let expression = node.child(at: 0)!
|
|
|
|
#RequireNodeType<Node, CST.AnExpression>(
|
|
node: expression, type: "fieldAccessExpression", nice_type_name: "Array Access Expression")
|
|
|
|
let field_access_expression_node = expression
|
|
|
|
var walker = Walker(node: field_access_expression_node)
|
|
var current_node: Node? = .none
|
|
|
|
#MustOr(
|
|
result: current_node, thing: walker.getNext(),
|
|
or: Result<CST.AnExpression>.Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(), withError: "Malformed field access expression")))
|
|
|
|
#RequireNodeType<Node, CST.AnExpression>(
|
|
node: current_node!, type: "expression",
|
|
nice_type_name: "struct identifier expression")
|
|
let struct_identifier_node = current_node!
|
|
|
|
walker.next()
|
|
#MustOr(
|
|
result: current_node, thing: walker.getNext(),
|
|
or: Result<CST.AnExpression>.Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(),
|
|
withError: "Missing . for field access expression")))
|
|
|
|
walker.next()
|
|
#MustOr(
|
|
result: current_node, thing: walker.getNext(),
|
|
or: Result<CST.AnExpression>.Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(),
|
|
withError: "Missing field name for field access expression")))
|
|
|
|
#RequireNodeType<Node, CST.AnExpression>(
|
|
node: current_node!, type: "identifier",
|
|
nice_type_name: "field name")
|
|
|
|
let field_name_node = current_node!
|
|
|
|
// Make sure that the identifier really identifies a struct.
|
|
let maybe_struct_identifier = CST.Expression.Parse(
|
|
node: struct_identifier_node, withContext: context)
|
|
guard case Result.Ok(let struct_identifier) = maybe_struct_identifier else {
|
|
return Result.Error(maybe_struct_identifier.error()!)
|
|
}
|
|
|
|
let maybe_field_name = CST.Identifier.ParseExpression(
|
|
node: field_name_node, withContext: context)
|
|
guard case Result.Ok(let field_name) = maybe_field_name else {
|
|
return Result.Error(maybe_field_name.error()!)
|
|
}
|
|
|
|
return .Ok(
|
|
CST.FieldAccessExpression(
|
|
withStruct: struct_identifier,
|
|
withField: field_name as! CST.Identifier))
|
|
}
|
|
}
|
|
|
|
extension CST.FunctionCall: ParsableExpression {
|
|
public static func ParseExpression(
|
|
node: Node, withContext context: CSTCompilerContext
|
|
) -> Result<CST.AnExpression> {
|
|
|
|
let expression = node.child(at: 0)!
|
|
#RequireNodeType<Node, CST.AnExpression>(
|
|
node: expression, type: "function_call", nice_type_name: "Function Call")
|
|
|
|
var walker = Walker(node: expression)
|
|
var current_node: Node? = .none
|
|
|
|
#MustOr(
|
|
result: current_node, thing: walker.getNext(),
|
|
or: Result<CST.AnExpression>.Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
|
|
|
let maybe_callee_name = CST.Identifier.ParseExpression(
|
|
node: current_node!, withContext: context)
|
|
guard case .Ok(let callee_name) = maybe_callee_name else {
|
|
return Result.Error(maybe_callee_name.error()!)
|
|
}
|
|
walker.next()
|
|
|
|
#MustOr(
|
|
result: current_node, thing: walker.getNext(),
|
|
or: Result<CST.AnExpression>.Error(
|
|
ErrorWithLocation(
|
|
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
|
|
|
let maybe_argument_list = CST.ArgumentList.Parse(node: current_node!, withContext: context)
|
|
|
|
guard case .Ok(let arguments) = maybe_argument_list else {
|
|
return .Error(maybe_argument_list.error()!)
|
|
}
|
|
return .Ok(CST.FunctionCall(callee_name as! CST.Identifier, withArguments: arguments))
|
|
}
|
|
}
|