Skip to content
Snippets Groups Projects
Select Git revision
  • 97ec6d48c990cfa202717d15adf0433540347d04
  • master default protected
  • home_exam
  • wip
4 results

parse.rs

Blame
  • parse.rs 10.34 KiB
    extern crate nom;
    
    use std::iter::Peekable;
    use std::slice::Iter;
    
    use nom::{
        branch::alt,
        bytes::complete::tag,
        character::complete::{
            alpha1, alphanumeric0, char, digit1, multispace0, multispace1,
        },
        combinator::{cut, map, opt},
        error::ParseError,
        multi::{many1, separated_list},
        sequence::{delimited, preceded, terminated, tuple},
        IResult,
    };
    
    use crate::ast::{
        Block, Cmd, Expr, Func, Item, Mutability, Op, Prog, Span, SpanCmd,
        SpanExpr, SpanId, Type,
    };
    
    pub fn parse_i32(i: Span) -> IResult<Span, (Span, i32)> {
        map(digit1, |digit_str: Span| {
            (digit_str, digit_str.fragment.parse::<i32>().unwrap())
        })(i)
    }
    
    fn parse_op(i: Span) -> IResult<Span, (Span, Op)> {
        alt((
            map(tag("=="), |s| (s, Op::Eq)),
            map(tag("!="), |s| (s, Op::Neq)),
            map(tag("**"), |s| (s, Op::Pow)),
            map(tag("&&"), |s| (s, Op::And)),
            map(tag("||"), |s| (s, Op::Or)),
            map(tag("+"), |s| (s, Op::Add)),
            map(tag("-"), |s| (s, Op::Sub)),
            map(tag("*"), |s| (s, Op::Mul)),
            map(tag("/"), |s| (s, Op::Div)),
            map(tag("!"), |s| (s, Op::Not)),
        ))(i)
    }
    
    #[derive(Debug, Clone, PartialEq)]
    pub enum Token<'a> {
        Num(i32),
        Bool(bool),
        Id(String),
        Call(String, Vec<(Span<'a>, Vec<SpanToken<'a>>)>),
        Par(Vec<SpanToken<'a>>),
        Op(Op),
    }
    
    type SpanToken<'a> = (Span<'a>, Token<'a>);
    
    pub fn parse_id(i: Span) -> IResult<Span, Span> {
        // an identifier needs to start with one or more alphas (head)
        // followed by zero or more alphanumerics (tail)
        map(
            preceded(multispace0, tuple((alpha1, alphanumeric0, tag("")))),
            // we concatenate the head and tail into a single String
            |(_, _, end): (Span, Span, Span)| {
                let mut res = i;
                res.fragment = &i.fragment[..(end.offset - i.offset)];
                res
            },
        )(i)
    }