jq
expression parser, so you can pipe some command that produces JSON into it: curl some.api |< .jq.expression[].etc >| echo
so what I'm trying to figure out is essentially some rules around once you hit a |<
the only valid two things are 1. capture any text and 2. capture >|
as the "closing" tag
terminated
though
|<
differently
x |< y |<
which breaks my grammar rules, I want to enforce that once you hit a |<
the only possible way of closing that expression is with a >|
.+
(in regex lingo)
|<
, and one for the inside of your |<>|
brace boi
take_until1
right?
take_until1
only works on individual bytes or you can pass it not(tag("|<"))
|<
from the input stream
fn parse_tuple(i: &str) -> IResult<&str, AST> {
let (i, _) = multispace0(i)?;
let (i, _) = tag("|<")(i)?;
let (i, elements) = fold_many1(
tuple((multispace0, parse_bit_of_syntax, multispace0)),
Vec::new(),
|mut acc, (_, thing, _)| {
acc.push(Box::new(thing));
acc
},
)(i)?;
let (i, _) = tuple((multispace0, tag(">|")))(i)?;
Ok((i, AST::Tuple { inners: elements }))
}
delimited
)
alt
notAfterString
I found it hard to implement with nom
. Was curious if someone might be familiar with pandoc/Haskell or be able to point me in a general direction about the appropriate way to handle emphasis and strong inline?
a * foo bar*
should be parse as <p>a * foo bar*</p>
but not <p>a <em>foo bar</em></p>
I'm new to nom and have also been attempting to build a markdown parser via nom as well. I'm sure the following is not entirely correct or commonmark compliant as I'm still attempting to learn but my first initial crack at it was
fn italics(i: &str) -> IResult<&str, String> {
let (i, _) = tag("*")(i)?;
let (i, _) = not(tag(" "))(i)?;
map(
terminated(many0(is_not("*")), tag("*")),
|vec| vec.join(""),
)(i)
}
Based on a few tests this appears to correctly parses *foo bar*
while fails on * foo bar*
Would still need a paragraph parser to parse the entire a * foo bar*
I hope this helps in some way. I'm sure someone more experienced can provide a more robust or correct parser. Would benefit me as well :)
take_until
for line 5 instead of many0
too
terminated(many0(is_not("*")), tag("*")),
) is usually frowned upon and rarely what you want for languages which can 'nest' features/syntax in a tree. In this case, you want to recurse back to some parser instead of consuming the bytes.
<geometry>
, but an array of geometry (ie: [4]<geometry>
) is also valid. To parse this, I have a nom parser which matches and parses the [4] thing, but then recurses to get the nested parse fragment.
use nom_parser_derive::*;
use nom_parser::Parsable;
use nom_parser::ParseResult;
use nom::combinator::{opt};
use nom::sequence::{tuple};
use nom::bytes::complete::{tag};
use nom::character::complete::{ digit1};
#[derive(Parser,PartialEq,Clone,Debug)]
pub enum BinaryExpression{
#[nom(tuple(field(0),tag(" + "),field(1)))]
Add(Number,Number),
#[nom(tuple(field(0),tag(" - "),field(1)))]
Subtract(Number,Number),
#[nom(tuple(field(0),tag(" * "),field(1)))]
Multiply(Number,Number),
#[nom(tuple(field(0),tag(" / "),field(1)))]
Divide(Number,Number)
}
impl BinaryExpression{
pub fn apply(&self)->Number{
match self {
Self::Add(one,two)=>{
return Number(one.0+two.0)
},
Self::Subtract(one,two)=>{
return Number(one.0-two.0)
},
Self::Multiply(one,two)=>{
return Number(one.0*two.0)
},
Self::Divide(one,two)=>{
return Number(one.0/two.0)
}
}
}
}
#[derive(Parser,PartialEq,Clone,Debug)]
pub struct Number(#[nom(func(parse_isize))]isize);
fn parse_isize<'a>(input:&'a str) ->ParseResult<'a,isize>{
let mut num = tuple((opt(tag("-")),digit1));
let (i,(sign,nums)) = num(input)?;
let str_num=format!("{}",nums);
let f_num=str_num.parse::<isize>().unwrap();
if let Some(_)=sign{
Ok((i,(f_num * -1)))
} else {
Ok((i,f_num))
}
}
fn main() {
let (_,expr) = BinaryExpression::parse("1 + 2").unwrap();
assert_eq!(expr,BinaryExpression::Add(Number(1),Number(2)));
assert_eq!(expr.apply(),Number(3));
let (_,expr) = BinaryExpression::parse("1 - 2").unwrap();
assert_eq!(expr,BinaryExpression::Subtract(Number(1),Number(2)));
assert_eq!(expr.apply(),Number(-1));
let (_,expr) = BinaryExpression::parse("4 * 2").unwrap();
assert_eq!(expr,BinaryExpression::Multiply(Number(4),Number(2)));
assert_eq!(expr.apply(),Number(8));
let (_,expr) = BinaryExpression::parse("4 / 3").unwrap();
assert_eq!(expr,BinaryExpression::Divide(Number(4),Number(3)));
assert_eq!(expr.apply(),Number(1));
}
use nom_parser_derive::*;
use nom_parser::Parsable;
use nom_parser::ParseResult;
use nom::sequence::{tuple};
use nom::branch::alt;
use nom::character::complete::{alpha1, alphanumeric1};
use nom::multi::many0;
use nom::bytes::complete::tag;
#[derive(Parser,PartialEq,Debug,Clone)]
#[nom(tuple(tag("fn"),field(identifier),tag("("),field(args),tag(")"),tag("{"),field(statements),tag("}")))]
pub struct Function{
identifier:Identifier,
#[nom(separated_list0(tag(","),field))]
args:Vec<Argument>,
#[nom(many0(terminated(field,tag(";"))))]
statements:Vec<Statement>
}
#[derive(Parser,PartialEq,Debug,Clone)]
#[nom(tuple(field(name),field(field_type)))]
pub struct Argument{
name:Identifier,
#[nom(opt(tuple(tag(":"),field)))]
field_type:Option<Type>
}
#[derive(Parser,PartialEq,Debug,Clone)]
pub enum Statement{
#[nom(tag("Hello"))]
Hello,
#[nom(tag("World"))]
World
}
#[derive(Parser,PartialEq,Debug,Clone)]
pub struct Identifier(#[nom(func(ident))]String);
pub fn ident<'a>(input: &'a str) -> ParseResult<'a,String> {
nom::combinator::map(tuple((
alt((alpha1,tag("_"))),
many0(alphanumeric1))),|(a,b)|{format!("{}{}",a,b.join(""))})
(input)
}
#[derive(Parser,PartialEq,Debug,Clone)]
pub enum Type{
#[nom(tag("Int"))]
Int,
#[nom(tag("String"))]
String
}
fn main() {
let (_,val) = Function::parse("fn hello( a : String , b ){ Hello; World; } ").unwrap();
assert_eq!(val,Function{
identifier:Identifier("hello".to_string()),
args:vec![Argument{
name:Identifier("a".to_string()),
field_type:Some(Type::String)
},
Argument{
name:Identifier("b".to_string()),
field_type:None
}
],
statements:vec![Statement::Hello,Statement::World]
});
}
Simple Function Parser
@CSUwangj , while doing some research I stumbled upon this. https://github.com/chipsenkbeil/vimwiki-rs. I thought you might find it helpful
thanks! I'll check it