From cde395a2a95a1687a9ec99a0146a8c28efc48c4f Mon Sep 17 00:00:00 2001 From: Trevor Maze Date: Thu, 29 Jan 2026 21:51:43 -0500 Subject: [PATCH] Blood, sweat, and tears... And it's only stage 3 --- Sources/rxcc/rxcc.swift | 181 ++++++++++++++++++++++++++-------------- 1 file changed, 118 insertions(+), 63 deletions(-) diff --git a/Sources/rxcc/rxcc.swift b/Sources/rxcc/rxcc.swift index 35e3ed9..cc8c866 100644 --- a/Sources/rxcc/rxcc.swift +++ b/Sources/rxcc/rxcc.swift @@ -92,12 +92,10 @@ enum ConstructVariant { case LogicalNegation // Expression variants - case AdditionPriorityOperation - case SingleTerm + case TermSequence // Term variants - case MultiplicationPriorityOperation - case SingleFactor + case FactorSequence // Factor variants case LiteralInteger @@ -167,24 +165,16 @@ let constructDefinitions: Dictionary [TestFile] { var testFiles: [TestFile] = [TestFile]() let fileManager = FileManager.default - let path = "c/tests/stage_2" + let path = "c/tests/stage_3" do { let validItems = try fileManager.contentsOfDirectory(atPath: path + "/valid") @@ -343,6 +333,9 @@ func lex(string: String) -> [Substring] { line = line.replacing("-", with: " - ") line = line.replacing("~", with: " ~ ") line = line.replacing("!", with: " ! ") + line = line.replacing("+", with: " + ") + line = line.replacing("*", with: " * ") + line = line.replacing("/", with: " / ") do { let tokens: [Substring] = line.split(separator: try Regex(" +")) @@ -365,7 +358,7 @@ func parse(lexed: [Substring]) -> String { let abstractSyntaxTree = SyntaxTreeNode(.Root) - if validateConstruct(program.variants[.SingleFunction]!, tokens: &tokens, node: abstractSyntaxTree) { + if validateConstruct(program.variants[.SingleFunction]!, tokens: &tokens, node: abstractSyntaxTree) != .Invalid { print("Success") print(abstractSyntaxTree.text()) print("Assembly:") @@ -386,7 +379,19 @@ func generateOutput(_ node: SyntaxTreeNode) -> String { text += generateOutput(child) } break - + + case .TermSequence: + for child in node.children { + text += generateOutput(child) + } + break + + case .FactorSequence: + for child in node.children { + text += generateOutput(child) + } + break + case .Integer: text += " .globl \(node.value)\n\(node.value):\n" for child in node.children { @@ -439,61 +444,111 @@ func generateOutput(_ node: SyntaxTreeNode) -> String { return text } -func validateConstruct(_ construct: Construct, tokens: inout [Token], node: SyntaxTreeNode) -> Bool { - for element in construct { - switch element { - case .Construct(let type): - print("Begin validate subconstruct (type \"\(type)\")") +enum Validity { + case Valid + case Invalid + case Break +} - var valid: Bool = false - var validVariant: ConstructVariant = .Error - let tokenBackup: [Token] = tokens - for key in constructDefinitions[type]!.keys { - let childNode = node.addChild(value: key) - print("Testing variant \(key)") - if !validateConstruct(constructDefinitions[type]![key]!, tokens: &tokens, node: childNode) { - print("Fail") - tokens = tokenBackup - _ = node.popLastChild() - continue - } - print("Success") - valid = true - validVariant = key - break - } - if !valid { - print("Subconstruct validation failed") - return false - } - print("End validate subconstruct (variant \"\(validVariant)\")") - continue +func validateConstruct(_ construct: Construct, tokens: inout [Token], node: SyntaxTreeNode) -> Validity { + var loop: Bool = false + repeat { + for element in construct { + switch element { + case .Construct(let type): + print("Begin validate subconstruct (type \"\(type)\")") - case .Token(let type): - if let token: Token = tokens.popLast() { - if type != token.type { - print("VALIDATION FAILED FOR TOKEN \"\(token.content)\"") - return false - } - print("Validated token \"\(token.content)\"") + var valid: Validity = .Invalid + var validVariant: ConstructVariant = .Error + let tokenBackup: [Token] = tokens + for key in constructDefinitions[type]!.keys { + let childNode = node.addChild(value: key) + print("Testing variant \(key) (Loop = \(loop))") + valid = validateConstruct(constructDefinitions[type]![key]!, tokens: &tokens, node: childNode) + if valid == .Invalid { + print("Fail") + tokens = tokenBackup + _ = node.popLastChild() + continue + } + print("Success") + validVariant = key - if token.type == .LITERAL_INTEGER { - node.value = String(token.content) + break } - else if token.type == .IDENTIFIER { - node.value = String(token.content) + + + + + // Factor looping nonsense + if type == .Factor { + let nextToken: Token = tokens[tokens.count - 1] + if nextToken.type == .MULTIPLICATION || nextToken.type == .DIVISION { + print("Looping due to factor") + loop = true + } else { + print("Breaking out of factor loop") + loop = false + return .Break + } } + // Term looping nonsense + else if type == .Term { + let nextToken: Token = tokens[tokens.count - 1] + if nextToken.type == .ADDITION || nextToken.type == .NEGATION { + print("Looping due to term") + loop = true + } else { + print("Breaking out of term loop") + loop = false + return .Break + } + } + + + + + if valid == .Invalid { + print("Subconstruct validation failed") + return .Invalid + } else if valid == .Break { + print("End validate subconstruct (variant \"\(validVariant) by breaking\")") + print(type) + break + } + + print("End validate subconstruct (variant \"\(validVariant)\")") + print(type) + continue - } else { - print("RAN OUT OF TOKENS") - return false + case .Token(let type): + if let token: Token = tokens.popLast() { + if type != token.type { + print("VALIDATION FAILED FOR TOKEN \"\(token.content)\"") + return .Invalid + } + print("Validated token \"\(token.content)\"") + + if token.type == .LITERAL_INTEGER { + node.value = String(token.content) + } + else if token.type == .IDENTIFIER { + node.value = String(token.content) + } + + continue + + } else { + print("RAN OUT OF TOKENS") + return .Invalid + } } } - } + } while loop - return true + return .Valid } func categorizeToken(token: Substring) -> TokenType {