|
6 | 6 | //! convenient to include a text-based lexer here!
|
7 | 7 | //!
|
8 | 8 | //! Note that these tokens, unlike the tokens we feed into the parser, do
|
9 |
| -//! include info about comments and whitespace. |
| 9 | +//! include info about comments and whitespace. |
10 | 10 |
|
11 | 11 | use crate::{
|
12 | 12 | SyntaxKind::{self, *},
|
@@ -82,18 +82,45 @@ impl<'a> LexedStr<'a> {
|
82 | 82 | assert!(i < self.len());
|
83 | 83 | self.kind[i]
|
84 | 84 | }
|
| 85 | + |
85 | 86 | pub fn text(&self, i: usize) -> &str {
|
86 | 87 | assert!(i < self.len());
|
87 | 88 | let lo = self.start[i] as usize;
|
88 | 89 | let hi = self.start[i + 1] as usize;
|
89 | 90 | &self.text[lo..hi]
|
90 | 91 | }
|
| 92 | + |
91 | 93 | pub fn error(&self, i: usize) -> Option<&str> {
|
92 | 94 | assert!(i < self.len());
|
93 | 95 | let err = self.error.binary_search_by_key(&(i as u32), |i| i.token).ok()?;
|
94 | 96 | Some(self.error[err].msg.as_str())
|
95 | 97 | }
|
96 | 98 |
|
| 99 | + pub fn to_tokens(&self) -> crate::Tokens { |
| 100 | + let mut res = crate::Tokens::default(); |
| 101 | + let mut was_joint = false; |
| 102 | + for i in 0..self.len() { |
| 103 | + let kind = self.kind(i); |
| 104 | + if kind.is_trivia() { |
| 105 | + was_joint = false |
| 106 | + } else { |
| 107 | + if kind == SyntaxKind::IDENT { |
| 108 | + let token_text = self.text(i); |
| 109 | + let contextual_kw = SyntaxKind::from_contextual_keyword(token_text) |
| 110 | + .unwrap_or(SyntaxKind::IDENT); |
| 111 | + res.push_ident(contextual_kw); |
| 112 | + } else { |
| 113 | + if was_joint { |
| 114 | + res.was_joint(); |
| 115 | + } |
| 116 | + res.push(kind); |
| 117 | + } |
| 118 | + was_joint = true; |
| 119 | + } |
| 120 | + } |
| 121 | + res |
| 122 | + } |
| 123 | + |
97 | 124 | fn push(&mut self, kind: SyntaxKind, offset: usize) {
|
98 | 125 | self.kind.push(kind);
|
99 | 126 | self.start.push(offset as u32);
|
|
0 commit comments