Simplify variable name parsing.
This commit is contained in:
parent
411b718a3b
commit
3e08160653
170
src/parser.rs
170
src/parser.rs
@ -264,6 +264,22 @@ fn match_token(input: &mut TokenStream, token: Token) -> (bool, Position) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a variable name.
|
||||||
|
fn parse_var_name(input: &mut TokenStream) -> Result<(String, Position), ParseError> {
|
||||||
|
match input.next().expect(NEVER_ENDS) {
|
||||||
|
// Variable name
|
||||||
|
(Token::Identifier(s), pos) => Ok((s, pos)),
|
||||||
|
// Reserved keyword
|
||||||
|
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
|
||||||
|
Err(PERR::Reserved(s).into_err(pos))
|
||||||
|
}
|
||||||
|
// Bad identifier
|
||||||
|
(Token::LexError(err), pos) => Err(err.into_err(pos)),
|
||||||
|
// Not a variable name
|
||||||
|
(_, pos) => Err(PERR::VariableExpected.into_err(pos)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse ( expr )
|
/// Parse ( expr )
|
||||||
fn parse_paren_expr(
|
fn parse_paren_expr(
|
||||||
input: &mut TokenStream,
|
input: &mut TokenStream,
|
||||||
@ -1232,33 +1248,26 @@ fn parse_primary(
|
|||||||
}
|
}
|
||||||
// module access
|
// module access
|
||||||
(Expr::Variable(_, var_pos, x), Token::DoubleColon) => {
|
(Expr::Variable(_, var_pos, x), Token::DoubleColon) => {
|
||||||
match input.next().expect(NEVER_ENDS) {
|
let (id2, pos2) = parse_var_name(input)?;
|
||||||
(Token::Identifier(id2), pos2) => {
|
let (_, mut namespace, var_name) = *x;
|
||||||
let (_, mut namespace, var_name) = *x;
|
let var_name_def = Ident {
|
||||||
let var_name_def = Ident {
|
name: var_name,
|
||||||
name: var_name,
|
pos: var_pos,
|
||||||
pos: var_pos,
|
};
|
||||||
};
|
|
||||||
|
|
||||||
if let Some((_, ref mut namespace)) = namespace {
|
if let Some((_, ref mut namespace)) = namespace {
|
||||||
namespace.push(var_name_def);
|
namespace.push(var_name_def);
|
||||||
} else {
|
} else {
|
||||||
let mut ns: NamespaceRef = Default::default();
|
let mut ns: NamespaceRef = Default::default();
|
||||||
ns.push(var_name_def);
|
ns.push(var_name_def);
|
||||||
namespace = Some((42, ns));
|
namespace = Some((42, ns));
|
||||||
}
|
|
||||||
|
|
||||||
Expr::Variable(
|
|
||||||
None,
|
|
||||||
pos2,
|
|
||||||
Box::new((None, namespace, state.get_identifier(id2))),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
(Token::Reserved(id2), pos2) if is_valid_identifier(id2.chars()) => {
|
|
||||||
return Err(PERR::Reserved(id2).into_err(pos2));
|
|
||||||
}
|
|
||||||
(_, pos2) => return Err(PERR::VariableExpected.into_err(pos2)),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr::Variable(
|
||||||
|
None,
|
||||||
|
pos2,
|
||||||
|
Box::new((None, namespace, state.get_identifier(id2))),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// Indexing
|
// Indexing
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
@ -1886,18 +1895,13 @@ fn parse_custom_syntax(
|
|||||||
};
|
};
|
||||||
|
|
||||||
match required_token.as_str() {
|
match required_token.as_str() {
|
||||||
MARKER_IDENT => match input.next().expect(NEVER_ENDS) {
|
MARKER_IDENT => {
|
||||||
(Token::Identifier(s), pos) => {
|
let (name, pos) = parse_var_name(input)?;
|
||||||
let name = state.get_identifier(s);
|
let name = state.get_identifier(name);
|
||||||
segments.push(name.clone().into());
|
segments.push(name.clone().into());
|
||||||
tokens.push(state.get_identifier(MARKER_IDENT));
|
tokens.push(state.get_identifier(MARKER_IDENT));
|
||||||
keywords.push(Expr::Variable(None, pos, Box::new((None, None, name))));
|
keywords.push(Expr::Variable(None, pos, Box::new((None, None, name))));
|
||||||
}
|
}
|
||||||
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
|
|
||||||
return Err(PERR::Reserved(s).into_err(pos));
|
|
||||||
}
|
|
||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
|
||||||
},
|
|
||||||
MARKER_EXPR => {
|
MARKER_EXPR => {
|
||||||
keywords.push(parse_expr(input, state, lib, settings)?);
|
keywords.push(parse_expr(input, state, lib, settings)?);
|
||||||
let keyword = state.get_identifier(MARKER_EXPR);
|
let keyword = state.get_identifier(MARKER_EXPR);
|
||||||
@ -2144,21 +2148,6 @@ fn parse_for(
|
|||||||
lib: &mut FunctionsLib,
|
lib: &mut FunctionsLib,
|
||||||
mut settings: ParseSettings,
|
mut settings: ParseSettings,
|
||||||
) -> Result<Stmt, ParseError> {
|
) -> Result<Stmt, ParseError> {
|
||||||
fn get_name_pos(input: &mut TokenStream) -> Result<(String, Position), ParseError> {
|
|
||||||
match input.next().expect(NEVER_ENDS) {
|
|
||||||
// Variable name
|
|
||||||
(Token::Identifier(s), pos) => Ok((s, pos)),
|
|
||||||
// Reserved keyword
|
|
||||||
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
|
|
||||||
Err(PERR::Reserved(s).into_err(pos))
|
|
||||||
}
|
|
||||||
// Bad identifier
|
|
||||||
(Token::LexError(err), pos) => Err(err.into_err(pos)),
|
|
||||||
// Not a variable name
|
|
||||||
(_, pos) => Err(PERR::VariableExpected.into_err(pos)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||||
|
|
||||||
@ -2168,7 +2157,7 @@ fn parse_for(
|
|||||||
// for name ...
|
// for name ...
|
||||||
let (name, name_pos, counter_name, counter_pos) = if match_token(input, Token::LeftParen).0 {
|
let (name, name_pos, counter_name, counter_pos) = if match_token(input, Token::LeftParen).0 {
|
||||||
// ( name, counter )
|
// ( name, counter )
|
||||||
let (name, name_pos) = get_name_pos(input)?;
|
let (name, name_pos) = parse_var_name(input)?;
|
||||||
let (has_comma, pos) = match_token(input, Token::Comma);
|
let (has_comma, pos) = match_token(input, Token::Comma);
|
||||||
if !has_comma {
|
if !has_comma {
|
||||||
return Err(PERR::MissingToken(
|
return Err(PERR::MissingToken(
|
||||||
@ -2177,7 +2166,7 @@ fn parse_for(
|
|||||||
)
|
)
|
||||||
.into_err(pos));
|
.into_err(pos));
|
||||||
}
|
}
|
||||||
let (counter_name, counter_pos) = get_name_pos(input)?;
|
let (counter_name, counter_pos) = parse_var_name(input)?;
|
||||||
|
|
||||||
if counter_name == name {
|
if counter_name == name {
|
||||||
return Err(PERR::DuplicatedVariable(counter_name).into_err(counter_pos));
|
return Err(PERR::DuplicatedVariable(counter_name).into_err(counter_pos));
|
||||||
@ -2194,7 +2183,7 @@ fn parse_for(
|
|||||||
(name, name_pos, Some(counter_name), Some(counter_pos))
|
(name, name_pos, Some(counter_name), Some(counter_pos))
|
||||||
} else {
|
} else {
|
||||||
// name
|
// name
|
||||||
let (name, name_pos) = get_name_pos(input)?;
|
let (name, name_pos) = parse_var_name(input)?;
|
||||||
(name, name_pos, None, None)
|
(name, name_pos, None, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2266,14 +2255,7 @@ fn parse_let(
|
|||||||
settings.pos = input.next().expect(NEVER_ENDS).1;
|
settings.pos = input.next().expect(NEVER_ENDS).1;
|
||||||
|
|
||||||
// let name ...
|
// let name ...
|
||||||
let (name, pos) = match input.next().expect(NEVER_ENDS) {
|
let (name, pos) = parse_var_name(input)?;
|
||||||
(Token::Identifier(s), pos) => (s, pos),
|
|
||||||
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
|
|
||||||
return Err(PERR::Reserved(s).into_err(pos));
|
|
||||||
}
|
|
||||||
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
|
||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let name = state.get_identifier(name);
|
let name = state.get_identifier(name);
|
||||||
let var_def = Ident {
|
let var_def = Ident {
|
||||||
@ -2322,15 +2304,7 @@ fn parse_import(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// import expr as name ...
|
// import expr as name ...
|
||||||
let (name, name_pos) = match input.next().expect(NEVER_ENDS) {
|
let (name, name_pos) = parse_var_name(input)?;
|
||||||
(Token::Identifier(s), pos) => (s, pos),
|
|
||||||
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
|
|
||||||
return Err(PERR::Reserved(s).into_err(pos));
|
|
||||||
}
|
|
||||||
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
|
||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let name = state.get_identifier(name);
|
let name = state.get_identifier(name);
|
||||||
state.modules.push(name.clone());
|
state.modules.push(name.clone());
|
||||||
|
|
||||||
@ -2379,36 +2353,18 @@ fn parse_export(
|
|||||||
let mut exports = Vec::with_capacity(4);
|
let mut exports = Vec::with_capacity(4);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (id, id_pos) = match input.next().expect(NEVER_ENDS) {
|
let (id, id_pos) = parse_var_name(input)?;
|
||||||
(Token::Identifier(s), pos) => (s.clone(), pos),
|
|
||||||
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
|
|
||||||
return Err(PERR::Reserved(s).into_err(pos));
|
|
||||||
}
|
|
||||||
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
|
||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let rename = if match_token(input, Token::As).0 {
|
let rename = if match_token(input, Token::As).0 {
|
||||||
match input.next().expect(NEVER_ENDS) {
|
let (name, pos) = parse_var_name(input)?;
|
||||||
(Token::Identifier(s), pos) => {
|
if exports.iter().any(|(_, alias)| match alias {
|
||||||
if exports.iter().any(|(_, alias)| match alias {
|
Some(Ident { name: alias, .. }) if alias == &name => true,
|
||||||
Some(Ident { name, .. }) if name == &s => true,
|
_ => false,
|
||||||
_ => false,
|
}) {
|
||||||
}) {
|
return Err(PERR::DuplicatedVariable(name).into_err(pos));
|
||||||
return Err(PERR::DuplicatedVariable(s).into_err(pos));
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(Ident {
|
|
||||||
name: state.get_identifier(s),
|
|
||||||
pos,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
|
|
||||||
return Err(PERR::Reserved(s).into_err(pos));
|
|
||||||
}
|
|
||||||
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
|
||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
|
||||||
}
|
}
|
||||||
|
let name = state.get_identifier(name);
|
||||||
|
Some(Ident { name, pos })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -2781,25 +2737,19 @@ fn parse_try_catch(
|
|||||||
|
|
||||||
// try { body } catch (
|
// try { body } catch (
|
||||||
let var_def = if match_token(input, Token::LeftParen).0 {
|
let var_def = if match_token(input, Token::LeftParen).0 {
|
||||||
let id = match input.next().expect(NEVER_ENDS) {
|
let (name, pos) = parse_var_name(input)?;
|
||||||
(Token::Identifier(s), pos) => Ident {
|
let (matched, err_pos) = match_token(input, Token::RightParen);
|
||||||
name: state.get_identifier(s),
|
|
||||||
pos,
|
|
||||||
},
|
|
||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let (matched, pos) = match_token(input, Token::RightParen);
|
|
||||||
|
|
||||||
if !matched {
|
if !matched {
|
||||||
return Err(PERR::MissingToken(
|
return Err(PERR::MissingToken(
|
||||||
Token::RightParen.into(),
|
Token::RightParen.into(),
|
||||||
"to enclose the catch variable".into(),
|
"to enclose the catch variable".into(),
|
||||||
)
|
)
|
||||||
.into_err(pos));
|
.into_err(err_pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(id)
|
let name = state.get_identifier(name);
|
||||||
|
Some(Ident { name, pos })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user