aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cps/AST.h4
-rw-r--r--include/cps/Lexer.h1
-rw-r--r--lib/CodeGen/ValueTypeGen.cc3
-rw-r--r--lib/Lexer/Lexer.cc4
-rw-r--r--lib/Parser/ParserControlFlow.cc2
-rw-r--r--lib/Parser/ParserExpression.cc4
-rw-r--r--lib/Parser/ParserType.cc2
-rw-r--r--tests/i/c-string-literals/case.json1
-rw-r--r--tests/i/c-string-literals/expected.txt4
-rw-r--r--tests/i/c-string-literals/notes.md5
-rw-r--r--tests/i/c-string-literals/program.cps13
11 files changed, 37 insertions, 6 deletions
diff --git a/include/cps/AST.h b/include/cps/AST.h
index 2b78aaa..bb6d090 100644
--- a/include/cps/AST.h
+++ b/include/cps/AST.h
@@ -51,9 +51,11 @@ public:
class StringExprAST : public ExprAST {
std::string Val;
+ bool CString;
public:
- StringExprAST(const std::string &Val) : Val(Val) {}
+ StringExprAST(const std::string &Val, bool CString = false) : Val(Val), CString(CString) {}
const std::string &getVal() const { return Val; }
+ bool isCString() const { return CString; }
};
class VariableExprAST : public ExprAST {
diff --git a/include/cps/Lexer.h b/include/cps/Lexer.h
index 588a5fa..b514904 100644
--- a/include/cps/Lexer.h
+++ b/include/cps/Lexer.h
@@ -49,6 +49,7 @@ enum Token {
tok_string_kw = -30,
tok_string_literal = -36,
+ tok_c_string_literal = -37,
tok_char_kw = -38,
tok_char_literal = -39,
diff --git a/lib/CodeGen/ValueTypeGen.cc b/lib/CodeGen/ValueTypeGen.cc
index e7a3f77..f2dafb1 100644
--- a/lib/CodeGen/ValueTypeGen.cc
+++ b/lib/CodeGen/ValueTypeGen.cc
@@ -15,7 +15,8 @@ const TypeInfo *CodeGen::getExprTypeInfo(ExprAST *Expr) {
if (dynamic_cast<RealExprAST*>(Expr)) return resolveType("REAL");
if (dynamic_cast<BooleanExprAST*>(Expr)) return resolveType("BOOLEAN");
if (dynamic_cast<CharExprAST*>(Expr)) return resolveType("CHAR");
- if (dynamic_cast<StringExprAST*>(Expr)) return resolveType("STRING");
+ if (auto *String = dynamic_cast<StringExprAST*>(Expr))
+ return resolveType(String->isCString() ? "C_STRING" : "STRING");
if (auto *Cast = dynamic_cast<CastExprAST*>(Expr))
return resolveType(Cast->getTypeName());
diff --git a/lib/Lexer/Lexer.cc b/lib/Lexer/Lexer.cc
index 577a741..6d0246a 100644
--- a/lib/Lexer/Lexer.cc
+++ b/lib/Lexer/Lexer.cc
@@ -137,6 +137,10 @@ int Lexer::readToken() {
}
CharVal = StringVal.size() == 1 ? StringVal[0] : '?';
}
+ if (!IsChar && LastChar == 'C') {
+ LastChar = Input.get();
+ return tok_c_string_literal;
+ }
return IsChar ? tok_char_literal : tok_string_literal;
}
diff --git a/lib/Parser/ParserControlFlow.cc b/lib/Parser/ParserControlFlow.cc
index 10dd512..8ca024d 100644
--- a/lib/Parser/ParserControlFlow.cc
+++ b/lib/Parser/ParserControlFlow.cc
@@ -157,7 +157,7 @@ bool Parser::isCaseLabel() {
case '(': case '[': ++Depth; break;
case ')': case ']': if (--Depth < 0) return false; break;
case tok_identifier: case tok_number_int: case tok_number_real:
- case tok_string_literal: case tok_char_literal: case tok_true: case tok_false:
+ case tok_string_literal: case tok_c_string_literal: case tok_char_literal: case tok_true: case tok_false:
case tok_integer_kw: case tok_real_kw: case tok_boolean_kw:
case tok_string_kw: case tok_char_kw: case tok_c_int: case tok_c_char:
case tok_c_string: case tok_c_double:
diff --git a/lib/Parser/ParserExpression.cc b/lib/Parser/ParserExpression.cc
index 7558c86..be22b4e 100644
--- a/lib/Parser/ParserExpression.cc
+++ b/lib/Parser/ParserExpression.cc
@@ -216,8 +216,8 @@ std::unique_ptr<ExprAST> Parser::ParsePrimaryImpl() {
case tok_identifier: case tok_operator: return ParseIdentifierExpr();
case tok_number_int: return ParseNumberExpr();
case tok_number_real: return ParseNumberExpr();
- case tok_string_literal: {
- auto Res = std::make_unique<StringExprAST>(Lex.StringVal);
+ case tok_string_literal: case tok_c_string_literal: {
+ auto Res = std::make_unique<StringExprAST>(Lex.StringVal, CurTok == tok_c_string_literal);
getNextToken();
return Res;
}
diff --git a/lib/Parser/ParserType.cc b/lib/Parser/ParserType.cc
index d281293..e3adc5b 100644
--- a/lib/Parser/ParserType.cc
+++ b/lib/Parser/ParserType.cc
@@ -346,7 +346,7 @@ std::unique_ptr<StmtAST> Parser::ParseConstant() {
if (Negative) getNextToken();
bool Numeric = CurTok == tok_number_int || CurTok == tok_number_real;
bool Literal = Numeric || CurTok == tok_true || CurTok == tok_false ||
- CurTok == tok_string_literal || CurTok == tok_char_literal;
+ CurTok == tok_string_literal || CurTok == tok_c_string_literal || CurTok == tok_char_literal;
if (!Literal || (Negative && !Numeric)) {
cps::sourceDiagnostic(Lex.getLine(), "error: CONSTANT initializer must be a literal at line %d\n", Line);
return nullptr;
diff --git a/tests/i/c-string-literals/case.json b/tests/i/c-string-literals/case.json
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/tests/i/c-string-literals/case.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/i/c-string-literals/expected.txt b/tests/i/c-string-literals/expected.txt
new file mode 100644
index 0000000..2255027
--- /dev/null
+++ b/tests/i/c-string-literals/expected.txt
@@ -0,0 +1,4 @@
+quote:" slash:\
+AB
+0
+1:2
diff --git a/tests/i/c-string-literals/notes.md b/tests/i/c-string-literals/notes.md
new file mode 100644
index 0000000..a469ce1
--- /dev/null
+++ b/tests/i/c-string-literals/notes.md
@@ -0,0 +1,5 @@
+# C string literals
+
+Human review: pending. Expectations follow the literal bytes and declared overloads.
+
+The adjacent uppercase C suffix produces C_STRING. Escapes use the ordinary lexer rules. Explicit STRING casts preserve the text; an empty C string has length zero after conversion. Overload selection distinguishes STRING from C_STRING.
diff --git a/tests/i/c-string-literals/program.cps b/tests/i/c-string-literals/program.cps
new file mode 100644
index 0000000..ac2f7b0
--- /dev/null
+++ b/tests/i/c-string-literals/program.cps
@@ -0,0 +1,13 @@
+DECLARE Text : C_STRING
+Text <- "quote:\" slash:\\"C
+OUTPUT (STRING)Text
+OUTPUT (STRING)"\101\x42"C
+CONSTANT Empty = ""C
+OUTPUT LENGTH((STRING)Empty)
+OVERLOAD FUNCTION Kind(Text : STRING) RETURNS INTEGER
+ RETURN 1
+ENDFUNCTION
+OVERLOAD FUNCTION Kind(Text : C_STRING) RETURNS INTEGER
+ RETURN 2
+ENDFUNCTION
+OUTPUT Kind("text"), ":", Kind("text"C)