summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/parser/lexer.cpp81
-rw-r--r--src/parser/lexer.h16
2 files changed, 68 insertions, 29 deletions
diff --git a/src/parser/lexer.cpp b/src/parser/lexer.cpp
index 2625bf8fd..07931d69b 100644
--- a/src/parser/lexer.cpp
+++ b/src/parser/lexer.cpp
@@ -329,6 +329,25 @@ public:
}
};
+struct LexIdResult : LexResult {
+ bool isStr = false;
+ std::optional<std::string> str;
+};
+
+struct LexIdCtx : LexCtx {
+ bool isStr = false;
+ std::optional<std::string> str;
+
+ LexIdCtx(std::string_view in) : LexCtx(in) {}
+
+ std::optional<LexIdResult> lexed() {
+ if (auto basic = LexCtx::lexed()) {
+ return LexIdResult{*basic, isStr, str};
+ }
+ return {};
+ }
+};
+
std::optional<LexResult> lparen(std::string_view in) {
LexCtx ctx(in);
ctx.takePrefix("("sv);
@@ -647,26 +666,6 @@ std::optional<LexResult> idchar(std::string_view in) {
return ctx.lexed();
}
-// id ::= '$' idchar+
-std::optional<LexResult> ident(std::string_view in) {
- LexCtx ctx(in);
- if (!ctx.takePrefix("$"sv)) {
- return {};
- }
- if (auto lexed = idchar(ctx.next())) {
- ctx.take(*lexed);
- } else {
- return {};
- }
- while (auto lexed = idchar(ctx.next())) {
- ctx.take(*lexed);
- }
- if (ctx.canFinish()) {
- return ctx.lexed();
- }
- return {};
-}
-
// string ::= '"' (b*:stringelem)* '"' => concat((b*)*)
// (if |concat((b*)*)| < 2^32)
// stringelem ::= c:stringchar => utf8(c)
@@ -741,6 +740,30 @@ std::optional<LexStrResult> str(std::string_view in) {
return ctx.lexed();
}
+// id ::= '$' idchar+ | '$' str
+std::optional<LexIdResult> ident(std::string_view in) {
+ LexIdCtx ctx(in);
+ if (!ctx.takePrefix("$"sv)) {
+ return {};
+ }
+ if (auto s = str(ctx.next())) {
+ ctx.isStr = true;
+ ctx.str = s->str;
+ ctx.take(*s);
+ } else if (auto lexed = idchar(ctx.next())) {
+ ctx.take(*lexed);
+ while (auto lexed = idchar(ctx.next())) {
+ ctx.take(*lexed);
+ }
+ } else {
+ return {};
+ }
+ if (ctx.canFinish()) {
+ return ctx.lexed();
+ }
+ return {};
+}
+
// keyword ::= ( 'a' | ... | 'z' ) idchar* (if literal terminal in grammar)
// reserved ::= idchar+
//
@@ -889,11 +912,27 @@ std::optional<std::string_view> Token::getString() const {
if (tok->str) {
return std::string_view(*tok->str);
}
+ // Remove quotes.
return span.substr(1, span.size() - 2);
}
return {};
}
+std::optional<std::string_view> Token::getID() const {
+ if (auto* tok = std::get_if<IdTok>(&data)) {
+ if (tok->str) {
+ return std::string_view(*tok->str);
+ }
+ if (tok->isStr) {
+ // Remove '$' and quotes.
+ return span.substr(2, span.size() - 3);
+ }
+ // Remove '$'.
+ return span.substr(1);
+ }
+ return {};
+}
+
void Lexer::skipSpace() {
if (auto ctx = space(next())) {
index += ctx->span.size();
@@ -908,7 +947,7 @@ void Lexer::lexToken() {
} else if (auto t = rparen(next())) {
tok = Token{t->span, RParenTok{}};
} else if (auto t = ident(next())) {
- tok = Token{t->span, IdTok{}};
+ tok = Token{t->span, IdTok{t->isStr, t->str}};
} else if (auto t = integer(next())) {
tok = Token{t->span, IntTok{t->n, t->sign}};
} else if (auto t = float_(next())) {
diff --git a/src/parser/lexer.h b/src/parser/lexer.h
index 42b18508e..f0da151f9 100644
--- a/src/parser/lexer.h
+++ b/src/parser/lexer.h
@@ -53,6 +53,12 @@ struct RParenTok {
};
struct IdTok {
+ // Whether this ID has `$"..."` format
+ bool isStr;
+
+ // If the ID is a string ID and contains escapes, this is its contents.
+ std::optional<std::string> str;
+
bool operator==(const IdTok&) const { return true; }
friend std::ostream& operator<<(std::ostream&, const IdTok&);
};
@@ -81,6 +87,7 @@ struct FloatTok {
};
struct StringTok {
+ // If the string contains escapes, this is its contents.
std::optional<std::string> str;
bool operator==(const StringTok& other) const { return str == other.str; }
@@ -111,14 +118,6 @@ struct Token {
bool isRParen() const { return std::get_if<RParenTok>(&data); }
- std::optional<std::string_view> getID() const {
- if (std::get_if<IdTok>(&data)) {
- // Drop leading '$'.
- return span.substr(1);
- }
- return {};
- }
-
std::optional<std::string_view> getKeyword() const {
if (std::get_if<KeywordTok>(&data)) {
return span;
@@ -132,6 +131,7 @@ struct Token {
std::optional<double> getF64() const;
std::optional<float> getF32() const;
std::optional<std::string_view> getString() const;
+ std::optional<std::string_view> getID() const;
bool operator==(const Token&) const;
friend std::ostream& operator<<(std::ostream& os, const Token&);