use lalrpop_util;
use crate::ast;
use crate::parser;
grammar<'err>(span: codespan::ByteSpan, errors: &'err mut Vec<lalrpop_util::ParseError<usize, Token<'input>, parser::Error>>);
extern {
type Error = parser::Error;
}
match {
r"(?x)
(
(?:0|[1-9]\d*)?(?:u8|u16|u32|u64) | # unsigned integral numbers
(?:-?(?:0|[1-9]\d*))?(?:i8|i16|i32|i64) | # signed integral numbers
(?:-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?)?(?:f32|f64) # fractional numbers
)" => NumberValue,
} else {
r"/\*(\*[^/]|[^*])*\*/" => Comment,
r"\p{XID_Start}\p{XID_Continue}*" => IdentifierName,
r":\p{XID_Start}\p{XID_Continue}*" => SymbolLabel,
r#""(?:[^"\\]|\\.)*""# => StringValue,
_
}
#[inline]
Comma0<A>: Vec<A> = {
<v:(<A> ",")*> <e: A?> => {
let mut v = v;
v.extend(e);
v
},
}
#[inline]
Comma1<A>: Vec<A> = {
<v:(<A> ",")+> <e: A?> => {
let mut v = v;
v.extend(e);
v
},
}
#[inline]
Semi0<A>: Vec<A> = {
<v:(<A> ";")*> <e: A> => {
let mut v = v;
v.push(e);
v
},
}
#[inline]
SemiRequired0<A>: Vec<A> = {
<(<A> ";")*> => <>,
}
pub Module: ast::Module<parser::Context> = {
<lo:@L> <ds:SemiRequired0<(Comment? <Definition>)>> <hi:@R> =>
ast::Module { context: parser::Context::new(ast::Kind::Module, span, lo, hi), variables: ds },
}
Definition: ast::Variable<parser::Context> = {
<lo:@L> <n:Identifier> "=" <i:Expression> <hi:@R> =>
ast::Variable { context: parser::Context::new(ast::Kind::Variable, span, lo, hi), name: n, initializer: i },
}
pub Expression = { <ExpressionBiOpOr> }
// Left-to-right evaluation
ExpressionBiOpOr: ast::Expression<parser::Context> = {
BiOp<ExpressionBiOpOr, BiOperatorOr, ExpressionBiOpXor> => ast::Expression::BiOp(<>),
ExpressionBiOpXor => <>,
}
// Left-to-right evaluation
ExpressionBiOpXor: ast::Expression<parser::Context> = {
BiOp<ExpressionBiOpXor, BiOperatorXor, ExpressionBiOpAnd> => ast::Expression::BiOp(<>),
ExpressionBiOpAnd => <>,
}
// Left-to-right evaluation
ExpressionBiOpAnd: ast::Expression<parser::Context> = {
BiOp<ExpressionBiOpAnd, BiOperatorAnd, ExpressionBiOpCmp> => ast::Expression::BiOp(<>),
ExpressionBiOpCmp => <>,
}
// No associativity; require parenthesis
ExpressionBiOpCmp: ast::Expression<parser::Context> = {
BiOp<ExpressionBiOpBOr, BiOperatorCmp, ExpressionBiOpBOr> => ast::Expression::BiOp(<>),
ExpressionBiOpBOr => <>,
}
// Left-to-right evaluation
ExpressionBiOpBOr: ast::Expression<parser::Context> = {
BiOp<ExpressionBiOpBOr, BiOperatorBOr, ExpressionBiOpBXor> => ast::Expression::BiOp(<>),
ExpressionBiOpBXor => <>,
}
// Left-to-right evaluation
ExpressionBiOpBXor: ast::Expression<parser::Context> = {
BiOp<ExpressionBiOpBXor, BiOperatorBXor, ExpressionBiOpBAnd> => ast::Expression::BiOp(<>),
ExpressionBiOpBAnd => <>,
}
// Left-to-right evaluation
ExpressionBiOpBAnd: ast::Expression<parser::Context> = {
BiOp<ExpressionBiOpBAnd, BiOperatorBAnd, ExpressionBiOpShift> => ast::Expression::BiOp(<>),
ExpressionBiOpShift => <>,
}
// Left-to-right evaluation
ExpressionBiOpShift: ast::Expression<parser::Context> = {
BiOp<ExpressionBiOpShift, BiOperatorShift, ExpressionBiOpSum> => ast::Expression::BiOp(<>),
ExpressionBiOpSum => <>,
}
// Left-to-right evaluation
ExpressionBiOpSum: ast::Expression<parser::Context> = {
BiOp<ExpressionBiOpSum, BiOperatorSum, ExpressionBiOpFactor> => ast::Expression::BiOp(<>),
ExpressionBiOpFactor => <>,
}
// Left-to-right evaluation
ExpressionBiOpFactor: ast::Expression<parser::Context> = {
BiOp<ExpressionBiOpFactor, BiOperatorFactor, ExpressionUnOp> => ast::Expression::BiOp(<>),
ExpressionUnOp => <>,
}
ExpressionUnOp: ast::Expression<parser::Context> = {
UnOp => ast::Expression::UnOp(<>),
ExpressionProjection => <>,
}
ExpressionProjection: ast::Expression<parser::Context> = {
Select => ast::Expression::Select(<>),
Apply => ast::Expression::Apply(<>),
ExpressionAtom => <>,
}
ExpressionAtom: ast::Expression<parser::Context> = {
Identifier => ast::Expression::Identifier(<>),
NumberLiteral => ast::Expression::NumberLiteral(<>),
StringLiteral => ast::Expression::StringLiteral(<>),
Symbol => ast::Expression::Symbol(<>),
Tuple => ast::Expression::Tuple(<>),
Record => ast::Expression::Record(<>),
Lambda => ast::Expression::Lambda(<>),
"(" <Expression> ")" => <>,
! => { errors.push(<>.error); ast::Expression::Unknown },
}
UnOperator: ast::UnOperator = {
"!" => ast::UnOperator::Not,
"~!" => ast::UnOperator::BNot,
"#^0" => ast::UnOperator::Cl0,
"#^1" => ast::UnOperator::Cl1,
"#^-" => ast::UnOperator::Cls,
"#$0" => ast::UnOperator::Ct0,
"#$1" => ast::UnOperator::Ct1,
"#0" => ast::UnOperator::C0,
"#1" => ast::UnOperator::C1,
"^/" => ast::UnOperator::Sqrt,
}
UnOp: ast::UnOp<parser::Context> = {
<lo:@L> <operator:UnOperator> <operand:ExpressionUnOp> <hi:@R> =>
ast::UnOp { context: parser::Context::new(ast::Kind::UnOp, span, lo, hi), operator, operand: Box::new(operand) },
}
#[inline]
BiOp<L, O, R>: ast::BiOp<parser::Context> = {
<lo:@L> <lhs:L> <operator:O> <rhs:R> <hi:@R> =>
ast::BiOp { context: parser::Context::new(ast::Kind::BiOp, span, lo, hi), lhs: Box::new(lhs), operator, rhs: Box::new(rhs) },
}
BiOperatorFactor: ast::BiOperator = {
"*" => ast::BiOperator::Mul,
"/" => ast::BiOperator::Div,
"%" => ast::BiOperator::Rem,
}
BiOperatorSum: ast::BiOperator = {
"+" => ast::BiOperator::Add,
"-" => ast::BiOperator::Sub,
}
BiOperatorShift: ast::BiOperator = {
"<-<" => ast::BiOperator::RotL,
">->" => ast::BiOperator::RotR,
"<<" => ast::BiOperator::ShL,
">>" => ast::BiOperator::ShR,
}
BiOperatorBAnd: ast::BiOperator = {
"~&" => ast::BiOperator::BAnd,
"~&!" => ast::BiOperator::BAndNot,
}
BiOperatorBOr: ast::BiOperator = {
"~|" => ast::BiOperator::BOr,
"~|!" => ast::BiOperator::BOrNot,
}
BiOperatorBXor: ast::BiOperator = {
"~^" => ast::BiOperator::BXor,
"~^!" => ast::BiOperator::BXorNot,
}
BiOperatorAnd: ast::BiOperator = {
"&" => ast::BiOperator::And,
"&!" => ast::BiOperator::AndNot,
}
BiOperatorOr: ast::BiOperator = {
"|" => ast::BiOperator::Or,
"|!" => ast::BiOperator::OrNot,
}
BiOperatorXor: ast::BiOperator = {
"^" => ast::BiOperator::Xor,
"^!" => ast::BiOperator::XorNot,
}
BiOperatorCmp: ast::BiOperator = {
"==" => ast::BiOperator::Eq,
"!=" => ast::BiOperator::Ne,
"<" => ast::BiOperator::Lt,
">=" => ast::BiOperator::Ge,
">" => ast::BiOperator::Gt,
"<=" => ast::BiOperator::Le,
"<=>" => ast::BiOperator::Cmp,
}
Identifier: ast::Identifier<parser::Context> = {
<lo:@L> <id:IdentifierName> <hi:@R> =>
ast::Identifier { context: parser::Context::new(ast::Kind::Identifier, span, lo, hi), value: id.into() },
}
Tuple: ast::Tuple<parser::Context> = {
<lo:@L> "(" ")" <hi:@R> =>
ast::Tuple { context: parser::Context::new(ast::Kind::Tuple, span, lo, hi), fields: vec![] },
<lo:@L> "(" <fs:Comma1<Expression>> ")" <hi:@R> =>
ast::Tuple { context: parser::Context::new(ast::Kind::Tuple, span, lo, hi), fields: fs },
}
Record: ast::Record<parser::Context> = {
<lo:@L> "{" <fs:Comma0<Field>> "}" <hi:@R> =>
ast::Record { context: parser::Context::new(ast::Kind::Record, span, lo, hi), fields: fs },
}
Field: (ast::Identifier<parser::Context>, ast::Expression<parser::Context>) = {
<Identifier> ":" <Expression> => (<>),
}
NumberLiteral: ast::NumberLiteral<parser::Context> = {
<lo:@L> <v:NumberValue> <hi:@R> =>
ast::NumberLiteral {
context: parser::Context::new(ast::Kind::NumberLiteral, span, lo, hi),
value: parser::util::parse_number_literal(span, lo, hi, v, errors),
},
}
StringLiteral: ast::StringLiteral<parser::Context> = {
<lo:@L> <v:StringValue> <hi:@R> =>
ast::StringLiteral { context: parser::Context::new(ast::Kind::StringLiteral, span, lo, hi), value: parser::util::parse_escaped_string(span, lo, hi, v, errors) },
}
Symbol: ast::Symbol<parser::Context> = {
<lo:@L> <label:SymbolLabel> <hi:@R> =>
ast::Symbol { context: parser::Context::new(ast::Kind::Symbol, span, lo, hi), label: (&label[1..]).to_owned() },
}
Lambda: ast::Lambda<parser::Context> = {
<lo:@L> "|" <params:Comma0<(Comment? <Parameter>)>> "|" <sig:Expression?> "{" <stmts:SemiRequired0<(Comment? <Statement>)>> <res:(Comment? <Expression>)> "}" <hi:@R> =>
ast::Lambda { context: parser::Context::new(ast::Kind::Lambda, span, lo, hi), parameters: params, signature: sig.map(Box::new), statements: stmts, result: Box::new(res) },
}
Statement: ast::Statement<parser::Context> = {
<Definition> => ast::Statement::Variable(<>),
<Expression> => ast::Statement::Expression(<>),
}
Select: ast::Select<parser::Context> = {
<lo:@L> <r:ExpressionProjection> "." <f:Identifier> <hi:@R> =>
ast::Select { context: parser::Context::new(ast::Kind::Select, span, lo, hi), record: Box::new(r), field: f },
}
Apply: ast::Apply<parser::Context> = {
<lo:@L> <e:ExpressionProjection> "(" <p:Comma0<Expression>> ")" <hi:@R> =>
ast::Apply { context: parser::Context::new(ast::Kind::Apply, span, lo, hi), function: Box::new(e), parameters: p },
}
Parameter: ast::Parameter<parser::Context> = {
<lo:@L> <name:Identifier> <signature:(":" <ExpressionAtom>)?> <hi:@R> =>
ast::Parameter { context: parser::Context::new(ast::Kind::Parameter, span, lo, hi), name, signature },
}