diff --git a/Sources/SwiftParser/CodeParser.swift b/Sources/SwiftParser/CodeParser.swift index 051f733..eb8d17e 100644 --- a/Sources/SwiftParser/CodeParser.swift +++ b/Sources/SwiftParser/CodeParser.swift @@ -3,12 +3,12 @@ import Foundation public final class CodeParser { private var builders: [CodeElementBuilder] private let tokenizer: CodeTokenizer - private var expressionBuilder: CodeExpressionBuilder? + private var expressionBuilders: [CodeExpressionBuilder] - public init(tokenizer: CodeTokenizer, builders: [CodeElementBuilder] = [], expressionBuilder: CodeExpressionBuilder? = nil) { + public init(tokenizer: CodeTokenizer, builders: [CodeElementBuilder] = [], expressionBuilders: [CodeExpressionBuilder] = []) { self.tokenizer = tokenizer self.builders = builders - self.expressionBuilder = expressionBuilder + self.expressionBuilders = expressionBuilders } public func register(builder: CodeElementBuilder) { @@ -20,7 +20,7 @@ public final class CodeParser { } public func register(expressionBuilder: CodeExpressionBuilder) { - self.expressionBuilder = expressionBuilder + expressionBuilders.append(expressionBuilder) } public func parse(_ input: String, rootNode: CodeNode) -> (node: CodeNode, context: CodeContext) { @@ -39,11 +39,16 @@ public final class CodeParser { break } } - if !matched, let expr = expressionBuilder, expr.accept(context: context, token: token) { - if let node = expr.parse(context: &context) { - context.currentNode.addChild(node) + if !matched { + for expr in expressionBuilders { + if expr.accept(context: context, token: token) { + if let node = expr.parse(context: &context) { + context.currentNode.addChild(node) + } + matched = true + break + } } - matched = true } if !matched { context.errors.append(CodeError("Unrecognized token \(token.kindDescription)", range: token.range)) @@ -59,7 +64,13 @@ public final class CodeParser { } public func parseExpression(context: inout CodeContext, minBP: Int = 0) -> CodeNode? { - guard let expr = expressionBuilder else { return nil } - return expr.parse(context: &context, minBP: minBP) + guard context.index < context.tokens.count else { return nil } + let token = context.tokens[context.index] + for expr in expressionBuilders { + if expr.accept(context: context, token: token) { + return expr.parse(context: &context, minBP: minBP) + } + } + return nil } } diff --git a/Sources/SwiftParser/Core.swift b/Sources/SwiftParser/Core.swift index 13fa0b5..ad4954e 100644 --- a/Sources/SwiftParser/Core.swift +++ b/Sources/SwiftParser/Core.swift @@ -75,5 +75,5 @@ public protocol CodeLanguage { var tokenizer: CodeTokenizer { get } var builders: [CodeElementBuilder] { get } var rootElement: any CodeElement { get } - var expressionBuilder: CodeExpressionBuilder? { get } + var expressionBuilders: [CodeExpressionBuilder] { get } } diff --git a/Sources/SwiftParser/Languages/MarkdownLanguage.swift b/Sources/SwiftParser/Languages/MarkdownLanguage.swift index c91e133..54da274 100644 --- a/Sources/SwiftParser/Languages/MarkdownLanguage.swift +++ b/Sources/SwiftParser/Languages/MarkdownLanguage.swift @@ -128,7 +128,7 @@ public struct MarkdownLanguage: CodeLanguage { public var tokenizer: CodeTokenizer { Tokenizer() } public var builders: [CodeElementBuilder] { [HeadingBuilder(), ParagraphBuilder()] } - public var expressionBuilder: CodeExpressionBuilder? { nil } + public var expressionBuilders: [CodeExpressionBuilder] { [] } public var rootElement: any CodeElement { Element.root } public init() {} } diff --git a/Sources/SwiftParser/Languages/PythonLanguage.swift b/Sources/SwiftParser/Languages/PythonLanguage.swift index c4326d4..0f0bf90 100644 --- a/Sources/SwiftParser/Languages/PythonLanguage.swift +++ b/Sources/SwiftParser/Languages/PythonLanguage.swift @@ -313,7 +313,7 @@ public struct PythonLanguage: CodeLanguage { return [NewlineBuilder(), FunctionBuilder(), AssignmentBuilder(expressionBuilder: expr)] } - public var expressionBuilder: CodeExpressionBuilder? { ExpressionBuilder() } + public var expressionBuilders: [CodeExpressionBuilder] { [ExpressionBuilder()] } public var rootElement: any CodeElement { Element.root } diff --git a/Sources/SwiftParser/SwiftParser.swift b/Sources/SwiftParser/SwiftParser.swift index 2086b37..0efcb89 100644 --- a/Sources/SwiftParser/SwiftParser.swift +++ b/Sources/SwiftParser/SwiftParser.swift @@ -6,7 +6,7 @@ public struct SwiftParser { public func parse(_ source: String, language: CodeLanguage) -> ParsedSource { let root = CodeNode(type: language.rootElement, value: "") - let parser = CodeParser(tokenizer: language.tokenizer, builders: language.builders, expressionBuilder: language.expressionBuilder) + let parser = CodeParser(tokenizer: language.tokenizer, builders: language.builders, expressionBuilders: language.expressionBuilders) let result = parser.parse(source, rootNode: root) return ParsedSource(content: source, root: result.node, errors: result.context.errors) }