From 757cf37578302ec8bd90a6d24d0a670bc5c815ba Mon Sep 17 00:00:00 2001 From: Trevor Maze Date: Sat, 31 Jan 2026 23:31:45 -0500 Subject: [PATCH] Streamlined looping --- Sources/rxcc/rxcc.swift | 229 ++++++++++++++++++++++++++++++++-------- 1 file changed, 186 insertions(+), 43 deletions(-) diff --git a/Sources/rxcc/rxcc.swift b/Sources/rxcc/rxcc.swift index 38b6290..6c83180 100644 --- a/Sources/rxcc/rxcc.swift +++ b/Sources/rxcc/rxcc.swift @@ -65,6 +65,15 @@ enum TokenType { case MULTIPLICATION case DIVISION + case LOGICAL_AND + case LOGICAL_OR + case EQUAL + case NOT_EQUAL + case LESS_THAN + case LESS_THAN_OR_EQUAL_TO + case GREATER_THAN + case GREATER_THAN_OR_EQUAL_TO + case UNDEFINED } @@ -76,6 +85,7 @@ struct Token { typealias Construct = [Element] enum Element { + case Loop(type: ConstructType) case Construct(type: ConstructType) case Token(type: TokenType) } @@ -86,6 +96,14 @@ enum ConstructVariant { case Multiplication case Division + case LessThan + case LessThanOrEqualTo + case GreaterThan + case GreaterThanOrEqualTo + + case EqualTo + case NotEqualTo + // Unary operation variants case Negation case BitwiseCompliment @@ -118,14 +136,22 @@ enum ConstructVariant { enum ConstructType { case UnaryOperator + case MultiplicationPriorityOperator case AdditionPriorityOperator - case Expression - case Factor - case Term - case Statement - case Function + case InequalityPriorityOperator + case EqualityPriorityOperator + case Program + case Function + case Statement + case Expression + case LogicalAndExpression + case EqualityExpression + case RelationalExpression + case AdditiveExpression + case Term + case Factor } struct ConstructDefinitions { @@ -164,17 +190,41 @@ let constructDefinitions: Dictionary [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: " == ") + 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(" +")) @@ -519,7 +577,7 @@ func parse(lexed: [Substring]) -> String { let abstractSyntaxTree = SyntaxTreeNode(.Root) - if validateConstruct(program.variants[.SingleFunction]!, tokens: &tokens, node: abstractSyntaxTree, loopingEnabled: false) != .Invalid { + if validateConstruct(type: .Program, variant: .SingleFunction, tokens: &tokens, node: abstractSyntaxTree) != .Invalid { print("Success") print(abstractSyntaxTree.text()) print("Assembly:") @@ -539,7 +597,7 @@ enum Validity { case Break } -func validateConstruct(_ construct: Construct, tokens: inout [Token], node: SyntaxTreeNode, loopingEnabled: Bool) -> Validity { +func validateConstruct(type: ConstructType, variant: ConstructVariant, tokens: inout [Token], node: SyntaxTreeNode) -> Validity { var indent: String { var count: Int = 0 var child: SyntaxTreeNode = node @@ -550,10 +608,119 @@ func validateConstruct(_ construct: Construct, tokens: inout [Token], node: Synt return String(repeating: " ", count: count) } - var loop: Bool = loopingEnabled + var loop: Bool = false repeat { + let construct = constructDefinitions[type]![variant]! for element in construct { switch element { + case .Loop(let constructType): + /* + var matchingOperator: Bool = false + + print("\(indent)Determining need for loop") + let tokenBackup: [Token] = tokens + for constructVariant in constructDefinitions[constructType]!.keys { + let childNode = node.addChild(value: variant) + print("\(indent)Testing operator \(constructType)::\(constructVariant)") + let valid = validateConstruct(type: constructType, variant: constructVariant, tokens: &tokens, node: node) + if valid == .Panic { + return .Invalid + } else if valid == .Invalid { + tokens = tokenBackup + _ = node.popLastChild() + continue + } + matchingOperator = true + break + } + + loop = matchingOperator + if loop { + print("\(indent)Looping") + } else { + print("\(indent)Not looping") + return .Valid + } + +*/ + + + + + + var valid: Validity = .Invalid + var matchingOperator: Bool = false + print("\(indent)Determining need to loop construct of type \(constructType)") + let tokenBackup: [Token] = tokens + for constructVariant in constructDefinitions[constructType]!.keys { + let childNode = node.addChild(value: constructVariant) + print("\(indent)Testing operator \(constructType)::\(constructVariant)") + + valid = validateConstruct(type: constructType, variant: constructVariant, tokens: &tokens, node: childNode) + if valid == .Panic { + print("\(indent)Fail: panic (variant \"\(constructVariant)\"))\n") + return .Invalid + } else if valid == .Invalid { + tokens = tokenBackup + _ = node.popLastChild() + continue + } + matchingOperator = true + break + } + + loop = matchingOperator + + if loop { + print("\(indent)Looping") + } else { + print("\(indent)Not looping") + break + } + +/* + if valid == .Invalid { + print("\(indent)Subconstruct validation failed") + return .Invalid + } else if valid == .Break { + print("\(indent)End validate subconstruct (variant \"\(validVariant) by breaking\")") + break + } + */ + + //print("\(indent)End validate subconstruct (variant \"\(validVariant)\")") + break + + case .Token(let type): + if let token: Token = tokens.popLast() { + if type != token.type { + print("\(indent)VALIDATION FAILED FOR TOKEN \"\(token.content)\"") + return .Invalid + } + print("\(indent)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("\(indent)RAN OUT OF TOKENS") + return .Invalid + } + + + + + + + + break + case .Construct(let type): print("\(indent)Begin validate subconstruct (type \"\(type)\")") @@ -568,7 +735,7 @@ func validateConstruct(_ construct: Construct, tokens: inout [Token], node: Synt } print("\(indent)Testing variant \(variant) (Loop = \(loop)) (Loopable = \(loopable))") - valid = validateConstruct(constructDefinitions[type]![variant]!, tokens: &tokens, node: childNode, loopingEnabled: loopable) + valid = validateConstruct(type: type, variant: variant, tokens: &tokens, node: childNode) if valid == .Panic { print("\(indent)Fail: panic (variant \"\(variant)\"))\n") return .Invalid @@ -587,38 +754,6 @@ func validateConstruct(_ construct: Construct, tokens: inout [Token], node: Synt - if loopingEnabled { - // Factor looping nonsense - if type == .Factor { - let nextToken: Token = tokens[tokens.count - 1] - if nextToken.type == .MULTIPLICATION || nextToken.type == .DIVISION { - print("\(indent)Looping due to factor") - loop = true - } else { - if node.children.count != 0 { - print("\(indent)Breaking out of factor loop") - loop = false - return .Break - } else { - print("\(indent)ERROR: FactorSequence has no children") - return .Panic - } - } - } - - // Term looping nonsense - else if type == .Term { - let nextToken: Token = tokens[tokens.count - 1] - if nextToken.type == .ADDITION || nextToken.type == .NEGATION { - print("\(indent)Looping due to term") - loop = true - } else { - print("\(indent)Breaking out of term loop") - loop = false - return .Break - } - } - } @@ -678,6 +813,14 @@ func categorizeToken(token: Substring) -> TokenType { else if token.firstMatch(of: /^\+$/) != nil { return .ADDITION } else if token.firstMatch(of: /^\*$/) != nil { return .MULTIPLICATION } else if token.firstMatch(of: /^\/$/) != nil { return .DIVISION } + else if token.firstMatch(of: /^&&$/) != nil { return .LOGICAL_AND } + else if token.firstMatch(of: /^||$/) != nil { return .LOGICAL_OR } + else if token.firstMatch(of: /^==$/) != nil { return .EQUAL } + else if token.firstMatch(of: /^!=$/) != nil { return .NOT_EQUAL } + else if token.firstMatch(of: /^<$/) != nil { return .LESS_THAN } + else if token.firstMatch(of: /^<=$/) != nil { return .LESS_THAN_OR_EQUAL_TO } + else if token.firstMatch(of: /^>$/) != nil { return .GREATER_THAN } + else if token.firstMatch(of: /^>=$/) != nil { return .GREATER_THAN_OR_EQUAL_TO } return .UNDEFINED }