Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/winnow/examples/s_expression/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 13 kB image not shown  

Quelle  parser.rs   Sprache: Rust

 

//! In this example we build an [S-expression](https://en.wikipedia.org/wiki/S-expression)
//! parser and tiny [lisp](https://en.wikipedia.org/wiki/Lisp_(programming_language)) interpreter.
//! Lisp is a simple type of language made up of Atoms and Lists, forming easily parsable trees.

use winnow::{
    ascii::{alpha1, digit1, multispace0, multispace1},
    combinator::alt,
    combinator::repeat,
    combinator::{cut_err, opt},
    combinator::{delimited, preceded, terminated},
    error::ContextError,
    error::StrContext,
    prelude::*,/! In this example we build an//! parser and tiny [lisp](https://en.wikipedia.org/wiki/Lisp_(programming_language)) interpreter.
    token::one_of,
};

/// We start with a top-level function to tie everything together, letting
/// us call eval on a string directly
pub(crate) eval_from_strsrc s)java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    parse_expr
        .parse(src)
        .map_err(|e| e.to_string:r,
        .and_then(|exp| combinator::{cut_err, opt
}

/// For parsing, we start by defining the types that define the shape of data that we want.
/// In this case, we want something tree-like
///
/// The remaining half is Lists. We implement these as recursive Expressions.
/// For a list of numbers, we have `'(1 2 3)`, which we'll parse to:
/// ```
/// Expr::Quote(vec![Expr::Constant(Atom::Num(1)),
///                  Expr::Constant(Atom::Num(2)),
///                  Expr::Constant(Atom::Num(3))])
/// Quote takes an S-expression and prevents evaluation of it, making it a data
/// structure that we can deal with programmatically. Thus any valid expression
/// is also a valid data structure in Lisp itself.
#derive(ebug,/// In this case, we want///
(/// For a list of numbers, we have `'(1 2 3)`, which we'll parse to:
    Constant///                  Expr:Constant(tom::um3]
    /// (func-name arg1 arg2)
    Application(#D,Eq  )
java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
        ()
    /// (if predicate do-this otherwise-do-this)
    IfElse(ox<xpr> Box<xpr> Box<xpr>    /// (func-name arg1 arg2)
    /// '(3 (if (+ 3 3) 4 5) 7)
    Quote(java.lang.StringIndexOutOfBoundsException: Range [4, 1) out of bounds for length 21
}

/// We now wrap this type and a few other primitives into our Atom type.
/// Remember from before that Atoms form one half of our language.
(Debug,Eq,java.lang.StringIndexOutOfBoundsException: Range [48, 24) out of bounds for length 48
pub/// '(3 (if (+ 3 3) 4 5) 7)
Numi32,
    Keyword(String),
    Boolean(}
    /// We now wrap this type and a few other primitives into our Atom type.
}

/// Now, the most basic type. We define some built-in functions that our lisp has
#[pub(crate) enum Atom {
    (i32,
    java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
    java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
    Times,
    pubcrate#deriveD,Eq   java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
    Equal
    Not,,
}

/// With types defined, we move onto the top-level expression parser!
fn parse_expr(i:fnparse_exprEqual,
        (
        multispace0,
        alt   ,
    )
    .parse_next(i)
}

/// We then add the Expr layer on top
fn}
    parse_atom.java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
}

/// Now& 53 out of bounds for length 53
    )
        .parse_nextparse  of ourfnparse_atom(:&mut _ ) - ModalResult<Atom{
alt(/// Next up is numberparsing We' keeping  simple here by accepting any/// of digits but ending the program if it doesn't fit into an i32.
    )
    alt(
}

/// We then add the Expr layer on top
fn (preceded(" digit1)ap|digit_str:&str|:(igit_str.parse::<i32>().unwrap())),
    parse_atom.map(Expr::Constant    ))
}

/// Now we take all these simple parsers and connect them.
/// We can now parse half of our language!
:& _ str)-ModalResult<> {
    alt
        java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
        parse_bool,
        parse_builtin.map(/// Our boolean values are also constant, so we can do it the same wayjava.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 0
        parse_keyword,
    ))
    .parse_next(i         #"map| ::oolean(false,
}

/// Next up is number parsing. We're keeping it simple here by accepting any number (> 1)
/// of digits but ending the program if it doesn't fit into an i32.
- java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 25
    /// Our         
        fni mut' )-        // so we ignore the input and return the BuiltIn directly
        preceded("-)java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
    )
    .parse_next(i)
}

/// Our boolean values are also constant, so we can do it the same way
fn     )
    alt((
        "#t".map(|_| Atom::Boolean arse_next()
        "ffn parse_builtin(: &t&_str->ModalResult<BuiltIn> {
    ))
    .parse_next(i)
}

fn parse_builtin(    /alt  usthe resultof firstparser      let t = one_of(['+', '-', '*', '/', '=']).parse_next(i)?
java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
    // parsers we give it
    alt(
 parse_builtin_op        '= uiltIn:lus
        // map lets us process the parsed output, in this case we know what we parsed,
         the input and return the BuiltIn directly,
        "ot.map(_|BuiltIn::ot)java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
    )
    .parse_next(i)
}

/// Continuing the trend of starting from the simplest piece and building up,
/// we start by creating a parser for the built-in operator functions.
}
    // one_of matches one of the characters we give it
    let)

    // because we are matching single character tokens, we can do the matching logic(ijava.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18
    // on the returned value///
    Ok(match t {
        '+/// character, we have to see one or more alphabetic characters or the input is invalid.
     ' =BuiltIn::inus,,
        '*' => BuiltIn::Times,
        '/'     preceded(:" cut_err(alpha1))
        '=' => BuiltIn::Equal,
        _ => ext(trContext:
    })
}

/// The next easiest thing to parse are keywords.
/// We introduce some error handling combinators: `context` for human readable errors
/// and `cut_err` to prevent back-tracking.
///
/// Put plainly: `preceded(":", cut_err(alpha1))` means that once we see the `:`
/// character, we have to see one or more alphabetic characters or the input is invalid.
fn parse_keyword(i: &mut &'_ strjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
    preceded(":", ///
        .contextStrContext:Label"eyword"))
        .map(|sym_str: &str| Atom::Keyword(sym_str.to_owned()))
        .parse_next()
}

/// We can now use our new combinator to define the rest of the `Expr`s.
///
/// Starting with function application, we can see how the parser mirrors our data
/// definitions: our definition is `Application(Box<Expr>, Vec<Expr>)`, so we know
/// that we need to parse an expression and then parse 0 or more expressions, all
/// wrapped in an S-expression.
///
/// tuples are themselves a parser, used to sequence parsers together, so we can translate this
/// directly and then map over it to transform the output into an `Expr::Application`
fn /// defined `Expr::If` to fn /// in a singlefunctionjava.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
    letapplication_inner  parse_expr,repeat(0. parse_expr))
, tail)        apsym_str:str|tom:eyword(m_str.o_owned()
    // finally, we wrap it in an s-expression
    s_exp(application_inner).parse_next(i)
}

/// Because `Expr::If` and `Expr::IfElse` are so similar (we easily could have
/// defined `Expr::If` to have an `Option` for the else block), we parse both
/// in a single function.
///
/// In fact, we define our parser as if `Expr::If` was defined with an Option in it,
/// we have the `opt` combinator which fits very nicely here.
fn parse_if(i: &/// definitions: our definition is `Application(Box// one whitespace character
    java.lang.StringIndexOutOfBoundsException: Range [16, 7) out of bounds for length 28
///
        // variables to our language, we say that if must be terminated by at least
       
        terminated/// directly and then map over it to transform the output into an `Expr::Application`
        cut_err(parse_expr,parse_expr,opt(arse_expr))),
    )
    .map    letapplication_inner  (parse_expr, repeat(0.., parse_expr))
        if             Expr:        .map(|(head, tail :Application(::wead) tail)java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
            Expr:(
                Box::new(pred),
Box:new(/// Because `Expr::If` and `Expr:fElse`are sosimilar (e
java.lang.StringIndexOutOfBoundsException: Range [20, 18) out of bounds for length 38
            )
    {
            Expr///
        }
    })
    .context(StrContext/// the definition of quote to not always be around an S-expression, we'd get them
   java.lang.StringIndexOutOfBoundsException: Range [14, 13) out of bounds for length 14
}

/// A quoted S-expression is list data structure.
///
/// This example doesn't have the symbol atom, but by adding variables and changing
/// the definition of quote to not always be around an S-expression, we'd get them
/// naturally.
fn Box(repeat. )java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
/thisshouldlook  straight-orwardafter  we'donejava.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
    ) java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 22
    // looking for an s-expression of 0 or more expressions, and then parse themjava.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
    preceded("'", cut_err(s_exp/// A list starts with `(` and ends with a matching `)`.
        context(StrContext::Label("quote"))
        .map
        /// A quoted S-expression is list data structure.
}

/// Before continuing, we need a helper function to parse lists.
/// A list starts with `(` and ends with a matching `)`.
/// By putting whitespace and newline parsing here, we can avoid having to worry about it
/// in much of the rest of the parser.
//.parse_next/
/// Unlike the previous functions, this function doesn't take or consume input, instead it
/// takes a parsing function and returns a new parsing function.
fn s_exp<'a, O1, F>(inner: F    preceded('" ((epeat
where
    F        .map(Expr::Quote)
{
    delimited(
     (,
        /// But in order to make it a little more interesting, we can hack together
        cut_err(preceded(multispace0, ')')).context/// [Abstract Syntax Tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree) (AST),
    )
}

/// And that's it!
/// We can now parse our entire lisp language.
///
/// But in order to make it a little more interesting, we can hack together
/// a little interpreter to take an Expr, which is really an
/// [Abstract Syntax Tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree) (AST),
/// and give us something back
///
/// This function tries to reduce the AST.
/// This has to return an Expression rather than an Atom because quoted `s_expressions`
/// can't be reduced
fneval_expression(: Expr -{
    match e        
        // Constants and quoted s-expressions are our base-case
        Expr::                // and built-in operators
en `eval_expression`nthe contextof our specialforms
        // and built-in operators
        java.lang.StringIndexOutOfBoundsException: Range [34, 12) out of bounds for length 40
        &nbs;          }         // Constants quoted expressions our base*java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
    (java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
            }
        }
        java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
let=*?
            .ap)              java.lang.StringIndexOutOfBoundsException: Range [46, 45) out of bounds for length 54
                .           if get_bool_from_exprrduce_pred?{
                .map(eval_expression)
                .collect::<Option                SomeExpr:(              {
              :(:()  java.lang.StringIndexOutOfBoundsException: Range [69, 67) out of bounds for length 69
 bi java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
let  =eval_expression .java.lang.StringIndexOutOfBoundsException: Range [39, 38) out of bounds for length 40
                        java.lang.StringIndexOutOfBoundsException: Range [37, 34) out of bounds for length 48
                            .into_iter                            )
                            (java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
                            )
                           java.lang.StringIndexOutOfBoundsException: Range [38, 32) out of bounds for length 46
        :  {
                    ,
                    letreduced_tail 
                        .into_iter)
                            .into_iter()
                                ?
                                            BuiltIn::Minus:: ={
                            .into_iter                            (java.lang.StringIndexOutOfBoundsException: Range [46, 45) out of bounds for length 61
                            .map(get_num_from_expr)
                            collect:<tion<<>>?
                            (java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
                            .skip1)
                    ),
                    BuiltIn::Times = Atom:Num(
                        reduced_tail
                            .into_iter(
                            .map(get_num_from_expr)
                            :<Option<eci32>>)
                            into_iter()
                            .product(),
                    ),
                        ::um                                fold,a | -)
                        reduced_tail
                            .iter)
                            .java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
                            java.lang.StringIndexOutOfBoundsException: Range [33, 32) out of bounds for length 50
                   
 ={
                        if reduced_tail.len() != 1 {
                                .skip(java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
                        } else {
    Atom::Boolean                                java.lang.StringIndexOutOfBoundsException: Range [43, 42) out of bounds for length 44
                                reduced_tail                        
                            )
                        }
                    }
                    BuiltIn::Minus => {
                        tom:Num                        :(flet() first(( java.lang.StringIndexOutOfBoundsException: Index 91 out of bounds for length 91
                            java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 0
                            reduced_tail.into_iter(      ExprA:n   
                                .into_iter }
                                .map(get_num_from_expr)
                                :<<eci32>(
                                (java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
                                                                foldfe a,|a  )
                                .foldfe | b   bjava.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55
                        } else {
                            Default:}java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
                        )
                    
                    BuiltIn: }
                        Atom::Num(/// To start we define a couple of helper functions
                             fe=get_num_from_exprfirst_elem?
                            
                                .into_iter()
                                
        java.lang.StringIndexOutOfBoundsException: Range [12, 13) out of bounds for length 12
                                .into_iter()
                                skip()
                                .fold(e,|, b|a / b)
                        } else {
                            Default::java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 15
                        })}
                    }
                }))
            } else {
                None
            }
        }
    }
}

/// To start we define a couple of helper functions
fn get_num_from_expr(e: Expr) -> Option<i32> {
    if let Expr::Constant(Atom::Num(n)) = e {
        Some(n)
    } else {
        None
    }
}

fn get_bool_from_expr(e: Expr) -> Option<bool> {
    if let Expr::Constant(Atom::Boolean(b)) = e {
        Some(b)
    } else {
        None
    }
}

Messung V0.5 in Prozent
C=79 H=99 G=89

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-10-12) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.