Logical operators and equality/inequality operators
This commit is contained in:
@@ -230,7 +230,7 @@ let constructDefinitions: Dictionary<ConstructType, Dictionary<ConstructVariant,
|
|||||||
],
|
],
|
||||||
|
|
||||||
.LogicalOrPriorityOperator: [
|
.LogicalOrPriorityOperator: [
|
||||||
.LogicalAnd: [
|
.LogicalOr: [
|
||||||
.Token(type: .LOGICAL_OR),
|
.Token(type: .LOGICAL_OR),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@@ -394,7 +394,7 @@ func getTestFiles() -> [TestFile] {
|
|||||||
var testFiles: [TestFile] = [TestFile]()
|
var testFiles: [TestFile] = [TestFile]()
|
||||||
|
|
||||||
let fileManager = FileManager.default
|
let fileManager = FileManager.default
|
||||||
let path = "c/tests/stage_3"
|
let path = "c/tests/stage_4"
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let validItems = try fileManager.contentsOfDirectory(atPath: path + "/valid")
|
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: " != ")
|
||||||
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 {
|
do {
|
||||||
let tokens: [Substring] = line.split(separator: try Regex(" +"))
|
let tokens: [Substring] = line.split(separator: try Regex(" +"))
|
||||||
@@ -474,26 +474,195 @@ func generateOutput(_ node: SyntaxTreeNode) -> String {
|
|||||||
break
|
break
|
||||||
|
|
||||||
case .LogicalAndExpressionSequence:
|
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)
|
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
|
break
|
||||||
|
|
||||||
case .EqualityExpressionSequence:
|
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)
|
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
|
break
|
||||||
|
|
||||||
case .RelationalExpressionSequence:
|
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)
|
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
|
break
|
||||||
|
|
||||||
case .AdditiveExpressionSequence:
|
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)
|
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
|
break
|
||||||
|
|
||||||
@@ -501,7 +670,7 @@ func generateOutput(_ node: SyntaxTreeNode) -> String {
|
|||||||
var operation: ConstructVariant = .Error
|
var operation: ConstructVariant = .Error
|
||||||
let count = node.children.count
|
let count = node.children.count
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
print("ERROR: FactorSequence with no children")
|
print("ERROR: \(node.variant) with no children")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
for i in 0...count - 1 {
|
for i in 0...count - 1 {
|
||||||
@@ -527,7 +696,7 @@ func generateOutput(_ node: SyntaxTreeNode) -> String {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
print("Unknown operation \"\(operation)\" in FactorSequence")
|
print("Unknown operation \"\(operation)\" in \(node.variant)")
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -690,40 +859,6 @@ func validateConstruct(type: ConstructType, variant: ConstructVariant, tokens: i
|
|||||||
for element in construct {
|
for element in construct {
|
||||||
switch element {
|
switch element {
|
||||||
case .Loop(let constructType):
|
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 valid: Validity = .Invalid
|
||||||
var matchingOperator: Bool = false
|
var matchingOperator: Bool = false
|
||||||
print("\(indent)Determining need to loop construct of type \(constructType)")
|
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 let token: Token = tokens.popLast() {
|
||||||
if type != token.type {
|
if type != token.type {
|
||||||
print("\(indent)VALIDATION FAILED FOR TOKEN \"\(token.content)\"")
|
print("\(indent)VALIDATION FAILED FOR TOKEN \"\(token.content)\"")
|
||||||
|
print("\(indent)AKA, \(type) not equal to \(token.type)")
|
||||||
return .Invalid
|
return .Invalid
|
||||||
}
|
}
|
||||||
print("\(indent)Validated token \"\(token.content)\"")
|
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 .MULTIPLICATION }
|
||||||
else if token.firstMatch(of: /^\/$/) != nil { return .DIVISION }
|
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_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 .EQUAL }
|
||||||
else if token.firstMatch(of: /^!=$/) != nil { return .NOT_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 }
|
||||||
|
|||||||
4
oldtest.c
Normal file
4
oldtest.c
Normal 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));
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user