diff --git a/generator.v b/generator.v index 6621b05..42dfe56 100644 --- a/generator.v +++ b/generator.v @@ -27,6 +27,7 @@ fn get_type_format(type string) string { return match type { 'int', 'bool' {'d'} 'real' {'f'} + 'string' {'s'} else {panic("invalid type to print")} } } @@ -45,6 +46,7 @@ fn (mut g Generator) get_c_type(typ string) string { return match typ { 'real' {'float'} 'int' {'int32_t'} + 'string' {'char*'} else {typ} } } @@ -150,6 +152,9 @@ fn (mut g Generator) gen_expr(expr Expr) { BoolLiteral { g.out.write_string(expr.val.str()) } + StringLiteral { + g.out.write_string('\"${expr.val}\"') + } Variable { g.out.write_string(mangle_var(expr.name)) } @@ -231,6 +236,7 @@ fn (mut g Generator) gen_c(program []Stmt) string { g.out.writeln('#include ') g.out.writeln('#include ') g.out.writeln('#include ') + //g.out.writeln('typedef struct __one_string_builtin__ {\nchar* string;\nint len;\n} string;') for stmt in program { g.gen_stmt(stmt) } diff --git a/lexer.v b/lexer.v index 02f5f6c..347d7ac 100644 --- a/lexer.v +++ b/lexer.v @@ -17,6 +17,7 @@ enum TokenType as u8 { integer real boolean + string identifier plus minus @@ -95,7 +96,7 @@ fn toktype_from_kw(kw string) TokenType { return match kw { 'let' {.kw_let} 'const' {.kw_const} - 'void', 'real', 'bool', 'int' {.type} + 'void', 'real', 'bool', 'int', 'string'{.type} 'if' {.kw_if} 'else' {.kw_else} 'for' {.kw_for} @@ -111,8 +112,8 @@ fn toktype_from_kw(kw string) TokenType { fn is_delimiter(c u8, is_inside_number bool) bool { valid_chars := match is_inside_number { - true {" +-*/,;:%<>()[]{}=\n"} - false {". +-*/,;:%<>()[]{}=\n"} + true {" +-*/,;:%<>()[]{}=\n\""} + false {". +-*/,;:%<>()[]{}=\n\""} } return valid_chars.contains(c.ascii_str()) } @@ -124,7 +125,7 @@ fn is_real(str string) bool { fn is_keyword(str string) bool { return [ - "void", "int", "real", "bool", "if", "else", "for", "break", "fn", "return", "let", "const", "true", "false", "print", "class" + "void", "int", "real", "bool", "string", "if", "else", "for", "break", "fn", "return", "let", "const", "true", "false", "print", "class" ].contains(str) } @@ -144,8 +145,18 @@ fn lex(input string) ?[]Token { mut line := 1 mut tokens := []Token{} mut is_inside_number := false + mut is_inside_string := false for (right < input.len && left <= right) { + for is_inside_string { + right++ + if input[right].ascii_str() == '\"' { + is_inside_string = false + right++ + tokens << Token{.string, input.substr(left+1, right-1)} + left = right + } + } is_inside_number = input[left].ascii_str().is_int() if input[right] == `\n` { line++ @@ -158,14 +169,15 @@ fn lex(input string) ?[]Token { } if is_delimiter(input[right], is_inside_number) && left == right { if !input[right].is_space() { + if input[right].ascii_str() == '\"' {is_inside_string = true; continue} mut tok_str := input[right].ascii_str() - if right + 1 < input.len { - combined := input.substr(right, right + 2) - if combined in ['==', '>=', '<=', '!=', '+=', '-=', '*=', '/=', '++', '--'] { - tok_str = combined - right++ - } + if right + 1 < input.len { + combined := input.substr(right, right + 2) + if combined in ['==', '>=', '<=', '!=', '+=', '-=', '*=', '/=', '++', '--'] { + tok_str = combined + right++ } + } tokens << Token{toktype_from_delimiter(tok_str), tok_str} } right++ diff --git a/parser.v b/parser.v index 84d8f4e..36d8db7 100644 --- a/parser.v +++ b/parser.v @@ -115,7 +115,7 @@ fn (mut s SymbolTable) is_in_global_scope() bool { // ------------------------------------------- Expressions -type Expr = VoidExpr | UnaryExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | Variable | TypeExpr | Function | TypeCast | ParenExpr | PrintExpr | FnCall | ClassMember | ClassInstantiation | MemberAccess +type Expr = VoidExpr | UnaryExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | StringLiteral | Variable | TypeExpr | Function | TypeCast | ParenExpr | PrintExpr | FnCall | ClassMember | ClassInstantiation | MemberAccess struct VoidExpr {} @@ -142,6 +142,10 @@ struct BoolLiteral { val bool } +struct StringLiteral { + val string +} + struct Variable { name string } @@ -295,6 +299,7 @@ fn (mut p Parser) parse_primary() Expr { .integer {IntegerLiteral{token.text.int()}} .real {RealLiteral{token.text.f32()}} .boolean {BoolLiteral{token.text == 'true'}} + .string {StringLiteral{token.text}} .kw_fn {Function{token.text}} .identifier {p.parse_ident(token.text)} .type {p.parse_type(token.text)} @@ -461,6 +466,7 @@ fn (mut p Parser) get_expr_type(expr Expr) string { IntegerLiteral {'int'} RealLiteral {'real'} BoolLiteral {'bool'} + StringLiteral {'string'} VoidExpr {'void'} TypeExpr {expr.name} BinaryExpr {