scan_expr.rs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // SPDX-License-Identifier: Apache-2.0 OR MIT
  2. use self::{Action::*, Input::*};
  3. use proc_macro2::{Delimiter, Ident, Spacing, TokenTree};
  4. use syn::parse::{ParseStream, Result};
  5. use syn::{AngleBracketedGenericArguments, BinOp, Expr, ExprPath, Lifetime, Lit, Token, Type};
  6. enum Input {
  7. Keyword(&'static str),
  8. Punct(&'static str),
  9. ConsumeAny,
  10. ConsumeBinOp,
  11. ConsumeBrace,
  12. ConsumeDelimiter,
  13. ConsumeIdent,
  14. ConsumeLifetime,
  15. ConsumeLiteral,
  16. ConsumeNestedBrace,
  17. ExpectPath,
  18. ExpectTurbofish,
  19. ExpectType,
  20. CanBeginExpr,
  21. Otherwise,
  22. Empty,
  23. }
  24. enum Action {
  25. SetState(&'static [(Input, Action)]),
  26. IncDepth,
  27. DecDepth,
  28. Finish,
  29. }
  30. static INIT: [(Input, Action); 28] = [
  31. (ConsumeDelimiter, SetState(&POSTFIX)),
  32. (Keyword("async"), SetState(&ASYNC)),
  33. (Keyword("break"), SetState(&BREAK_LABEL)),
  34. (Keyword("const"), SetState(&CONST)),
  35. (Keyword("continue"), SetState(&CONTINUE)),
  36. (Keyword("for"), SetState(&FOR)),
  37. (Keyword("if"), IncDepth),
  38. (Keyword("let"), SetState(&PATTERN)),
  39. (Keyword("loop"), SetState(&BLOCK)),
  40. (Keyword("match"), IncDepth),
  41. (Keyword("move"), SetState(&CLOSURE)),
  42. (Keyword("return"), SetState(&RETURN)),
  43. (Keyword("static"), SetState(&CLOSURE)),
  44. (Keyword("unsafe"), SetState(&BLOCK)),
  45. (Keyword("while"), IncDepth),
  46. (Keyword("yield"), SetState(&RETURN)),
  47. (Keyword("_"), SetState(&POSTFIX)),
  48. (Punct("!"), SetState(&INIT)),
  49. (Punct("#"), SetState(&[(ConsumeDelimiter, SetState(&INIT))])),
  50. (Punct("&"), SetState(&REFERENCE)),
  51. (Punct("*"), SetState(&INIT)),
  52. (Punct("-"), SetState(&INIT)),
  53. (Punct("..="), SetState(&INIT)),
  54. (Punct(".."), SetState(&RANGE)),
  55. (Punct("|"), SetState(&CLOSURE_ARGS)),
  56. (ConsumeLifetime, SetState(&[(Punct(":"), SetState(&INIT))])),
  57. (ConsumeLiteral, SetState(&POSTFIX)),
  58. (ExpectPath, SetState(&PATH)),
  59. ];
  60. static POSTFIX: [(Input, Action); 10] = [
  61. (Keyword("as"), SetState(&[(ExpectType, SetState(&POSTFIX))])),
  62. (Punct("..="), SetState(&INIT)),
  63. (Punct(".."), SetState(&RANGE)),
  64. (Punct("."), SetState(&DOT)),
  65. (Punct("?"), SetState(&POSTFIX)),
  66. (ConsumeBinOp, SetState(&INIT)),
  67. (Punct("="), SetState(&INIT)),
  68. (ConsumeNestedBrace, SetState(&IF_THEN)),
  69. (ConsumeDelimiter, SetState(&POSTFIX)),
  70. (Empty, Finish),
  71. ];
  72. static ASYNC: [(Input, Action); 3] = [
  73. (Keyword("move"), SetState(&ASYNC)),
  74. (Punct("|"), SetState(&CLOSURE_ARGS)),
  75. (ConsumeBrace, SetState(&POSTFIX)),
  76. ];
  77. static BLOCK: [(Input, Action); 1] = [(ConsumeBrace, SetState(&POSTFIX))];
  78. static BREAK_LABEL: [(Input, Action); 2] = [
  79. (ConsumeLifetime, SetState(&BREAK_VALUE)),
  80. (Otherwise, SetState(&BREAK_VALUE)),
  81. ];
  82. static BREAK_VALUE: [(Input, Action); 3] = [
  83. (ConsumeNestedBrace, SetState(&IF_THEN)),
  84. (CanBeginExpr, SetState(&INIT)),
  85. (Otherwise, SetState(&POSTFIX)),
  86. ];
  87. static CLOSURE: [(Input, Action); 7] = [
  88. (Keyword("async"), SetState(&CLOSURE)),
  89. (Keyword("move"), SetState(&CLOSURE)),
  90. (Punct(","), SetState(&CLOSURE)),
  91. (Punct(">"), SetState(&CLOSURE)),
  92. (Punct("|"), SetState(&CLOSURE_ARGS)),
  93. (ConsumeLifetime, SetState(&CLOSURE)),
  94. (ConsumeIdent, SetState(&CLOSURE)),
  95. ];
  96. static CLOSURE_ARGS: [(Input, Action); 2] = [
  97. (Punct("|"), SetState(&CLOSURE_RET)),
  98. (ConsumeAny, SetState(&CLOSURE_ARGS)),
  99. ];
  100. static CLOSURE_RET: [(Input, Action); 2] = [
  101. (Punct("->"), SetState(&[(ExpectType, SetState(&BLOCK))])),
  102. (Otherwise, SetState(&INIT)),
  103. ];
  104. static CONST: [(Input, Action); 2] = [
  105. (Punct("|"), SetState(&CLOSURE_ARGS)),
  106. (ConsumeBrace, SetState(&POSTFIX)),
  107. ];
  108. static CONTINUE: [(Input, Action); 2] = [
  109. (ConsumeLifetime, SetState(&POSTFIX)),
  110. (Otherwise, SetState(&POSTFIX)),
  111. ];
  112. static DOT: [(Input, Action); 3] = [
  113. (Keyword("await"), SetState(&POSTFIX)),
  114. (ConsumeIdent, SetState(&METHOD)),
  115. (ConsumeLiteral, SetState(&POSTFIX)),
  116. ];
  117. static FOR: [(Input, Action); 2] = [
  118. (Punct("<"), SetState(&CLOSURE)),
  119. (Otherwise, SetState(&PATTERN)),
  120. ];
  121. static IF_ELSE: [(Input, Action); 2] = [(Keyword("if"), SetState(&INIT)), (ConsumeBrace, DecDepth)];
  122. static IF_THEN: [(Input, Action); 2] =
  123. [(Keyword("else"), SetState(&IF_ELSE)), (Otherwise, DecDepth)];
  124. static METHOD: [(Input, Action); 1] = [(ExpectTurbofish, SetState(&POSTFIX))];
  125. static PATH: [(Input, Action); 4] = [
  126. (Punct("!="), SetState(&INIT)),
  127. (Punct("!"), SetState(&INIT)),
  128. (ConsumeNestedBrace, SetState(&IF_THEN)),
  129. (Otherwise, SetState(&POSTFIX)),
  130. ];
  131. static PATTERN: [(Input, Action); 15] = [
  132. (ConsumeDelimiter, SetState(&PATTERN)),
  133. (Keyword("box"), SetState(&PATTERN)),
  134. (Keyword("in"), IncDepth),
  135. (Keyword("mut"), SetState(&PATTERN)),
  136. (Keyword("ref"), SetState(&PATTERN)),
  137. (Keyword("_"), SetState(&PATTERN)),
  138. (Punct("!"), SetState(&PATTERN)),
  139. (Punct("&"), SetState(&PATTERN)),
  140. (Punct("..="), SetState(&PATTERN)),
  141. (Punct(".."), SetState(&PATTERN)),
  142. (Punct("="), SetState(&INIT)),
  143. (Punct("@"), SetState(&PATTERN)),
  144. (Punct("|"), SetState(&PATTERN)),
  145. (ConsumeLiteral, SetState(&PATTERN)),
  146. (ExpectPath, SetState(&PATTERN)),
  147. ];
  148. static RANGE: [(Input, Action); 6] = [
  149. (Punct("..="), SetState(&INIT)),
  150. (Punct(".."), SetState(&RANGE)),
  151. (Punct("."), SetState(&DOT)),
  152. (ConsumeNestedBrace, SetState(&IF_THEN)),
  153. (Empty, Finish),
  154. (Otherwise, SetState(&INIT)),
  155. ];
  156. static RAW: [(Input, Action); 3] = [
  157. (Keyword("const"), SetState(&INIT)),
  158. (Keyword("mut"), SetState(&INIT)),
  159. (Otherwise, SetState(&POSTFIX)),
  160. ];
  161. static REFERENCE: [(Input, Action); 3] = [
  162. (Keyword("mut"), SetState(&INIT)),
  163. (Keyword("raw"), SetState(&RAW)),
  164. (Otherwise, SetState(&INIT)),
  165. ];
  166. static RETURN: [(Input, Action); 2] = [
  167. (CanBeginExpr, SetState(&INIT)),
  168. (Otherwise, SetState(&POSTFIX)),
  169. ];
  170. pub(crate) fn scan_expr(input: ParseStream) -> Result<()> {
  171. let mut state = INIT.as_slice();
  172. let mut depth = 0usize;
  173. 'table: loop {
  174. for rule in state {
  175. if match rule.0 {
  176. Input::Keyword(expected) => input.step(|cursor| match cursor.ident() {
  177. Some((ident, rest)) if ident == expected => Ok((true, rest)),
  178. _ => Ok((false, *cursor)),
  179. })?,
  180. Input::Punct(expected) => input.step(|cursor| {
  181. let begin = *cursor;
  182. let mut cursor = begin;
  183. for (i, ch) in expected.chars().enumerate() {
  184. match cursor.punct() {
  185. Some((punct, _)) if punct.as_char() != ch => break,
  186. Some((_, rest)) if i == expected.len() - 1 => {
  187. return Ok((true, rest));
  188. }
  189. Some((punct, rest)) if punct.spacing() == Spacing::Joint => {
  190. cursor = rest;
  191. }
  192. _ => break,
  193. }
  194. }
  195. Ok((false, begin))
  196. })?,
  197. Input::ConsumeAny => input.parse::<Option<TokenTree>>()?.is_some(),
  198. Input::ConsumeBinOp => input.parse::<BinOp>().is_ok(),
  199. Input::ConsumeBrace | Input::ConsumeNestedBrace => {
  200. (matches!(rule.0, Input::ConsumeBrace) || depth > 0)
  201. && input.step(|cursor| match cursor.group(Delimiter::Brace) {
  202. Some((_inside, _span, rest)) => Ok((true, rest)),
  203. None => Ok((false, *cursor)),
  204. })?
  205. }
  206. Input::ConsumeDelimiter => input.step(|cursor| match cursor.any_group() {
  207. Some((_inside, _delimiter, _span, rest)) => Ok((true, rest)),
  208. None => Ok((false, *cursor)),
  209. })?,
  210. Input::ConsumeIdent => input.parse::<Option<Ident>>()?.is_some(),
  211. Input::ConsumeLifetime => input.parse::<Option<Lifetime>>()?.is_some(),
  212. Input::ConsumeLiteral => input.parse::<Option<Lit>>()?.is_some(),
  213. Input::ExpectPath => {
  214. input.parse::<ExprPath>()?;
  215. true
  216. }
  217. Input::ExpectTurbofish => {
  218. if input.peek(Token![::]) {
  219. input.parse::<AngleBracketedGenericArguments>()?;
  220. }
  221. true
  222. }
  223. Input::ExpectType => {
  224. Type::without_plus(input)?;
  225. true
  226. }
  227. Input::CanBeginExpr => Expr::peek(input),
  228. Input::Otherwise => true,
  229. Input::Empty => input.is_empty() || input.peek(Token![,]),
  230. } {
  231. state = match rule.1 {
  232. Action::SetState(next) => next,
  233. Action::IncDepth => (depth += 1, &INIT).1,
  234. Action::DecDepth => (depth -= 1, &POSTFIX).1,
  235. Action::Finish => return if depth == 0 { Ok(()) } else { break },
  236. };
  237. continue 'table;
  238. }
  239. }
  240. return Err(input.error("unsupported expression"));
  241. }
  242. }