Bitwise shift and modulo

This commit is contained in:
2026-02-11 15:39:42 -05:00
parent c158751554
commit e0fb2c37fa
2 changed files with 102 additions and 5 deletions

View File

@@ -136,6 +136,13 @@ struct rxcc {
case GREATER_THAN case GREATER_THAN
case GREATER_THAN_OR_EQUAL_TO case GREATER_THAN_OR_EQUAL_TO
case MODULO
case BITWISE_AND
case BITWISE_OR
case BITWISE_XOR
case BITWISE_SHIFT_LEFT
case BITWISE_SHIFT_RIGHT
case ASSIGNMENT case ASSIGNMENT
case UNDEFINED case UNDEFINED
@@ -164,8 +171,13 @@ struct rxcc {
case Addition case Addition
case Subtraction case Subtraction
case Multiplication case Multiplication
case Division case Division
case Modulo
case BitwiseShiftLeft
case BitwiseShiftRight
case LessThan case LessThan
case LessThanOrEqualTo case LessThanOrEqualTo
@@ -186,6 +198,7 @@ struct rxcc {
// Expression variants // Expression variants
case TermSequence case TermSequence
case AdditiveExpressionSequence case AdditiveExpressionSequence
case BitwiseShiftExpressionSequence
case RelationalExpressionSequence case RelationalExpressionSequence
case EqualityExpressionSequence case EqualityExpressionSequence
case LogicalAndExpressionSequence case LogicalAndExpressionSequence
@@ -227,6 +240,7 @@ struct rxcc {
case MultiplicationPriorityOperator case MultiplicationPriorityOperator
case AdditionPriorityOperator case AdditionPriorityOperator
case BitwiseShiftPriorityOperator
case InequalityPriorityOperator case InequalityPriorityOperator
case EqualityPriorityOperator case EqualityPriorityOperator
case LogicalAndPriorityOperator case LogicalAndPriorityOperator
@@ -239,6 +253,7 @@ struct rxcc {
case Expression case Expression
case LogicalOrExpression case LogicalOrExpression
case LogicalAndExpression case LogicalAndExpression
case BitwiseShiftExpression
case EqualityExpression case EqualityExpression
case RelationalExpression case RelationalExpression
case AdditiveExpression case AdditiveExpression
@@ -300,6 +315,18 @@ struct rxcc {
.Division: [ .Division: [
.Token(type: .DIVISION), .Token(type: .DIVISION),
], ],
.Modulo: [
.Token(type: .MODULO),
],
],
.BitwiseShiftPriorityOperator: [
.BitwiseShiftLeft: [
.Token(type: .BITWISE_SHIFT_LEFT),
],
.BitwiseShiftRight: [
.Token(type: .BITWISE_SHIFT_RIGHT),
],
], ],
.InequalityPriorityOperator: [ .InequalityPriorityOperator: [
@@ -370,9 +397,16 @@ struct rxcc {
], ],
.RelationalExpression: [ .RelationalExpression: [
.BitwiseShiftExpressionSequence: [
.Construct(type: .BitwiseShiftExpression),
.OperatorLoop(type: .InequalityPriorityOperator),
]
],
.BitwiseShiftExpression: [
.AdditiveExpressionSequence: [ .AdditiveExpressionSequence: [
.Construct(type: .AdditiveExpression), .Construct(type: .AdditiveExpression),
.OperatorLoop(type: .InequalityPriorityOperator), .OperatorLoop(type: .BitwiseShiftPriorityOperator),
] ]
], ],
@@ -520,6 +554,9 @@ struct rxcc {
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: " == ")
@@ -527,6 +564,8 @@ struct rxcc {
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(" +"))
@@ -610,7 +649,6 @@ struct rxcc {
print("ERROR: \(node.variant) with more or less than 1 child") print("ERROR: \(node.variant) with more or less than 1 child")
break break
} }
let variable: String = node.children[0].value
text += generateOutput(node.children[0]) text += generateOutput(node.children[0])
text += " push\t%eax\n" text += " push\t%eax\n"
@@ -789,7 +827,7 @@ struct rxcc {
} }
break break
case .AdditiveExpressionSequence: case .BitwiseShiftExpressionSequence:
var operation: ConstructVariant = .Error var operation: ConstructVariant = .Error
let count = node.children.count let count = node.children.count
if count == 0 { if count == 0 {
@@ -845,6 +883,48 @@ struct rxcc {
} }
break break
case .AdditiveExpressionSequence:
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 .BitwiseShiftLeft:
text += " movl\t%eax, %ecx\n" // Move e2 to ecx
text += " pop \t%eax\n" // Move e1 to eax
text += " sal \t%cl, %eax\n" // Perform e1 << e2; result in e1
case .BitwiseShiftRight:
text += " movl\t%eax, %ecx\n" // Move e2 to ecx
text += " pop \t%eax\n" // Move e1 to eax
text += " sar \t%cl, %eax\n" // Perform e1 >> e2; result in e1
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 .TermSequence: case .TermSequence:
var operation: ConstructVariant = .Error var operation: ConstructVariant = .Error
let count = node.children.count let count = node.children.count
@@ -908,6 +988,7 @@ struct rxcc {
case .Multiplication: case .Multiplication:
text += " pop \t%ecx\n" text += " pop \t%ecx\n"
text += " imul\t%ecx, %eax\n" text += " imul\t%ecx, %eax\n"
break
case .Division: case .Division:
text += " movl\t%eax, %ecx\n" // Move e2 to ecx text += " movl\t%eax, %ecx\n" // Move e2 to ecx
@@ -915,6 +996,16 @@ struct rxcc {
text += " cdq\n" // Extend eax into edx text += " cdq\n" // Extend eax into edx
text += " idivl\t%ecx\n" // Perform edx:eax / ecx text += " idivl\t%ecx\n" // Perform edx:eax / ecx
// eax = quotient; edx rem. // eax = quotient; edx rem.
break
case .Modulo:
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.
text += " movl\t%edx, %eax\n" // Move remainder to eax
break
default: default:
if i != 0 { if i != 0 {
@@ -1212,7 +1303,7 @@ struct rxcc {
} }
else if type != token.type { else if type != token.type {
print("\(indent)Failed to validate token \"\(token.content)\". Expected \"\(type)\"") print("\(indent)Failed to validate token \"\(token.content)\". Expected \"\(type)\"")
//print("\(indent)AKA, \(type) not equal to \(token.type)") 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)\"")
@@ -1262,6 +1353,12 @@ struct rxcc {
else if token.firstMatch(of: /^>$/) != nil { return .GREATER_THAN } else if token.firstMatch(of: /^>$/) != nil { return .GREATER_THAN }
else if token.firstMatch(of: /^>=$/) != nil { return .GREATER_THAN_OR_EQUAL_TO } else if token.firstMatch(of: /^>=$/) != nil { return .GREATER_THAN_OR_EQUAL_TO }
else if token.firstMatch(of: /^=$/) != nil { return .ASSIGNMENT } else if token.firstMatch(of: /^=$/) != nil { return .ASSIGNMENT }
else if token.firstMatch(of: /^%$/) != nil { return .MODULO }
else if token.firstMatch(of: /^&$/) != nil { return .BITWISE_AND }
else if token.firstMatch(of: /^\|$/) != nil { return .BITWISE_OR }
else if token.firstMatch(of: /^\^$/) != nil { return .BITWISE_XOR }
else if token.firstMatch(of: /^<<$/) != nil { return .BITWISE_SHIFT_LEFT }
else if token.firstMatch(of: /^>>$/) != nil { return .BITWISE_SHIFT_RIGHT }
return .UNDEFINED return .UNDEFINED
} }

2
test.c
View File

@@ -1,4 +1,4 @@
int main() { int main() {
return 3 % 2 / 29 % 23 + 9 % 2 % 3 % 4 % 5;
} }