Stage 3 complete, (+ - * / binary operators implemented)

This commit is contained in:
2026-01-31 21:32:53 -05:00
parent 1d9ad824a6
commit 409c5938f9
11 changed files with 190 additions and 31 deletions

View File

@@ -357,12 +357,53 @@ func generateOutput(_ node: SyntaxTreeNode) -> String {
} }
break break
case .TermSequence: case .ParenthesizedExpression:
for child in node.children { for child in node.children {
text += generateOutput(child) text += generateOutput(child)
} }
break break
case .TermSequence:
var operation: ConstructVariant = .Error
let count = node.children.count
if count == 0 {
print("ERROR: FactorSequence 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 .Addition:
text += " pop \t%ecx\n"
text += " addl\t%ecx, %eax\n"
case .Subtraction:
text += " pop \t%ecx\n"
text += " subl\t%eax, %ecx\n"
text += " movl\t%ecx, %eax\n"
default:
if i != 0 {
print("Unknown operation \"\(operation)\" in FactorSequence")
}
break
}
if i != node.children.count - 1 {
text += " push\t%eax\n"
}
}
break
case .FactorSequence: case .FactorSequence:
var operation: ConstructVariant = .Error var operation: ConstructVariant = .Error
let count = node.children.count let count = node.children.count
@@ -383,8 +424,15 @@ func generateOutput(_ node: SyntaxTreeNode) -> String {
switch operation { switch operation {
case .Multiplication: case .Multiplication:
text += " pop %ecx\n" text += " pop \t%ecx\n"
text += " imul %ecx, %eax\n" text += " imul\t%ecx, %eax\n"
case .Division:
text += " movl\t%eax, %ecx\n" // Move e2 to ecx
text += " pop \t%eax\n" // Fetch e1 off stack into eax
text += " cdq\n" // Extend eax into edx
text += " idivl\t%ecx\n" // Perform edx:eax / ecx
// eax = quotient; edx rem.
default: default:
if i != 0 { if i != 0 {
@@ -394,7 +442,7 @@ func generateOutput(_ node: SyntaxTreeNode) -> String {
} }
if i != node.children.count - 1 { if i != node.children.count - 1 {
text += " push %eax\n" text += " push\t%eax\n"
} }
} }
break break
@@ -437,19 +485,21 @@ func generateOutput(_ node: SyntaxTreeNode) -> String {
break break
case .BitwiseCompliment: case .BitwiseCompliment:
text += " not %eax\n" text += " not \t%eax\n"
break break
case .Negation: case .Negation:
text += " neg %eax\n" text += " neg \t%eax\n"
break break
case .LogicalNegation: case .LogicalNegation:
text += " cmpl $0, %eax\n movl $0, %eax\n sete %al\n" text += " cmpl\t$0, %eax\n"
text += " movl\t$0, %eax\n"
text += " sete\t%al\n"
break break
case .LiteralInteger: case .LiteralInteger:
text += " movl $\(node.value), %eax\n" text += " movl\t$\(node.value), %eax\n"
break break
default: default:
@@ -485,6 +535,7 @@ func parse(lexed: [Substring]) -> String {
enum Validity { enum Validity {
case Valid case Valid
case Invalid case Invalid
case Panic
case Break case Break
} }
@@ -518,8 +569,11 @@ func validateConstruct(_ construct: Construct, tokens: inout [Token], node: Synt
print("\(indent)Testing variant \(variant) (Loop = \(loop)) (Loopable = \(loopable))") print("\(indent)Testing variant \(variant) (Loop = \(loop)) (Loopable = \(loopable))")
valid = validateConstruct(constructDefinitions[type]![variant]!, tokens: &tokens, node: childNode, loopingEnabled: loopable) valid = validateConstruct(constructDefinitions[type]![variant]!, tokens: &tokens, node: childNode, loopingEnabled: loopable)
if valid == .Invalid { if valid == .Panic {
print("\(indent)Fail (no valid variants)\n") print("\(indent)Fail: panic (variant \"\(variant)\"))\n")
return .Invalid
} else if valid == .Invalid {
print("\(indent)Fail: no valid variants (variant \"\(variant)\")\n")
tokens = tokenBackup tokens = tokenBackup
_ = node.popLastChild() _ = node.popLastChild()
continue continue
@@ -541,9 +595,14 @@ func validateConstruct(_ construct: Construct, tokens: inout [Token], node: Synt
print("\(indent)Looping due to factor") print("\(indent)Looping due to factor")
loop = true loop = true
} else { } else {
if node.children.count != 0 {
print("\(indent)Breaking out of factor loop") print("\(indent)Breaking out of factor loop")
loop = false loop = false
return .Break return .Break
} else {
print("\(indent)ERROR: FactorSequence has no children")
return .Panic
}
} }
} }
@@ -569,7 +628,6 @@ func validateConstruct(_ construct: Construct, tokens: inout [Token], node: Synt
return .Invalid return .Invalid
} else if valid == .Break { } else if valid == .Break {
print("\(indent)End validate subconstruct (variant \"\(validVariant) by breaking\")") print("\(indent)End validate subconstruct (variant \"\(validVariant) by breaking\")")
print(type)
break break
} }

BIN
a.out

Binary file not shown.

BIN
gcc.out Executable file

Binary file not shown.

BIN
my.out Executable file

Binary file not shown.

BIN
rxcc.out Executable file

Binary file not shown.

10
test
View File

@@ -1,9 +1,11 @@
#!/bin/bash #!/bin/bash
gcc $1.c nvim test.c
gcc $1.s -o my.out gcc -m32 test.c -o gcc.out
./.build/debug/rxcc test.c
gcc -m32 test.s -o rxcc.out
echo "GCC:" echo "GCC:"
./a.out ./gcc.out
echo $? echo $?
echo "RXCC" echo "RXCC"
./my.out ./rxcc.out
echo $? echo $?

3
test.c
View File

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

105
test.s
View File

@@ -1,8 +1,111 @@
.globl main .globl main
main: main:
movl $1, %eax movl $4, %eax
push %eax
movl $4, %eax
neg %eax
pop %ecx
addl %ecx, %eax
cmpl $0, %eax
movl $0, %eax
sete %al
push %eax
movl $6, %eax
push %eax
movl $2, %eax
push %eax push %eax
movl $2, %eax movl $2, %eax
pop %ecx pop %ecx
addl %ecx, %eax
movl %eax, %ecx
pop %eax
cdq
idivl %ecx
push %eax
movl $4, %eax
neg %eax
pop %ecx
imul %ecx, %eax imul %ecx, %eax
push %eax
movl $4, %eax
not %eax
pop %ecx
imul %ecx, %eax
push %eax
movl $9, %eax
movl %eax, %ecx
pop %eax
cdq
idivl %ecx
pop %ecx
addl %ecx, %eax
push %eax
movl $4, %eax
push %eax
movl $5, %eax
push %eax
movl $32, %eax
push %eax
movl $2, %eax
movl %eax, %ecx
pop %eax
cdq
idivl %ecx
pop %ecx
imul %ecx, %eax
push %eax
movl $1, %eax
not %eax
pop %ecx
addl %ecx, %eax
movl %eax, %ecx
pop %eax
cdq
idivl %ecx
push %eax
movl $400, %eax
push %eax
movl $90, %eax
movl %eax, %ecx
pop %eax
cdq
idivl %ecx
push %eax
movl $1, %eax
pop %ecx
addl %ecx, %eax
pop %ecx
subl %eax, %ecx
movl %ecx, %eax
push %eax
movl $5, %eax
push %eax
movl $4, %eax
movl %eax, %ecx
pop %eax
cdq
idivl %ecx
push %eax
movl $2, %eax
push %eax
movl $3, %eax
pop %ecx
addl %ecx, %eax
pop %ecx
imul %ecx, %eax
push %eax
movl $9, %eax
neg %eax
movl %eax, %ecx
pop %eax
cdq
idivl %ecx
not %eax
neg %eax
pop %ecx
subl %eax, %ecx
movl %ecx, %eax
neg %eax
pop %ecx
addl %ecx, %eax
ret ret

View File

@@ -1,3 +1,4 @@
int main() { int main() {
return ~1 * 2; return -(2 * 3) * 5 * (2 * 5) * (3 * -4 * -(-2 * 5) * 4) * -7 * 7;
} }

View File

@@ -1,6 +0,0 @@
.globl main
main:
movl $1, %eax
not %eax
movl $2, %eax
ret

0
test2s
View File