1 use super::errors::{ErrorKind, ParserError}; 2 use super::{core::Parser, core::Result, slice::Slice}; 3 use crate::ast; 4 5 impl<'s, S> Parser<S> 6 where 7 S: Slice<'s>, 8 { get_expression(&mut self) -> Result<ast::Expression<S>>9 pub(super) fn get_expression(&mut self) -> Result<ast::Expression<S>> { 10 let exp = self.get_inline_expression(false)?; 11 12 self.skip_blank(); 13 14 if !self.is_current_byte(b'-') || !self.is_byte_at(b'>', self.ptr + 1) { 15 if let ast::InlineExpression::TermReference { ref attribute, .. } = exp { 16 if attribute.is_some() { 17 return error!(ErrorKind::TermAttributeAsPlaceable, self.ptr); 18 } 19 } 20 return Ok(ast::Expression::Inline(exp)); 21 } 22 23 match exp { 24 ast::InlineExpression::MessageReference { ref attribute, .. } => { 25 if attribute.is_none() { 26 return error!(ErrorKind::MessageReferenceAsSelector, self.ptr); 27 } else { 28 return error!(ErrorKind::MessageAttributeAsSelector, self.ptr); 29 } 30 } 31 ast::InlineExpression::TermReference { ref attribute, .. } => { 32 if attribute.is_none() { 33 return error!(ErrorKind::TermReferenceAsSelector, self.ptr); 34 } 35 } 36 ast::InlineExpression::StringLiteral { .. } 37 | ast::InlineExpression::NumberLiteral { .. } 38 | ast::InlineExpression::VariableReference { .. } 39 | ast::InlineExpression::FunctionReference { .. } => {} 40 _ => { 41 return error!(ErrorKind::ExpectedSimpleExpressionAsSelector, self.ptr); 42 } 43 }; 44 45 self.ptr += 2; // -> 46 47 self.skip_blank_inline(); 48 if !self.skip_eol() { 49 return error!( 50 ErrorKind::ExpectedCharRange { 51 range: "\n | \r\n".to_string() 52 }, 53 self.ptr 54 ); 55 } 56 self.skip_blank(); 57 58 let variants = self.get_variants()?; 59 60 Ok(ast::Expression::Select { 61 selector: exp, 62 variants, 63 }) 64 } 65 get_inline_expression( &mut self, only_literal: bool, ) -> Result<ast::InlineExpression<S>>66 pub(super) fn get_inline_expression( 67 &mut self, 68 only_literal: bool, 69 ) -> Result<ast::InlineExpression<S>> { 70 match get_current_byte!(self) { 71 Some(b'"') => { 72 self.ptr += 1; // " 73 let start = self.ptr; 74 while let Some(b) = get_current_byte!(self) { 75 match b { 76 b'\\' => match get_byte!(self, self.ptr + 1) { 77 Some(b'\\') | Some(b'{') | Some(b'"') => self.ptr += 2, 78 Some(b'u') => { 79 self.ptr += 2; 80 self.skip_unicode_escape_sequence(4)?; 81 } 82 Some(b'U') => { 83 self.ptr += 2; 84 self.skip_unicode_escape_sequence(6)?; 85 } 86 b => { 87 let seq = b.unwrap_or(&b' ').to_string(); 88 return error!(ErrorKind::UnknownEscapeSequence(seq), self.ptr); 89 } 90 }, 91 b'"' => { 92 break; 93 } 94 b'\n' => { 95 return error!(ErrorKind::UnterminatedStringLiteral, self.ptr); 96 } 97 _ => self.ptr += 1, 98 } 99 } 100 101 self.expect_byte(b'"')?; 102 let slice = self.source.slice(start..self.ptr - 1); 103 Ok(ast::InlineExpression::StringLiteral { value: slice }) 104 } 105 Some(b) if b.is_ascii_digit() => { 106 let num = self.get_number_literal()?; 107 Ok(ast::InlineExpression::NumberLiteral { value: num }) 108 } 109 Some(b'-') if !only_literal => { 110 self.ptr += 1; // - 111 if self.is_identifier_start() { 112 self.ptr += 1; 113 let id = self.get_identifier_unchecked(); 114 let attribute = self.get_attribute_accessor()?; 115 let arguments = self.get_call_arguments()?; 116 Ok(ast::InlineExpression::TermReference { 117 id, 118 attribute, 119 arguments, 120 }) 121 } else { 122 self.ptr -= 1; 123 let num = self.get_number_literal()?; 124 Ok(ast::InlineExpression::NumberLiteral { value: num }) 125 } 126 } 127 Some(b'$') if !only_literal => { 128 self.ptr += 1; // $ 129 let id = self.get_identifier()?; 130 Ok(ast::InlineExpression::VariableReference { id }) 131 } 132 Some(b) if b.is_ascii_alphabetic() => { 133 self.ptr += 1; 134 let id = self.get_identifier_unchecked(); 135 let arguments = self.get_call_arguments()?; 136 if let Some(arguments) = arguments { 137 if !Self::is_callee(&id.name) { 138 return error!(ErrorKind::ForbiddenCallee, self.ptr); 139 } 140 141 Ok(ast::InlineExpression::FunctionReference { id, arguments }) 142 } else { 143 let attribute = self.get_attribute_accessor()?; 144 Ok(ast::InlineExpression::MessageReference { id, attribute }) 145 } 146 } 147 Some(b'{') if !only_literal => { 148 self.ptr += 1; // { 149 let exp = self.get_placeable()?; 150 Ok(ast::InlineExpression::Placeable { 151 expression: Box::new(exp), 152 }) 153 } 154 _ if only_literal => error!(ErrorKind::ExpectedLiteral, self.ptr), 155 _ => error!(ErrorKind::ExpectedInlineExpression, self.ptr), 156 } 157 } 158 get_call_arguments(&mut self) -> Result<Option<ast::CallArguments<S>>>159 pub fn get_call_arguments(&mut self) -> Result<Option<ast::CallArguments<S>>> { 160 self.skip_blank(); 161 if !self.take_byte_if(b'(') { 162 return Ok(None); 163 } 164 165 let mut positional = vec![]; 166 let mut named = vec![]; 167 let mut argument_names = vec![]; 168 169 self.skip_blank(); 170 171 while self.ptr < self.length { 172 if self.is_current_byte(b')') { 173 break; 174 } 175 176 let expr = self.get_inline_expression(false)?; 177 178 if let ast::InlineExpression::MessageReference { 179 ref id, 180 attribute: None, 181 } = expr 182 { 183 self.skip_blank(); 184 if self.is_current_byte(b':') { 185 if argument_names.contains(&id.name) { 186 return error!( 187 ErrorKind::DuplicatedNamedArgument(id.name.as_ref().to_owned()), 188 self.ptr 189 ); 190 } 191 self.ptr += 1; 192 self.skip_blank(); 193 let val = self.get_inline_expression(true)?; 194 195 argument_names.push(id.name.clone()); 196 named.push(ast::NamedArgument { 197 name: ast::Identifier { 198 name: id.name.clone(), 199 }, 200 value: val, 201 }); 202 } else { 203 if !argument_names.is_empty() { 204 return error!(ErrorKind::PositionalArgumentFollowsNamed, self.ptr); 205 } 206 positional.push(expr); 207 } 208 } else { 209 if !argument_names.is_empty() { 210 return error!(ErrorKind::PositionalArgumentFollowsNamed, self.ptr); 211 } 212 positional.push(expr); 213 } 214 215 self.skip_blank(); 216 self.take_byte_if(b','); 217 self.skip_blank(); 218 } 219 220 self.expect_byte(b')')?; 221 222 Ok(Some(ast::CallArguments { positional, named })) 223 } 224 } 225