mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
cleanup
This commit is contained in:
parent
b4b77add08
commit
3e554cb21f
10 changed files with 237 additions and 117 deletions
|
@ -1,8 +1,7 @@
|
|||
use crate::ast::CommentOrNewline::{self, *};
|
||||
use crate::ast::{Attempting, Spaceable};
|
||||
use crate::parser::{
|
||||
self, and, ascii_char, ascii_string, optional, parse_utf8, peek_utf8_char, then, unexpected,
|
||||
unexpected_eof, BadInputError, Col, Parser,
|
||||
self, and, peek_utf8_char, unexpected, unexpected_eof, BadInputError, Col, Parser,
|
||||
Progress::{self, *},
|
||||
Row, State, SyntaxError,
|
||||
};
|
||||
|
@ -161,31 +160,69 @@ enum LineState {
|
|||
DocComment,
|
||||
}
|
||||
|
||||
pub fn line_comment<'a>() -> impl Parser<'a, &'a str, SyntaxError<'a>> {
|
||||
then(
|
||||
and!(ascii_char(b'#'), optional(ascii_string("# "))),
|
||||
|arena: &'a Bump, state: State<'a>, _, (_, opt_doc)| {
|
||||
if opt_doc != None {
|
||||
return Err(unexpected(3, Attempting::LineComment, state));
|
||||
}
|
||||
let mut length = 0;
|
||||
// then(
|
||||
// and!(ascii_char(b'#'), optional(ascii_string("# "))),
|
||||
// |arena: &'a Bump, state: State<'a>, _, (_, opt_doc)| {
|
||||
// if opt_doc != None {
|
||||
// return Err(unexpected(3, Attempting::LineComment, state));
|
||||
// }
|
||||
// let mut length = 0;
|
||||
//
|
||||
// for &byte in state.bytes.iter() {
|
||||
// if byte != b'\n' {
|
||||
// length += 1;
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// let comment = &state.bytes[..length];
|
||||
// let state = state.advance_without_indenting(length + 1)?;
|
||||
// match parse_utf8(comment) {
|
||||
// Ok(comment_str) => Ok((MadeProgress, comment_str, state)),
|
||||
// Err(reason) => state.fail(arena, MadeProgress, reason),
|
||||
// }
|
||||
// },
|
||||
// )
|
||||
|
||||
for &byte in state.bytes.iter() {
|
||||
if byte != b'\n' {
|
||||
length += 1;
|
||||
} else {
|
||||
pub fn line_comment<'a>() -> impl Parser<'a, &'a str, SyntaxError<'a>> {
|
||||
|_, state: State<'a>| match chomp_line_comment(state.bytes) {
|
||||
Ok(comment) => {
|
||||
let width = 1 + comment.len();
|
||||
let state = state.advance_without_indenting(width + 1)?;
|
||||
|
||||
Ok((MadeProgress, comment, state))
|
||||
}
|
||||
Err(progress) => Err((progress, SyntaxError::ConditionFailed, state)),
|
||||
}
|
||||
}
|
||||
|
||||
fn chomp_line_comment<'a>(buffer: &'a [u8]) -> Result<&'a str, Progress> {
|
||||
if let Some(b'#') = buffer.get(0) {
|
||||
if (&buffer[1..]).starts_with(b"# ") {
|
||||
// this is a doc comment, not a line comment
|
||||
Err(NoProgress)
|
||||
} else {
|
||||
use encode_unicode::CharExt;
|
||||
|
||||
let mut chomped = 1;
|
||||
|
||||
while let Ok((ch, width)) = char::from_utf8_slice_start(&buffer[chomped..]) {
|
||||
if ch == '\n' {
|
||||
break;
|
||||
} else {
|
||||
chomped += width;
|
||||
}
|
||||
}
|
||||
|
||||
let comment = &state.bytes[..length];
|
||||
let state = state.advance_without_indenting(length + 1)?;
|
||||
match parse_utf8(comment) {
|
||||
Ok(comment_str) => Ok((MadeProgress, comment_str, state)),
|
||||
Err(reason) => state.fail(arena, MadeProgress, reason),
|
||||
}
|
||||
},
|
||||
)
|
||||
let comment_bytes = &buffer[1..chomped];
|
||||
let comment = unsafe { std::str::from_utf8_unchecked(comment_bytes) };
|
||||
|
||||
Ok(comment)
|
||||
}
|
||||
} else {
|
||||
Err(NoProgress)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
|
|
@ -1171,7 +1171,7 @@ fn parse_def_signature_help<'a>(
|
|||
// Indented more beyond the original indent.
|
||||
let indented_more = original_indent + 1;
|
||||
|
||||
and!(
|
||||
let parser1 = {
|
||||
// Parse the first annotation. It doesn't need any spaces
|
||||
// around it parsed, because both the subsquent defs and the
|
||||
// final body will have space1_before on them.
|
||||
|
@ -1183,19 +1183,24 @@ fn parse_def_signature_help<'a>(
|
|||
specialize(EExpr::Type, type_annotation::located_help(indented_more)),
|
||||
min_indent,
|
||||
EExpr::Space,
|
||||
EExpr::IndentAnnotation
|
||||
EExpr::IndentAnnotation,
|
||||
),
|
||||
// The first annotation may be immediately (spaces_then_comment_or_newline())
|
||||
// followed by a body at the exact same indent_level
|
||||
// leading to an AnnotatedBody in this case
|
||||
|_progress, type_ann, indent_level| map(
|
||||
optional(and!(
|
||||
backtrackable(spaces_then_comment_or_newline_help()),
|
||||
body_at_indent_help(indent_level)
|
||||
)),
|
||||
move |opt_body| (type_ann.clone(), opt_body)
|
||||
)
|
||||
),
|
||||
|_progress, type_ann, indent_level| {
|
||||
map(
|
||||
optional(and!(
|
||||
backtrackable(spaces_then_comment_or_newline_help()),
|
||||
body_at_indent_help(indent_level)
|
||||
)),
|
||||
move |opt_body| (type_ann.clone(), opt_body),
|
||||
)
|
||||
},
|
||||
)
|
||||
};
|
||||
|
||||
let parser2 = {
|
||||
and!(
|
||||
// Optionally parse additional defs.
|
||||
zero_or_more!(backtrackable(allocated(space0_before_e(
|
||||
|
@ -1207,15 +1212,22 @@ fn parse_def_signature_help<'a>(
|
|||
// Parse the final expression that will be returned.
|
||||
// It should be indented the same amount as the original.
|
||||
space0_before_e(
|
||||
loc!(|arena, state| parse_expr_help(original_indent, arena, state)),
|
||||
loc!(one_of![
|
||||
|arena, state| parse_expr_help(original_indent, arena, state),
|
||||
|_, state: State<'a>| Err((
|
||||
MadeProgress,
|
||||
EExpr::DefMissingFinalExpr(state.line, state.column),
|
||||
state
|
||||
)),
|
||||
]),
|
||||
original_indent,
|
||||
EExpr::Space,
|
||||
EExpr::IndentEnd,
|
||||
)
|
||||
)
|
||||
)
|
||||
.parse(arena, state)
|
||||
.map(
|
||||
};
|
||||
|
||||
and!(parser1, parser2).parse(arena, state).map(
|
||||
move |(progress, ((loc_first_annotation, opt_body), (mut defs, loc_ret)), state)| {
|
||||
let loc_first_def: Located<Def<'a>> = match opt_body {
|
||||
None => {
|
||||
|
|
|
@ -150,7 +150,7 @@ pub fn parse_ident_help<'a>(
|
|||
Err((MadeProgress, fail, state)) => match fail {
|
||||
BadIdent::Start(r, c) => Err((NoProgress, EExpr::Start(r, c), state)),
|
||||
BadIdent::Space(e, r, c) => Err((NoProgress, EExpr::Space(e, r, c), state)),
|
||||
_ => malformed_identifier(initial.bytes, fail, arena, state),
|
||||
_ => malformed_identifier(initial.bytes, fail, state),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -158,13 +158,24 @@ pub fn parse_ident_help<'a>(
|
|||
fn malformed_identifier<'a>(
|
||||
initial_bytes: &'a [u8],
|
||||
problem: BadIdent,
|
||||
_arena: &'a Bump,
|
||||
mut state: State<'a>,
|
||||
) -> ParseResult<'a, Ident<'a>, EExpr<'a>> {
|
||||
let chomped = chomp_malformed(state.bytes);
|
||||
let delta = initial_bytes.len() - state.bytes.len();
|
||||
let parsed_str = unsafe { std::str::from_utf8_unchecked(&initial_bytes[..chomped + delta]) };
|
||||
|
||||
state = state.advance_without_indenting_ee(chomped, |r, c| {
|
||||
EExpr::Space(crate::parser::BadInputError::LineTooLong, r, c)
|
||||
})?;
|
||||
|
||||
Ok((MadeProgress, Ident::Malformed(parsed_str, problem), state))
|
||||
}
|
||||
|
||||
/// skip forward to the next non-identifier character
|
||||
pub fn chomp_malformed<'a>(bytes: &'a [u8]) -> usize {
|
||||
use encode_unicode::CharExt;
|
||||
// skip forward to the next non-identifier character
|
||||
let mut chomped = 0;
|
||||
while let Ok((ch, width)) = char::from_utf8_slice_start(&state.bytes[chomped..]) {
|
||||
while let Ok((ch, width)) = char::from_utf8_slice_start(&bytes[chomped..]) {
|
||||
// We can't use ch.is_alphanumeric() here because that passes for
|
||||
// things that are "numeric" but not ASCII digits, like `¾`
|
||||
if ch == '.' || ch == '_' || ch.is_alphabetic() || ch.is_ascii_digit() {
|
||||
|
@ -175,14 +186,7 @@ fn malformed_identifier<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
let delta = initial_bytes.len() - state.bytes.len();
|
||||
let parsed_str = unsafe { std::str::from_utf8_unchecked(&initial_bytes[..chomped + delta]) };
|
||||
|
||||
state = state.advance_without_indenting_ee(chomped, |r, c| {
|
||||
EExpr::Space(crate::parser::BadInputError::LineTooLong, r, c)
|
||||
})?;
|
||||
|
||||
Ok((MadeProgress, Ident::Malformed(parsed_str, problem), state))
|
||||
chomped
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
|
@ -447,6 +451,12 @@ fn chomp_concrete_type<'a>(buffer: &'a [u8]) -> Result<(&'a str, &'a str, usize)
|
|||
Err(_) => Err(MadeProgress),
|
||||
Ok(rest) => {
|
||||
let width = first.len() + rest as usize;
|
||||
|
||||
// we must explicitly check here for a trailing `.`
|
||||
if let Some(b'.') = buffer.get(width) {
|
||||
return Err(MadeProgress);
|
||||
}
|
||||
|
||||
let slice = &buffer[..width];
|
||||
|
||||
match slice.iter().rev().position(|c| *c == b'.') {
|
||||
|
|
|
@ -526,6 +526,7 @@ pub enum EExpr<'a> {
|
|||
BadOperator(&'a [u8], Row, Col),
|
||||
|
||||
Def(&'a SyntaxError<'a>, Row, Col),
|
||||
DefMissingFinalExpr(Row, Col),
|
||||
Type(Type<'a>, Row, Col),
|
||||
Pattern(&'a EPattern<'a>, Row, Col),
|
||||
IndentDefBody(Row, Col),
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::ast;
|
||||
use crate::expr::expr;
|
||||
use crate::module::module_defs;
|
||||
use crate::parser::{loc, Parser, State, SyntaxError};
|
||||
use crate::parser::{Parser, State, SyntaxError};
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_region::all::Located;
|
||||
|
|
|
@ -518,12 +518,34 @@ fn parse_concrete_type<'a>(
|
|||
arena: &'a Bump,
|
||||
state: State<'a>,
|
||||
) -> ParseResult<'a, TypeAnnotation<'a>, TApply> {
|
||||
let (_, (module_name, type_name), state) =
|
||||
specialize(|_, r, c| TApply::End(r, c), crate::ident::concrete_type())
|
||||
.parse(arena, state)?;
|
||||
let answer = TypeAnnotation::Apply(module_name, type_name, &[]);
|
||||
let initial_bytes = state.bytes;
|
||||
|
||||
Ok((MadeProgress, answer, state))
|
||||
match crate::ident::concrete_type().parse(arena, state) {
|
||||
Ok((_, (module_name, type_name), state)) => {
|
||||
let answer = TypeAnnotation::Apply(module_name, type_name, &[]);
|
||||
|
||||
Ok((MadeProgress, answer, state))
|
||||
}
|
||||
Err((NoProgress, _, state)) => {
|
||||
Err((NoProgress, TApply::End(state.line, state.column), state))
|
||||
}
|
||||
Err((MadeProgress, _, mut state)) => {
|
||||
// we made some progress, but ultimately failed.
|
||||
// that means a malformed type name
|
||||
let chomped = crate::ident::chomp_malformed(state.bytes);
|
||||
let delta = initial_bytes.len() - state.bytes.len();
|
||||
let parsed_str =
|
||||
unsafe { std::str::from_utf8_unchecked(&initial_bytes[..chomped + delta]) };
|
||||
|
||||
state = state.advance_without_indenting_ee(chomped, |r, c| {
|
||||
TApply::Space(crate::parser::BadInputError::LineTooLong, r, c)
|
||||
})?;
|
||||
|
||||
dbg!(&state);
|
||||
|
||||
Ok((MadeProgress, TypeAnnotation::Malformed(parsed_str), state))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_type_variable<'a>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue