diff --git a/schala-lang/language/src/parser.rs b/schala-lang/language/src/parser.rs index 8a4e234..b632e89 100644 --- a/schala-lang/language/src/parser.rs +++ b/schala-lang/language/src/parser.rs @@ -4,28 +4,45 @@ use std::rc::Rc; use std::str::FromStr; use nom::IResult; -use nom::character::complete::{one_of, space0}; -use nom::bytes::complete::{tag, take_while, take_until}; -use nom::combinator::{map, map_res, value, opt}; -use nom::multi::many1; -use nom::error::{ParseError, ErrorKind}; +use nom::character::complete::{one_of, space0, alphanumeric0}; +use nom::bytes::complete::{tag, take, take_while, take_until}; +use nom::combinator::{map, map_res, value, opt, verify}; +use nom::multi::{separated_list, many1, many0}; +//use nom::error::{ParseError, ErrorKind}; use nom::branch::alt; -use nom::sequence::delimited; +use nom::sequence::{pair, delimited}; use crate::ast::*; use crate::builtin::Builtin; -const OPERATOR_CHARS: &'static str = "~`!@#$%^&*-+=<>?/|"; +fn single_alphabetic_character(text: &str) -> IResult<&str, char> { + let p = verify(take(1usize), |s: &str| s.chars().nth(0).map(|c| c.is_alphabetic()).unwrap_or(false)); + map(p, |s: &str| s.chars().nth(0).unwrap())(text) +} +fn single_alphanumeric_character(text: &str) -> IResult<&str, char> { + let p = verify(take(1usize), |s: &str| s.chars().nth(0).map(|c| c.is_alphanumeric() || c == '_').unwrap_or(false)); + map(p, |s: &str| s.chars().nth(0).unwrap())(text) +} + +fn identifier(text: &str) -> IResult<&str, Rc> { + use nom::character::complete::char; + map(alt(( + pair(char('_'), many1(single_alphanumeric_character)), + pair(single_alphabetic_character, many0(single_alphanumeric_character)) + )), + |(first, rest): (char, Vec)| Rc::new(format!("{}{}", first, rest.into_iter().collect::())) + )(text) +} + +const OPERATOR_CHARS: &'static str = "~`!@#$%^&*-+=<>?/|"; fn parse_binop(input: &str) -> IResult<&str, BinOp> { - use nom::character::complete::one_of; let (rest, op): (_, Vec) = many1(one_of(OPERATOR_CHARS))(input)?; let sigil: String = op.into_iter().collect(); Ok((rest, BinOp::from_sigil(&sigil))) } - fn parse_bool_literal(input: &str) -> IResult<&str, ExpressionKind> { let p = alt(( value(true, tag("true")), @@ -79,7 +96,7 @@ fn parse_string_literal(text: &str) -> IResult<&str, ExpressionKind> { Ok((text, expr)) } -fn parse_literal(input: &str) -> IResult<&str, ExpressionKind> { +fn literal(input: &str) -> IResult<&str, ExpressionKind> { alt(( parse_string_literal, parse_hex_literal, @@ -100,11 +117,45 @@ fn prefix_op(input: &str) -> IResult<&str, PrefixOp> { map(p, |sigil| PrefixOp::from_str(&sigil.to_string()).unwrap())(input) } +fn primary_expr(text: &str) -> IResult<&str, ExpressionKind> { + // primary := literal | paren_expr | if_expr | for_expr | while_expr | identifier_expr | lambda_expr | anonymous_struct | list_expr + + alt(( + literal, + paren_expr, + ))(text) +} + +fn invocation_argument(text: &str) -> IResult<&str, InvocationArgument> { + use nom::character::complete::char; + alt(( + value(InvocationArgument::Ignored, pair(char('_'), alphanumeric0)), + map(expression_kind, |kind: ExpressionKind| InvocationArgument::Positional( + Expression { id: ItemId::new(0), kind, type_anno: None })) + //map(identifier, |id: Rc| + ))(text) +} + +fn call_expr(text: &str) -> IResult<&str, ExpressionKind> { + use nom::character::complete::char; + let (text, expr) = primary_expr(text)?; + let (text, call_part) = opt( + delimited(char('('), separated_list(char(','), invocation_argument), char(')')) + )(text)?; + let output = if let Some(arguments) = call_part { + let f = bx!(Expression { id: ItemId::new(0), kind: expr, type_anno: None }); + ExpressionKind::Call { f, arguments } + } else { + expr + }; + Ok((text, output)) +} + fn prefix_expr(text: &str) -> IResult<&str, ExpressionKind> { let (text, pfx) = delimited(space0, opt(prefix_op), space0)(text)?; let (text, result) = alt(( paren_expr, - parse_literal + literal, ))(text)?; match pfx { None => Ok((text, result)), @@ -145,6 +196,7 @@ fn expression_kind(input: &str) -> IResult<&str, ExpressionKind> { } pub fn perform_parsing(input: &str) -> Result { - let output = expression_kind(input); + //let output = expression_kind(input); + let output = identifier(input); Ok(format!("{:?}", output)) }