SOMEHOW IT WORKS
This commit is contained in:
153
Sources/rxcc/rxcc.swift
Normal file
153
Sources/rxcc/rxcc.swift
Normal file
@@ -0,0 +1,153 @@
|
||||
enum Constant {
|
||||
case Integer(value: Int)
|
||||
}
|
||||
|
||||
struct Return {
|
||||
let value: Constant
|
||||
}
|
||||
|
||||
struct Function {
|
||||
let name: String
|
||||
let statement: Return
|
||||
}
|
||||
|
||||
struct Program {
|
||||
let contents: Function
|
||||
}
|
||||
|
||||
enum TokenType {
|
||||
case BRACE_OPEN
|
||||
case BRACE_CLOSE
|
||||
case PARENTHESIS_OPEN
|
||||
case PARENTHESIS_CLOSE
|
||||
case SEMICOLON
|
||||
case INT
|
||||
case RETURN
|
||||
case IDENTIFIER
|
||||
case LITERAL_INTEGER
|
||||
|
||||
case UNDEFINED
|
||||
}
|
||||
|
||||
struct Token {
|
||||
let content: Substring
|
||||
let type: TokenType
|
||||
}
|
||||
|
||||
typealias Construct = [Element]
|
||||
|
||||
enum Element {
|
||||
case Construct(type: Construct)
|
||||
case Token(type: TokenType)
|
||||
}
|
||||
|
||||
|
||||
|
||||
let expression: Construct = [
|
||||
.Token(type: .LITERAL_INTEGER)
|
||||
]
|
||||
let statement: Construct = [
|
||||
.Token(type: .RETURN),
|
||||
.Construct(type: expression),
|
||||
.Token(type: .SEMICOLON)
|
||||
]
|
||||
let function: Construct = [
|
||||
.Token(type: .INT),
|
||||
.Token(type: .IDENTIFIER),
|
||||
.Token(type: .PARENTHESIS_OPEN),
|
||||
.Token(type: .PARENTHESIS_CLOSE),
|
||||
.Token(type: .BRACE_OPEN),
|
||||
.Construct(type: statement),
|
||||
.Token(type: .BRACE_CLOSE)
|
||||
]
|
||||
let program: Construct = [
|
||||
.Construct(type: function)
|
||||
]
|
||||
|
||||
|
||||
|
||||
@main
|
||||
struct rxcc {
|
||||
static func main() {
|
||||
let lexed: [Substring] = lex(string: """
|
||||
int main() {
|
||||
return 100;
|
||||
}
|
||||
""")
|
||||
parse(lexed: lexed)
|
||||
}
|
||||
}
|
||||
|
||||
func lex(string: String) -> [Substring] {
|
||||
var line = string.replacing("\n", with: " ")
|
||||
line = line.replacing("\t", 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(" +"))
|
||||
return tokens
|
||||
} catch {
|
||||
print("Regex did something wrong")
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
func parse(lexed: [Substring]) {
|
||||
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()
|
||||
|
||||
if validateConstruct(program, tokens: &tokens) {
|
||||
print("Success")
|
||||
return
|
||||
}
|
||||
|
||||
print("Distinct lack of success")
|
||||
}
|
||||
|
||||
func validateConstruct(_ construct: Construct, tokens: inout [Token]) -> Bool {
|
||||
for element in construct {
|
||||
switch element {
|
||||
case .Construct(let type):
|
||||
print("Begin validate subconstruct")
|
||||
if !validateConstruct(type, tokens: &tokens) {
|
||||
print("Subconstruct validation failed")
|
||||
return false
|
||||
}
|
||||
print("End validate subconstruct")
|
||||
break
|
||||
|
||||
case .Token(let type):
|
||||
if let token: Token = tokens.popLast() {
|
||||
if type != token.type {
|
||||
print("VALIDATION FAILED FOR TOKEN \"\(token.content)\"")
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func categorizeToken(token: Substring) -> TokenType {
|
||||
if token.firstMatch(of: /{/) != nil { return .BRACE_OPEN }
|
||||
else if token.firstMatch(of: /}/) != nil { return .BRACE_CLOSE }
|
||||
else if token.firstMatch(of: /\(/) != nil { return .PARENTHESIS_OPEN }
|
||||
else if token.firstMatch(of: /\)/) != nil { return .PARENTHESIS_CLOSE }
|
||||
else if token.firstMatch(of: /;/) != nil { return .SEMICOLON }
|
||||
else if token.firstMatch(of: /int/) != nil { return .INT }
|
||||
else if token.firstMatch(of: /return/) != nil { return .RETURN }
|
||||
else if token.firstMatch(of: /[a-zA-Z]\w*/) != nil { return .IDENTIFIER }
|
||||
else if token.firstMatch(of: /[0-9]+/) != nil { return .LITERAL_INTEGER }
|
||||
|
||||
return .UNDEFINED
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user