diff --git a/Sources/rxcc/rxcc.swift b/Sources/rxcc/rxcc.swift index 6a9a458..a941430 100644 --- a/Sources/rxcc/rxcc.swift +++ b/Sources/rxcc/rxcc.swift @@ -348,29 +348,6 @@ func lex(string: String) -> [Substring] { return [] } -func parse(lexed: [Substring]) -> String { - var tokens: [Token] = [Token]() - for token: Substring in lexed { - let tokenType: TokenType = categorizeToken(token: token) - tokens.append(Token(content: token, type: tokenType)) - } - tokens = tokens.reversed() - - let abstractSyntaxTree = SyntaxTreeNode(.Root) - - if validateConstruct(program.variants[.SingleFunction]!, tokens: &tokens, node: abstractSyntaxTree) != .Invalid { - print("Success") - print(abstractSyntaxTree.text()) - print("Assembly:") - let assembly: String = generateOutput(abstractSyntaxTree) - print(assembly) - return assembly - } - - print("Distinct lack of success") - return "" -} - func generateOutput(_ node: SyntaxTreeNode) -> String { var text: String = "" switch node.variant { @@ -387,13 +364,51 @@ func generateOutput(_ node: SyntaxTreeNode) -> String { break case .FactorSequence: - for child in node.children { + 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 .Multiplication: + text += " pop %ecx\n" + text += " imul %ecx, %eax\n" + + default: + if i != 0 { + print("Unknown operation \"\(operation)\" in FactorSequence") + } + break + } + + if i != node.children.count - 1 { + text += " push %eax\n" + } } break +/* + + push %eax ; save value of e1 on the stack + + pop %ecx ; pop e1 from the stack into ecx + addl %ecx, %eax ; add e1 to e2, save results in eax +*/ + case .Integer: - text += " .globl \(node.value)\n\(node.value):\n" + text += " .globl \(node.value)\n\(node.value):\n" for child in node.children { text += generateOutput(child) } @@ -444,13 +459,36 @@ func generateOutput(_ node: SyntaxTreeNode) -> String { return text } +func parse(lexed: [Substring]) -> String { + var tokens: [Token] = [Token]() + for token: Substring in lexed { + let tokenType: TokenType = categorizeToken(token: token) + tokens.append(Token(content: token, type: tokenType)) + } + tokens = tokens.reversed() + + let abstractSyntaxTree = SyntaxTreeNode(.Root) + + if validateConstruct(program.variants[.SingleFunction]!, tokens: &tokens, node: abstractSyntaxTree, loopingEnabled: false) != .Invalid { + print("Success") + print(abstractSyntaxTree.text()) + print("Assembly:") + let assembly: String = generateOutput(abstractSyntaxTree) + print(assembly) + return assembly + } + + print("Distinct lack of success") + return "" +} + enum Validity { case Valid case Invalid case Break } -func validateConstruct(_ construct: Construct, tokens: inout [Token], node: SyntaxTreeNode) -> Validity { +func validateConstruct(_ construct: Construct, tokens: inout [Token], node: SyntaxTreeNode, loopingEnabled: Bool) -> Validity { var indent: String { var count: Int = 0 var child: SyntaxTreeNode = node @@ -461,7 +499,7 @@ func validateConstruct(_ construct: Construct, tokens: inout [Token], node: Synt return String(repeating: " ", count: count) } - var loop: Bool = false + var loop: Bool = loopingEnabled repeat { for element in construct { switch element { @@ -471,18 +509,23 @@ func validateConstruct(_ construct: Construct, tokens: inout [Token], node: Synt var valid: Validity = .Invalid var validVariant: ConstructVariant = .Error let tokenBackup: [Token] = tokens - for key in constructDefinitions[type]!.keys { - let childNode = node.addChild(value: key) - print("\(indent)Testing variant \(key) (Loop = \(loop))") - valid = validateConstruct(constructDefinitions[type]![key]!, tokens: &tokens, node: childNode) + for variant in constructDefinitions[type]!.keys { + let childNode = node.addChild(value: variant) + var loopable = false + if variant == .FactorSequence || variant == .TermSequence { + loopable = true + } + + print("\(indent)Testing variant \(variant) (Loop = \(loop)) (Loopable = \(loopable))") + valid = validateConstruct(constructDefinitions[type]![variant]!, tokens: &tokens, node: childNode, loopingEnabled: loopable) if valid == .Invalid { - print("\(indent)Fail") + print("\(indent)Fail (no valid variants)\n") tokens = tokenBackup _ = node.popLastChild() continue } - print("\(indent)Success") - validVariant = key + print("\(indent)Success (variant \"\(variant)\")\n") + validVariant = variant break } @@ -490,29 +533,31 @@ func validateConstruct(_ construct: Construct, tokens: inout [Token], node: Synt - // 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 { - print("\(indent)Breaking out of factor loop") - loop = false - return .Break + 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 { + print("\(indent)Breaking out of factor loop") + loop = false + return .Break + } } - } - // 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 + // 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 + } } } diff --git a/a.out b/a.out index ffc6a38..6397d0d 100755 Binary files a/a.out and b/a.out differ diff --git a/hard.c b/hard.c new file mode 100644 index 0000000..90f9805 --- /dev/null +++ b/hard.c @@ -0,0 +1,3 @@ +int main() { + return !(2 * 3) + !2 * 3 + (4 + 5) * ~6 * 7 * (8 + -(!~9 * 10)) - -11 * ~12 + !~-13; +} diff --git a/hard.s b/hard.s new file mode 100644 index 0000000..7bdf703 --- /dev/null +++ b/hard.s @@ -0,0 +1,24 @@ + .globl main +main: + cmpl $0, %eax + movl $0, %eax + sete %al + movl $2, %eax + cmpl $0, %eax + movl $0, %eax + sete %al + movl $3, %eax + movl $6, %eax + not %eax + movl $7, %eax + movl $11, %eax + neg %eax + movl $12, %eax + not %eax + movl $13, %eax + neg %eax + not %eax + cmpl $0, %eax + movl $0, %eax + sete %al + ret diff --git a/test b/test index 3802835..5a14f46 100755 --- a/test +++ b/test @@ -1,6 +1,6 @@ #!/bin/bash -gcc c/tests/stage_2/valid/$1.c -gcc bin/$1.s -o my.out +gcc $1.c +gcc $1.s -o my.out echo "GCC:" ./a.out echo $? diff --git a/test.c b/test.c index 554c254..3f0924b 100644 --- a/test.c +++ b/test.c @@ -1,3 +1,3 @@ int main() { - return !1 * 1; + return 1 * 2; } diff --git a/test.s b/test.s index e69de29..6f18599 100644 --- a/test.s +++ b/test.s @@ -0,0 +1,8 @@ + .globl main +main: + movl $1, %eax + push %eax + movl $2, %eax + pop %ecx + imul %ecx, %eax + ret diff --git a/test2.c b/test2.c index 08e20b8..8ec47b5 100644 --- a/test2.c +++ b/test2.c @@ -1,3 +1,3 @@ int main() { - return (~2 + !(4 - 2) / 9 - -9) + 90 * 8 - 2 - 33 * (400 - 1) - !~-9; + return ~1 * 2; } diff --git a/test2.s b/test2.s index e69de29..3afb065 100644 --- a/test2.s +++ b/test2.s @@ -0,0 +1,6 @@ + .globl main +main: + movl $1, %eax + not %eax + movl $2, %eax + ret diff --git a/test2s b/test2s new file mode 100644 index 0000000..e69de29