lib_ruby_parser/lexer/
parse_ident.rs1use crate::lex_states::*;
2use crate::lexer::*;
3use crate::maybe_byte::*;
4use crate::reserved_word;
5use crate::source::buffer::*;
6use crate::DiagnosticMessage;
7
8fn is_var_name(ident: &str) -> bool {
9 if let Some(first_char) = ident.chars().next() {
10 return !first_char.is_uppercase();
11 }
12 false
13}
14
15impl Lexer {
16 pub(crate) fn is_identchar(&self) -> bool {
17 !self.buffer.eofp
18 && self
19 .buffer
20 .is_identchar(self.buffer.pcur - 1, self.buffer.pend)
21 }
22
23 pub(crate) fn tokenize_ident(&mut self) -> Option<String> {
24 self.set_yylval_name();
25 self.tokenbuf.borrow_string().map(|s| s.to_string()).ok()
26 }
27
28 pub(crate) fn parse_ident(&mut self, mut c: MaybeByte, cmd_state: bool) -> i32 {
29 let mut result: i32;
30 let last_state = self.lex_state;
31
32 loop {
33 if !c.is_ascii() { }
34 if self.tokadd_mbchar(c).is_err() {
35 return Self::END_OF_INPUT;
36 }
37 c = self.nextc();
38
39 if !self.is_identchar() {
40 break;
41 }
42 }
43
44 if (c == b'!' || c == b'?') && !self.buffer.peek(b'=') {
45 result = Self::tFID;
46 self.tokadd(c);
47 } else if c == b'='
48 && self.lex_state.is_some(EXPR_FNAME)
49 && (!self.buffer.peek(b'~')
50 && !self.buffer.peek(b'>')
51 && (!self.buffer.peek(b'=') || (self.buffer.peek_n(b'>', 1))))
52 {
53 result = Self::tIDENTIFIER;
54 self.tokadd(c)
55 } else {
56 result = Self::tCONSTANT; self.buffer.pushback(c)
58 }
59 self.tokfix();
60
61 if self.lex_state.is_label_possible(cmd_state) && self.is_label_suffix(0) {
62 self.lex_state.set(EXPR_ARG | EXPR_LABELED);
63 self.nextc();
64 self.set_yylval_name();
65 return Self::tLABEL;
66 }
67 if !self.lex_state.is_some(EXPR_DOT) {
68 if let Some(kw) = reserved_word(self.tokenbuf.bytes.as_raw()) {
69 let state = self.lex_state;
70 if state.is_some(EXPR_FNAME) {
71 self.lex_state.set(EXPR_ENDFN);
72 self.set_yylval_name();
73 return kw.id;
74 }
75 self.lex_state.set(kw.state);
76 if self.lex_state.is_some(EXPR_BEG) {
77 self.command_start = true
78 }
79 if kw.id == Self::kDO {
80 if self.is_lambda_beginning() {
81 self.lpar_beg = -1; return Self::kDO_LAMBDA;
83 }
84 if self.cond.is_active() {
85 return Self::kDO_COND;
86 }
87 if self.cmdarg.is_active() && !state.is_some(EXPR_CMDARG) {
88 return Self::kDO_BLOCK;
89 }
90 return Self::kDO;
91 }
92 if state.is_some(EXPR_BEG | EXPR_LABELED) {
93 return kw.id;
94 } else {
95 if kw.id != kw.modifier_id {
96 self.lex_state.set(EXPR_BEG | EXPR_LABEL)
97 }
98 return kw.modifier_id;
99 }
100 }
101 }
102
103 if self
104 .lex_state
105 .is_some(EXPR_BEG_ANY | EXPR_ARG_ANY | EXPR_DOT)
106 {
107 if cmd_state {
108 self.lex_state.set(EXPR_CMDARG);
109 } else {
110 self.lex_state.set(EXPR_ARG);
111 }
112 } else if self.lex_state.is(EXPR_FNAME) {
113 self.lex_state.set(EXPR_ENDFN)
114 } else {
115 self.lex_state.set(EXPR_END)
116 }
117
118 let ident = match self.tokenize_ident() {
119 Some(ident) => ident,
120 None => {
121 self.yyerror0(DiagnosticMessage::InvalidMultibyteChar {});
122 return Self::END_OF_INPUT;
123 }
124 };
125 if result == Self::tCONSTANT && is_var_name(&ident) {
126 result = Self::tIDENTIFIER
127 }
128 if !last_state.is_some(EXPR_DOT|EXPR_FNAME) &&
129 result == Self::tIDENTIFIER && self.is_lvar_defined(&ident)
131 {
132 self.lex_state.set(EXPR_END | EXPR_LABEL);
133 }
134
135 result
136 }
137}