Logical operators and equality/inequality operators

This commit is contained in:
2026-02-02 20:57:00 -05:00
parent df6c897fde
commit e08bb2ff95
3 changed files with 189 additions and 49 deletions

View File

@@ -230,7 +230,7 @@ let constructDefinitions: Dictionary<ConstructType, Dictionary<ConstructVariant,
],
.LogicalOrPriorityOperator: [
.LogicalAnd: [
.LogicalOr: [
.Token(type: .LOGICAL_OR),
],
],
@@ -394,7 +394,7 @@ func getTestFiles() -> [TestFile] {
var testFiles: [TestFile] = [TestFile]()
let fileManager = FileManager.default
let path = "c/tests/stage_3"
let path = "c/tests/stage_4"
do {
let validItems = try fileManager.contentsOfDirectory(atPath: path + "/valid")
@@ -438,14 +438,14 @@ 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: " && ")
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(" +"))
@@ -474,26 +474,195 @@ func generateOutput(_ node: SyntaxTreeNode) -> String {
break
case .LogicalAndExpressionSequence:
for child in node.children {
var operation: ConstructVariant = .Error
let count = node.children.count
if count == 0 {
print("ERROR: \(node.variant) with no children")
break
}
for i in 0...count - 1 {
let child: SyntaxTreeNode = node.children[i]
let uuid: String = String(UUID().uuidString.split(separator: "-")[0])
// Operation
if i % 2 == 1 {
operation = child.variant
continue
}
text += generateOutput(child)
switch operation {
case .LogicalOr:
text += " movl\t%eax, %ecx\n" // Put e2 in ecx
text += " pop \t%eax\n" // Put e1 in eax
text += " cmpl\t$0, %eax\n"
text += " je \tlabel_\(uuid)\n"
text += " movl\t$1, %eax\n"
text += " jmp \tend_\(uuid)\n"
text += "label_\(uuid):\n"
text += " movl\t%ecx, %eax\n" // Put e2 in eax
text += " cmpl\t$0, %eax\n"
text += " movl\t$0, %eax\n"
text += " setne\t%al\n"
text += "end_\(uuid):\n"
default:
if i != 0 {
print("Unknown operation \"\(operation)\" in \(node.variant)")
}
break
}
if i != node.children.count - 1 {
text += " push\t%eax\n"
}
}
break
case .EqualityExpressionSequence:
for child in node.children {
var operation: ConstructVariant = .Error
let count = node.children.count
if count == 0 {
print("ERROR: \(node.variant) with no children")
break
}
for i in 0...count - 1 {
let child: SyntaxTreeNode = node.children[i]
let uuid: String = String(UUID().uuidString.split(separator: "-")[0])
// Operation
if i % 2 == 1 {
operation = child.variant
continue
}
text += generateOutput(child)
switch operation {
case .LogicalAnd:
text += " movl\t%eax, %ecx\n" // Put e2 in ecx
text += " pop \t%eax\n" // Put e1 in eax
text += " cmpl\t$0, %eax\n"
text += " jne \tlabel_\(uuid)\n"
text += " jmp \tend_\(uuid)\n"
text += "label_\(uuid):\n"
text += " movl\t%ecx, %eax\n" // Put e2 in eax
text += " cmpl\t$0, %eax\n"
text += " movl\t$0, %eax\n"
text += " setne\t%al\n"
text += "end_\(uuid):\n"
default:
if i != 0 {
print("Unknown operation \"\(operation)\" in \(node.variant)")
}
break
}
if i != node.children.count - 1 {
text += " push\t%eax\n"
}
}
break
case .RelationalExpressionSequence:
for child in node.children {
var operation: ConstructVariant = .Error
let count = node.children.count
if count == 0 {
print("ERROR: \(node.variant) with no children")
break
}
for i in 0...count - 1 {
let child: SyntaxTreeNode = node.children[i]
// Operation
if i % 2 == 1 {
operation = child.variant
continue
}
text += generateOutput(child)
switch operation {
case .EqualTo:
text += " pop \t%ecx\n"
text += " cmpl\t%eax, %ecx\n"
text += " movl\t$0, %eax\n"
text += " sete\t%al\n"
case .NotEqualTo:
text += " pop \t%ecx\n"
text += " cmpl\t%eax, %ecx\n"
text += " movl\t$0, %eax\n"
text += " setne\t%al\n"
default:
if i != 0 {
print("Unknown operation \"\(operation)\" in \(node.variant)")
}
break
}
if i != node.children.count - 1 {
text += " push\t%eax\n"
}
}
break
case .AdditiveExpressionSequence:
for child in node.children {
var operation: ConstructVariant = .Error
let count = node.children.count
if count == 0 {
print("ERROR: \(node.variant) with no children")
break
}
for i in 0...count - 1 {
let child: SyntaxTreeNode = node.children[i]
// Operation
if i % 2 == 1 {
operation = child.variant
continue
}
text += generateOutput(child)
switch operation {
case .LessThan:
text += " pop \t%ecx\n"
text += " cmpl\t%eax, %ecx\n"
text += " movl\t$0, %eax\n"
text += " setl\t%al\n"
case .LessThanOrEqualTo:
text += " pop \t%ecx\n"
text += " cmpl\t%eax, %ecx\n"
text += " movl\t$0, %eax\n"
text += " setle\t%al\n"
case .GreaterThan:
text += " pop \t%ecx\n"
text += " cmpl\t%eax, %ecx\n"
text += " movl\t$0, %eax\n"
text += " setg\t%al\n"
case .GreaterThanOrEqualTo:
text += " pop \t%ecx\n"
text += " cmpl\t%eax, %ecx\n"
text += " movl\t$0, %eax\n"
text += " setge\t%al\n"
default:
if i != 0 {
print("Unknown operation \"\(operation)\" in \(node.variant)")
}
break
}
if i != node.children.count - 1 {
text += " push\t%eax\n"
}
}
break
@@ -501,7 +670,7 @@ func generateOutput(_ node: SyntaxTreeNode) -> String {
var operation: ConstructVariant = .Error
let count = node.children.count
if count == 0 {
print("ERROR: FactorSequence with no children")
print("ERROR: \(node.variant) with no children")
break
}
for i in 0...count - 1 {
@@ -527,7 +696,7 @@ func generateOutput(_ node: SyntaxTreeNode) -> String {
default:
if i != 0 {
print("Unknown operation \"\(operation)\" in FactorSequence")
print("Unknown operation \"\(operation)\" in \(node.variant)")
}
break
}
@@ -690,40 +859,6 @@ func validateConstruct(type: ConstructType, variant: ConstructVariant, tokens: i
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)")
@@ -800,6 +935,7 @@ func validateConstruct(type: ConstructType, variant: ConstructVariant, tokens: i
if let token: Token = tokens.popLast() {
if type != token.type {
print("\(indent)VALIDATION FAILED FOR TOKEN \"\(token.content)\"")
print("\(indent)AKA, \(type) not equal to \(token.type)")
return .Invalid
}
print("\(indent)Validated token \"\(token.content)\"")
@@ -841,7 +977,7 @@ func categorizeToken(token: Substring) -> TokenType {
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 .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 }

4
oldtest.c Normal file
View File

@@ -0,0 +1,4 @@
int main() {
return !(4 + -4) + 6 / (2 + 2) * -4 * ~4 / 9 + -(4 / (5 * (32 / 2) + ~1) - (400 / 90 + 1) - -~((5 / 4) * (2 + 3) / -9));
}

2
test.c
View File

@@ -1,4 +1,4 @@
int main() {
return !(4 + -4) + 6 / (2 + 2) * -4 * ~4 / 9 + -(4 / (5 * (32 / 2) + ~1) - (400 / 90 + 1) - -~((5 / 4) * (2 + 3) / -9));
return 1 || 0 && 2;
}