Positive version of assert and group functions w/ parsers
Grouping function in execution::data
This commit is contained in:
@ -140,8 +140,7 @@ AssertTree2: relabel::Tree = {
|
||||
"else" "{" <t2: AssertTree> "}" ";"? =>
|
||||
relabel::Tree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)),
|
||||
|
||||
"let" <v: AssertVariable> <q: AssertQualifier?> "=" <e: AssertExpression>
|
||||
";"
|
||||
"let" <v: AssertVariable> <q: AssertQualifier?> "=" <e: AssertExpression>";"
|
||||
=> relabel::Tree::Assignment(v, q, Box::new(e)),
|
||||
|
||||
"return" <e: AssertExpression> ";" =>
|
||||
|
||||
@ -1,13 +1,9 @@
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
use lalrpop_util::ParseError;
|
||||
|
||||
use assert::{relabel, grouping};
|
||||
use rsprocess::{set, reaction, process, environment, system, label};
|
||||
use rsprocess::element::IdType;
|
||||
use assert::grouping;
|
||||
use rsprocess::{set, label};
|
||||
use rsprocess::translator::Translator;
|
||||
use execution::presets;
|
||||
use rsprocess::graph;
|
||||
use crate::custom_error;
|
||||
|
||||
grammar(translator: &mut Translator);
|
||||
@ -23,7 +19,14 @@ extern {
|
||||
|
||||
// order
|
||||
match {
|
||||
"!",
|
||||
"!", "!=", "%", "&&", "'", "(", ")", "*", "+", ",", "-", "..", "/", ":",
|
||||
"::", ";", "<", "<=", "=", "==", ">", ">=", "AllInhibitors", "AllReactants",
|
||||
"AvailableEntities", "Context", "Entities", "Inhibitors",
|
||||
"InhibitorsPresent", "Products", "Reactants", "ReactantsAbsent",
|
||||
"SystemContext", "SystemEntities", "[", "\"", "]", "^", "^^", "edge",
|
||||
"else", "empty", "false", "for", "if", "in", "label", "length", "let",
|
||||
"neighbours", "not", "rand", "return", "source", "system", "target", "then",
|
||||
"toel", "tostr", "true", "{", "||", "}", "node",
|
||||
} else {
|
||||
r"[0-9]+" => NUMBER
|
||||
} else {
|
||||
@ -90,9 +93,9 @@ Separated_Empty<LP, T, C, RP>: Vec<T> = {
|
||||
// SetParser
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
pub Set: set::Set = {
|
||||
Set: set::Set = {
|
||||
<s: Separated_Empty<"{", Literal, ",", "}">> =>
|
||||
set::Set::from(t.into_iter().map(|t| translator.encode(t))
|
||||
set::Set::from(s.into_iter().map(|t| translator.encode(t))
|
||||
.collect::<Vec<_>>())
|
||||
};
|
||||
|
||||
@ -100,7 +103,7 @@ pub Set: set::Set = {
|
||||
// LabelParser
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
pub Label: label::Label = {
|
||||
Label: label::Label = {
|
||||
"["
|
||||
"Entities" ":" <e: Set> ","
|
||||
"Context" ":" <c: Set> ","
|
||||
@ -116,8 +119,8 @@ pub Label: label::Label = {
|
||||
// -----------------------------------------------------------------------------
|
||||
// GroupingParser
|
||||
// -----------------------------------------------------------------------------
|
||||
Group: Box<grouping::Assert> = {
|
||||
">" "node" "{" <f: GroupTree> "}" =>
|
||||
pub Group: Box<grouping::Assert> = {
|
||||
"node" "{" <f: GroupTree> "}" =>
|
||||
Box::new(grouping::Assert{tree: f}),
|
||||
};
|
||||
|
||||
@ -202,7 +205,6 @@ GroupTerm: grouping::Expression = {
|
||||
"(" <e: GroupExpression> ")" => e,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
GroupRange: grouping::Range = {
|
||||
"{" <e: GroupExpression> "}" =>
|
||||
grouping::Range::IterateOverSet(Box::new(e)),
|
||||
@ -210,13 +212,11 @@ GroupRange: grouping::Range = {
|
||||
grouping::Range::IterateInRange(Box::new(e1), Box::new(e2)),
|
||||
}
|
||||
|
||||
#[inline]
|
||||
GroupUnaryPrefix: grouping::Unary = {
|
||||
"not" => grouping::Unary::Not,
|
||||
"rand" => grouping::Unary::Rand,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
GroupUnarySuffix: grouping::Unary = {
|
||||
#[precedence(level="0")]
|
||||
"empty" => grouping::Unary::Empty,
|
||||
@ -228,7 +228,6 @@ GroupUnarySuffix: grouping::Unary = {
|
||||
<q: GroupQualifier> => grouping::Unary::Qualifier(q),
|
||||
}
|
||||
|
||||
#[inline]
|
||||
GroupQualifierRestricted: grouping::QualifierRestricted = {
|
||||
"Entities" => grouping::QualifierRestricted::Entities,
|
||||
"Context" => grouping::QualifierRestricted::Context,
|
||||
@ -239,32 +238,27 @@ GroupQualifierRestricted: grouping::QualifierRestricted = {
|
||||
"Products" => grouping::QualifierRestricted::Products,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
GroupQualifierLabel: grouping::QualifierLabel = {
|
||||
"AvailableEntities" => grouping::QualifierLabel::AvailableEntities,
|
||||
"AllReactants" => grouping::QualifierLabel::AllReactants,
|
||||
"AllInhibitors" => grouping::QualifierLabel::AllInhibitors,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
GroupQualifierSystem: grouping::QualifierSystem = {
|
||||
"SystemEntities" => grouping::QualifierSystem::Entities,
|
||||
"SystemContext" => grouping::QualifierSystem::Context,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
GroupQualifierEdge: grouping::QualifierEdge = {
|
||||
"source" => grouping::QualifierEdge::Source,
|
||||
"target" => grouping::QualifierEdge::Target,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
GroupQualifierNode: grouping::QualifierNode = {
|
||||
"neighbours" => grouping::QualifierNode::Neighbours,
|
||||
"system" => grouping::QualifierNode::System,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
GroupQualifier: grouping::Qualifier = {
|
||||
<q: GroupQualifierSystem> => grouping::Qualifier::System(q),
|
||||
<q: GroupQualifierLabel> => grouping::Qualifier::Label(q),
|
||||
@ -273,7 +267,6 @@ GroupQualifier: grouping::Qualifier = {
|
||||
<q: GroupQualifierNode> => grouping::Qualifier::Node(q),
|
||||
}
|
||||
|
||||
#[inline]
|
||||
GroupBinary: grouping::Binary = {
|
||||
"&&" => grouping::Binary::And,
|
||||
"||" => grouping::Binary::Or,
|
||||
@ -293,7 +286,6 @@ GroupBinary: grouping::Binary = {
|
||||
"::" => grouping::Binary::Concat,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
GroupBinaryPrefix: grouping::Binary = {
|
||||
"substr" => grouping::Binary::SubStr,
|
||||
"min" => grouping::Binary::Min,
|
||||
|
||||
@ -26,6 +26,39 @@ pub mod assert {
|
||||
include!(concat!(env!("OUT_DIR"), "/src/assert.rs"));
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::extra_unused_lifetimes)]
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
#[allow(clippy::let_unit_value)]
|
||||
#[allow(clippy::just_underscores_and_digits)]
|
||||
#[allow(clippy::uninlined_format_args)]
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub mod positive_assert {
|
||||
include!(concat!(env!("OUT_DIR"), "/src/positive_assert.rs"));
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::extra_unused_lifetimes)]
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
#[allow(clippy::let_unit_value)]
|
||||
#[allow(clippy::just_underscores_and_digits)]
|
||||
#[allow(clippy::uninlined_format_args)]
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub mod grouping {
|
||||
include!(concat!(env!("OUT_DIR"), "/src/grouping.rs"));
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::extra_unused_lifetimes)]
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
#[allow(clippy::let_unit_value)]
|
||||
#[allow(clippy::just_underscores_and_digits)]
|
||||
#[allow(clippy::uninlined_format_args)]
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub mod positive_grouping {
|
||||
include!(concat!(env!("OUT_DIR"), "/src/positive_grouping.rs"));
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::extra_unused_lifetimes)]
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
|
||||
297
grammar_separated/src/positive_assert.lalrpop
Normal file
297
grammar_separated/src/positive_assert.lalrpop
Normal file
@ -0,0 +1,297 @@
|
||||
use std::str::FromStr;
|
||||
use lalrpop_util::ParseError;
|
||||
|
||||
use assert::positive_relabel;
|
||||
use rsprocess::{set, label};
|
||||
use rsprocess::translator::Translator;
|
||||
use crate::custom_error;
|
||||
|
||||
grammar(translator: &mut Translator);
|
||||
|
||||
extern {
|
||||
type Error = custom_error::UserError;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// order
|
||||
match {
|
||||
"!", "!=", "%", "&&", "'", "(", ")", "*", "+", ",", "-", "..", "/", ":",
|
||||
"::", ";", "<", "<=", "=", "==", ">", ">=", "AllInhibitors", "AllReactants",
|
||||
"AvailableEntities", "Context", "Entities", "Inhibitors",
|
||||
"InhibitorsPresent", "Products", "Reactants", "ReactantsAbsent",
|
||||
"SystemContext", "SystemEntities", "[", "\"", "]", "^", "^^", "edge",
|
||||
"else", "empty", "false", "for", "if", "in", "label", "length", "let",
|
||||
"neighbours", "not", "rand", "return", "source", "system", "target", "then",
|
||||
"toel", "tostr", "true", "{", "||", "}",
|
||||
} else {
|
||||
r"[0-9]+" => NUMBER
|
||||
} else {
|
||||
r"([[:alpha:]])([[:word:]])*" => WORD
|
||||
// r"(\p{L}|\p{Emoji})(\p{L}|\p{Emoji}|\p{Dash}|\p{N})*" => WORD,
|
||||
} else {
|
||||
r#""[^"]+""# => PATH, // " <- ignore comment, its for the linter in emacs
|
||||
} else {
|
||||
_
|
||||
}
|
||||
|
||||
// matches words (letter followed by numbers, letters or _)
|
||||
Literal: String = {
|
||||
WORD => <>.into(),
|
||||
};
|
||||
|
||||
Num: i64 = {
|
||||
<sign: "-"?> <start: @L> <n: NUMBER> <end: @R> =>? {
|
||||
if sign.is_some() {
|
||||
i64::from_str(n)
|
||||
.map(|n| -n)
|
||||
.map_err(|_| ParseError::User {
|
||||
error: custom_error::UserError {
|
||||
token: (start, n.into(), end),
|
||||
error: custom_error::UserErrorTypes::NumberTooBigi64
|
||||
}
|
||||
})
|
||||
} else {
|
||||
i64::from_str(n)
|
||||
.map_err(|_| ParseError::User {
|
||||
error: custom_error::UserError {
|
||||
token: (start, n.into(), end),
|
||||
error: custom_error::UserErrorTypes::NumberTooBigi64
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// macro for matching sequence of patterns with C as separator
|
||||
Separated<T, C>: Vec<T> = {
|
||||
<mut v:(<T> C)+> <e:T?> => match e {
|
||||
None => v,
|
||||
Some(e) => {
|
||||
v.push(e);
|
||||
v
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Separated_Or<T, C>: Vec<T> = {
|
||||
<v: T> => vec![v],
|
||||
<v: Separated<T, C>> => v
|
||||
}
|
||||
|
||||
Separated_Empty<LP, T, C, RP>: Vec<T> = {
|
||||
LP RP => vec![],
|
||||
LP <v: T> RP => vec![v],
|
||||
LP <v: Separated<T, C>> RP => v
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// SetParser
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
PositiveSet: set::PositiveSet = {
|
||||
<s: Separated_Empty<"{", PositiveLiteral, ",", "}">> =>
|
||||
set::PositiveSet::from(s)
|
||||
};
|
||||
|
||||
PositiveLiteral: (rsprocess::element::IdType, rsprocess::element::IdState) = {
|
||||
"+" <t: Literal> => (translator.encode(t), rsprocess::element::IdState::Positive),
|
||||
"-" <t: Literal> => (translator.encode(t), rsprocess::element::IdState::Negative),
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// LabelParser
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Label: label::PositiveLabel = {
|
||||
"["
|
||||
"Entities" ":" <e: PositiveSet> ","
|
||||
"Context" ":" <c: PositiveSet> ","
|
||||
"Reactants" ":" <r: PositiveSet> ","
|
||||
"ReactantsAbsent" ":" <r_a: PositiveSet> ","
|
||||
"Inhibitors" ":" <i: PositiveSet> ","
|
||||
"InhibitorsPresent" ":" <i_p: PositiveSet> ","
|
||||
"Products" ":" <p: PositiveSet> ","?
|
||||
"]" => label::PositiveLabel::create(e, c, r, r_a, i, i_p, p)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// AssertParser
|
||||
// -----------------------------------------------------------------------------
|
||||
pub Assert: Box<positive_relabel::PositiveAssert> = {
|
||||
"label" "{" <f: AssertTree> "}" =>
|
||||
Box::new(positive_relabel::PositiveAssert{tree: f}),
|
||||
};
|
||||
|
||||
AssertTree: positive_relabel::PositiveTree = {
|
||||
<t1: AssertTree2> <t2: AssertTree> =>
|
||||
positive_relabel::PositiveTree::Concat(Box::new(t1), Box::new(t2)),
|
||||
<t: AssertTree2> => t,
|
||||
}
|
||||
|
||||
AssertTree2: positive_relabel::PositiveTree = {
|
||||
#[precedence(level="1")]
|
||||
"if" <e: AssertExpression>
|
||||
"then" "{" <t: AssertTree> "}" ";"? =>
|
||||
positive_relabel::PositiveTree::If(Box::new(e), Box::new(t)),
|
||||
|
||||
#[precedence(level="0")]
|
||||
"if" <e: AssertExpression>
|
||||
"then" "{" <t1: AssertTree> "}"
|
||||
"else" "{" <t2: AssertTree> "}" ";"? =>
|
||||
positive_relabel::PositiveTree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)),
|
||||
|
||||
"let" <v: AssertVariable> <q: AssertQualifier?> "=" <e: AssertExpression>";"
|
||||
=> positive_relabel::PositiveTree::Assignment(v, q, Box::new(e)),
|
||||
|
||||
"return" <e: AssertExpression> ";" =>
|
||||
positive_relabel::PositiveTree::Return(Box::new(e)),
|
||||
|
||||
"for" <v: AssertVariable> "in" <r: AssertRange> "{" <t: AssertTree> "}" ";"?
|
||||
=> positive_relabel::PositiveTree::For(v, r, Box::new(t)),
|
||||
}
|
||||
|
||||
AssertVariable: positive_relabel::PositiveVariable = {
|
||||
#[precedence(level="0")]
|
||||
"label" => positive_relabel::PositiveVariable::Special(positive_relabel::Special::Label),
|
||||
"edge" => positive_relabel::PositiveVariable::Special(positive_relabel::Special::Edge),
|
||||
#[precedence(level="1")]
|
||||
<v: Literal> => positive_relabel::PositiveVariable::Id(v),
|
||||
}
|
||||
|
||||
AssertExpression: positive_relabel::PositiveExpression = {
|
||||
#[precedence(level="100")]
|
||||
<unp: AssertUnaryPrefix> "(" <e: AssertExpression> ")" =>
|
||||
positive_relabel::PositiveExpression::Unary(unp, Box::new(e)),
|
||||
|
||||
#[precedence(level="50")]
|
||||
<e: AssertExpression> "." <uns: AssertUnarySuffix> =>
|
||||
positive_relabel::PositiveExpression::Unary(uns, Box::new(e)),
|
||||
|
||||
#[precedence(level="100")] #[assoc(side="left")]
|
||||
"(" <e1: AssertExpression> <b: AssertBinary> <e2: AssertExpression> ")" =>
|
||||
positive_relabel::PositiveExpression::Binary(b, Box::new(e1), Box::new(e2)),
|
||||
|
||||
#[precedence(level="100")]
|
||||
<b: AssertBinaryPrefix>
|
||||
"(" <e1: AssertExpression> "," <e2: AssertExpression> ")" =>
|
||||
positive_relabel::PositiveExpression::Binary(b, Box::new(e1), Box::new(e2)),
|
||||
|
||||
#[precedence(level="0")]
|
||||
<t: AssertTerm> => t,
|
||||
}
|
||||
|
||||
AssertTerm: positive_relabel::PositiveExpression = {
|
||||
"true" => positive_relabel::PositiveExpression::True,
|
||||
"false" => positive_relabel::PositiveExpression::False,
|
||||
|
||||
<v: AssertVariable> => positive_relabel::PositiveExpression::Var(v),
|
||||
|
||||
// If changing IntegerType in assert.rs, also change from Num to another
|
||||
// similar parser with different return type
|
||||
<i: Num> => positive_relabel::PositiveExpression::Integer(i),
|
||||
|
||||
<lab: Label> => positive_relabel::PositiveExpression::Label(Box::new(lab)),
|
||||
<set: PositiveSet> => positive_relabel::PositiveExpression::Set(set),
|
||||
"'" <el: PositiveLiteral> "'" =>
|
||||
positive_relabel::PositiveExpression::PositiveElement(el.into()),
|
||||
|
||||
// strings
|
||||
PATH => positive_relabel::PositiveExpression::String(<>.trim_end_matches("\"")
|
||||
.trim_start_matches("\"")
|
||||
.to_string()),
|
||||
|
||||
// allow arbitrary parenthesis
|
||||
"(" <e: AssertExpression> ")" => e,
|
||||
}
|
||||
|
||||
AssertRange: positive_relabel::PositiveRange = {
|
||||
"{" <e: AssertExpression> "}" =>
|
||||
positive_relabel::PositiveRange::IterateOverSet(Box::new(e)),
|
||||
"{" <e1: AssertExpression> ".." <e2: AssertExpression> "}" =>
|
||||
positive_relabel::PositiveRange::IterateInRange(Box::new(e1), Box::new(e2)),
|
||||
}
|
||||
|
||||
AssertUnaryPrefix: positive_relabel::PositiveUnary = {
|
||||
"not" => positive_relabel::PositiveUnary::Not,
|
||||
"rand" => positive_relabel::PositiveUnary::Rand,
|
||||
}
|
||||
|
||||
AssertUnarySuffix: positive_relabel::PositiveUnary = {
|
||||
#[precedence(level="0")]
|
||||
"empty" => positive_relabel::PositiveUnary::Empty,
|
||||
"length" => positive_relabel::PositiveUnary::Length,
|
||||
"tostr" => positive_relabel::PositiveUnary::ToStr,
|
||||
"toel" => positive_relabel::PositiveUnary::ToEl,
|
||||
|
||||
#[precedence(level="1")]
|
||||
<q: AssertQualifier> => positive_relabel::PositiveUnary::Qualifier(q),
|
||||
}
|
||||
|
||||
AssertQualifierRestricted: positive_relabel::QualifierRestricted = {
|
||||
"Entities" => positive_relabel::QualifierRestricted::Entities,
|
||||
"Context" => positive_relabel::QualifierRestricted::Context,
|
||||
"Reactants" => positive_relabel::QualifierRestricted::Reactants,
|
||||
"ReactantsAbsent" => positive_relabel::QualifierRestricted::ReactantsAbsent,
|
||||
"Inhibitors" => positive_relabel::QualifierRestricted::Inhibitors,
|
||||
"InhibitorsPresent" => positive_relabel::QualifierRestricted::InhibitorsPresent,
|
||||
"Products" => positive_relabel::QualifierRestricted::Products,
|
||||
}
|
||||
|
||||
AssertQualifierLabel: positive_relabel::QualifierLabel = {
|
||||
"AvailableEntities" => positive_relabel::QualifierLabel::AvailableEntities,
|
||||
"AllReactants" => positive_relabel::QualifierLabel::AllReactants,
|
||||
"AllInhibitors" => positive_relabel::QualifierLabel::AllInhibitors,
|
||||
}
|
||||
|
||||
AssertQualifierSystem: positive_relabel::QualifierSystem = {
|
||||
"SystemEntities" => positive_relabel::QualifierSystem::Entities,
|
||||
"SystemContext" => positive_relabel::QualifierSystem::Context,
|
||||
}
|
||||
|
||||
AssertQualifierEdge: positive_relabel::QualifierEdge = {
|
||||
"source" => positive_relabel::QualifierEdge::Source,
|
||||
"target" => positive_relabel::QualifierEdge::Target,
|
||||
}
|
||||
|
||||
AssertQualifierNode: positive_relabel::QualifierNode = {
|
||||
"neighbours" => positive_relabel::QualifierNode::Neighbours,
|
||||
"system" => positive_relabel::QualifierNode::System,
|
||||
}
|
||||
|
||||
AssertQualifier: positive_relabel::PositiveQualifier = {
|
||||
<q: AssertQualifierSystem> => positive_relabel::PositiveQualifier::System(q),
|
||||
<q: AssertQualifierLabel> => positive_relabel::PositiveQualifier::Label(q),
|
||||
<q: AssertQualifierRestricted> => positive_relabel::PositiveQualifier::Restricted(q),
|
||||
<q: AssertQualifierEdge> => positive_relabel::PositiveQualifier::Edge(q),
|
||||
<q: AssertQualifierNode> => positive_relabel::PositiveQualifier::Node(q),
|
||||
}
|
||||
|
||||
AssertBinary: positive_relabel::PositiveBinary = {
|
||||
"&&" => positive_relabel::PositiveBinary::And,
|
||||
"||" => positive_relabel::PositiveBinary::Or,
|
||||
"^^" => positive_relabel::PositiveBinary::Xor,
|
||||
"<" => positive_relabel::PositiveBinary::Less,
|
||||
"<=" => positive_relabel::PositiveBinary::LessEq,
|
||||
">" => positive_relabel::PositiveBinary::More,
|
||||
">=" => positive_relabel::PositiveBinary::MoreEq,
|
||||
"==" => positive_relabel::PositiveBinary::Eq,
|
||||
"!=" => positive_relabel::PositiveBinary::NotEq,
|
||||
"+" => positive_relabel::PositiveBinary::Plus,
|
||||
"-" => positive_relabel::PositiveBinary::Minus,
|
||||
"*" => positive_relabel::PositiveBinary::Times,
|
||||
"^" => positive_relabel::PositiveBinary::Exponential,
|
||||
"/" => positive_relabel::PositiveBinary::Quotient,
|
||||
"%" => positive_relabel::PositiveBinary::Reminder,
|
||||
"::" => positive_relabel::PositiveBinary::Concat,
|
||||
}
|
||||
|
||||
AssertBinaryPrefix: positive_relabel::PositiveBinary = {
|
||||
"substr" => positive_relabel::PositiveBinary::SubStr,
|
||||
"min" => positive_relabel::PositiveBinary::Min,
|
||||
"max" => positive_relabel::PositiveBinary::Max,
|
||||
"commonsubstr" => positive_relabel::PositiveBinary::CommonSubStr,
|
||||
}
|
||||
298
grammar_separated/src/positive_grouping.lalrpop
Normal file
298
grammar_separated/src/positive_grouping.lalrpop
Normal file
@ -0,0 +1,298 @@
|
||||
use std::str::FromStr;
|
||||
use lalrpop_util::ParseError;
|
||||
|
||||
use assert::positive_grouping;
|
||||
use rsprocess::{set, label};
|
||||
use rsprocess::translator::Translator;
|
||||
use crate::custom_error;
|
||||
|
||||
grammar(translator: &mut Translator);
|
||||
|
||||
extern {
|
||||
type Error = custom_error::UserError;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// order
|
||||
match {
|
||||
"!", "!=", "%", "&&", "'", "(", ")", "*", "+", ",", "-", "..", "/", ":",
|
||||
"::", ";", "<", "<=", "=", "==", ">", ">=", "AllInhibitors", "AllReactants",
|
||||
"AvailableEntities", "Context", "Entities", "Inhibitors",
|
||||
"InhibitorsPresent", "Products", "Reactants", "ReactantsAbsent",
|
||||
"SystemContext", "SystemEntities", "[", "\"", "]", "^", "^^", "edge",
|
||||
"else", "empty", "false", "for", "if", "in", "label", "length", "let",
|
||||
"neighbours", "not", "rand", "return", "source", "system", "target", "then",
|
||||
"toel", "tostr", "true", "{", "||", "}", "node",
|
||||
} else {
|
||||
r"[0-9]+" => NUMBER
|
||||
} else {
|
||||
r"([[:alpha:]])([[:word:]])*" => WORD
|
||||
// r"(\p{L}|\p{Emoji})(\p{L}|\p{Emoji}|\p{Dash}|\p{N})*" => WORD,
|
||||
} else {
|
||||
r#""[^"]+""# => PATH, // " <- ignore comment, its for the linter in emacs
|
||||
} else {
|
||||
_
|
||||
}
|
||||
|
||||
// matches words (letter followed by numbers, letters or _)
|
||||
Literal: String = {
|
||||
WORD => <>.into(),
|
||||
};
|
||||
|
||||
Num: i64 = {
|
||||
<sign: "-"?> <start: @L> <n: NUMBER> <end: @R> =>? {
|
||||
if sign.is_some() {
|
||||
i64::from_str(n)
|
||||
.map(|n| -n)
|
||||
.map_err(|_| ParseError::User {
|
||||
error: custom_error::UserError {
|
||||
token: (start, n.into(), end),
|
||||
error: custom_error::UserErrorTypes::NumberTooBigi64
|
||||
}
|
||||
})
|
||||
} else {
|
||||
i64::from_str(n)
|
||||
.map_err(|_| ParseError::User {
|
||||
error: custom_error::UserError {
|
||||
token: (start, n.into(), end),
|
||||
error: custom_error::UserErrorTypes::NumberTooBigi64
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// macro for matching sequence of patterns with C as separator
|
||||
Separated<T, C>: Vec<T> = {
|
||||
<mut v:(<T> C)+> <e:T?> => match e {
|
||||
None => v,
|
||||
Some(e) => {
|
||||
v.push(e);
|
||||
v
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Separated_Or<T, C>: Vec<T> = {
|
||||
<v: T> => vec![v],
|
||||
<v: Separated<T, C>> => v
|
||||
}
|
||||
|
||||
Separated_Empty<LP, T, C, RP>: Vec<T> = {
|
||||
LP RP => vec![],
|
||||
LP <v: T> RP => vec![v],
|
||||
LP <v: Separated<T, C>> RP => v
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// SetParser
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
PositiveSet: set::PositiveSet = {
|
||||
<s: Separated_Empty<"{", PositiveLiteral, ",", "}">> =>
|
||||
set::PositiveSet::from(s)
|
||||
};
|
||||
|
||||
PositiveLiteral: (rsprocess::element::IdType, rsprocess::element::IdState) = {
|
||||
"+" <t: Literal> => (translator.encode(t), rsprocess::element::IdState::Positive),
|
||||
"-" <t: Literal> => (translator.encode(t), rsprocess::element::IdState::Negative),
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// LabelParser
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Label: label::PositiveLabel = {
|
||||
"["
|
||||
"Entities" ":" <e: PositiveSet> ","
|
||||
"Context" ":" <c: PositiveSet> ","
|
||||
"Reactants" ":" <r: PositiveSet> ","
|
||||
"ReactantsAbsent" ":" <r_a: PositiveSet> ","
|
||||
"Inhibitors" ":" <i: PositiveSet> ","
|
||||
"InhibitorsPresent" ":" <i_p: PositiveSet> ","
|
||||
"Products" ":" <p: PositiveSet> ","?
|
||||
"]" => label::PositiveLabel::create(e, c, r, r_a, i, i_p, p)
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// GroupingParser
|
||||
// -----------------------------------------------------------------------------
|
||||
pub Group: Box<positive_grouping::PositiveAssert> = {
|
||||
"node" "{" <f: GroupTree> "}" =>
|
||||
Box::new(positive_grouping::PositiveAssert{tree: f}),
|
||||
};
|
||||
|
||||
GroupTree: positive_grouping::PositiveTree = {
|
||||
<t1: GroupTree2> <t2: GroupTree> =>
|
||||
positive_grouping::PositiveTree::Concat(Box::new(t1), Box::new(t2)),
|
||||
<t: GroupTree2> => t,
|
||||
}
|
||||
|
||||
GroupTree2: positive_grouping::PositiveTree = {
|
||||
#[precedence(level="1")]
|
||||
"if" <e: GroupExpression>
|
||||
"then" "{" <t: GroupTree> "}" ";"? =>
|
||||
positive_grouping::PositiveTree::If(Box::new(e), Box::new(t)),
|
||||
|
||||
#[precedence(level="0")]
|
||||
"if" <e: GroupExpression>
|
||||
"then" "{" <t1: GroupTree> "}"
|
||||
"else" "{" <t2: GroupTree> "}" ";"? =>
|
||||
positive_grouping::PositiveTree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)),
|
||||
|
||||
"let" <v: GroupVariable> <q: GroupQualifier?> "=" <e: GroupExpression> ";"
|
||||
=> positive_grouping::PositiveTree::Assignment(v, q, Box::new(e)),
|
||||
|
||||
"return" <e: GroupExpression> ";" =>
|
||||
positive_grouping::PositiveTree::Return(Box::new(e)),
|
||||
|
||||
"for" <v: GroupVariable> "in" <r: GroupRange> "{" <t: GroupTree> "}" ";"? =>
|
||||
positive_grouping::PositiveTree::For(v, r, Box::new(t)),
|
||||
}
|
||||
|
||||
GroupVariable: positive_grouping::PositiveVariable = {
|
||||
#[precedence(level="0")]
|
||||
"entities" => positive_grouping::PositiveVariable::Special(positive_grouping::Special::Entities),
|
||||
"node" => positive_grouping::PositiveVariable::Special(positive_grouping::Special::Node),
|
||||
#[precedence(level="1")]
|
||||
<v: Literal> => positive_grouping::PositiveVariable::Id(v),
|
||||
}
|
||||
|
||||
GroupExpression: positive_grouping::PositiveExpression = {
|
||||
#[precedence(level="100")]
|
||||
<unp: GroupUnaryPrefix> "(" <e: GroupExpression> ")" =>
|
||||
positive_grouping::PositiveExpression::Unary(unp, Box::new(e)),
|
||||
|
||||
#[precedence(level="50")]
|
||||
<e: GroupExpression> "." <uns: GroupUnarySuffix> =>
|
||||
positive_grouping::PositiveExpression::Unary(uns, Box::new(e)),
|
||||
|
||||
#[precedence(level="100")] #[assoc(side="left")]
|
||||
<e1: GroupExpression> <b: GroupBinary> <e2: GroupExpression> =>
|
||||
positive_grouping::PositiveExpression::Binary(b, Box::new(e1), Box::new(e2)),
|
||||
|
||||
#[precedence(level="100")]
|
||||
<b: GroupBinaryPrefix>
|
||||
"(" <e1: GroupExpression> "," <e2: GroupExpression> ")" =>
|
||||
positive_grouping::PositiveExpression::Binary(b, Box::new(e1), Box::new(e2)),
|
||||
|
||||
#[precedence(level="0")]
|
||||
<t: GroupTerm> => t,
|
||||
}
|
||||
|
||||
GroupTerm: positive_grouping::PositiveExpression = {
|
||||
"true" => positive_grouping::PositiveExpression::True,
|
||||
"false" => positive_grouping::PositiveExpression::False,
|
||||
|
||||
<v: GroupVariable> => positive_grouping::PositiveExpression::Var(v),
|
||||
|
||||
// If changing IntegerType in assert.rs, also change from Num to another
|
||||
// similar parser with different return type
|
||||
<i: Num> => positive_grouping::PositiveExpression::Integer(i),
|
||||
|
||||
<lab: Label> => positive_grouping::PositiveExpression::Label(Box::new(lab)),
|
||||
<set: PositiveSet> => positive_grouping::PositiveExpression::Set(set),
|
||||
"'" <el: PositiveLiteral> "'" =>
|
||||
positive_grouping::PositiveExpression::PositiveElement(el.into()),
|
||||
|
||||
// strings
|
||||
PATH => positive_grouping::PositiveExpression::String(<>.trim_end_matches("\"")
|
||||
.trim_start_matches("\"")
|
||||
.to_string()),
|
||||
// allow arbitrary parenthesis
|
||||
"(" <e: GroupExpression> ")" => e,
|
||||
}
|
||||
|
||||
GroupRange: positive_grouping::PositiveRange = {
|
||||
"{" <e: GroupExpression> "}" =>
|
||||
positive_grouping::PositiveRange::IterateOverSet(Box::new(e)),
|
||||
"{" <e1: GroupExpression> ".." <e2: GroupExpression> "}" =>
|
||||
positive_grouping::PositiveRange::IterateInRange(Box::new(e1), Box::new(e2)),
|
||||
}
|
||||
|
||||
GroupUnaryPrefix: positive_grouping::PositiveUnary = {
|
||||
"not" => positive_grouping::PositiveUnary::Not,
|
||||
"rand" => positive_grouping::PositiveUnary::Rand,
|
||||
}
|
||||
|
||||
GroupUnarySuffix: positive_grouping::PositiveUnary = {
|
||||
#[precedence(level="0")]
|
||||
"empty" => positive_grouping::PositiveUnary::Empty,
|
||||
"length" => positive_grouping::PositiveUnary::Length,
|
||||
"tostr" => positive_grouping::PositiveUnary::ToStr,
|
||||
"toel" => positive_grouping::PositiveUnary::ToEl,
|
||||
|
||||
#[precedence(level="1")]
|
||||
<q: GroupQualifier> => positive_grouping::PositiveUnary::Qualifier(q),
|
||||
}
|
||||
|
||||
GroupQualifierRestricted: positive_grouping::QualifierRestricted = {
|
||||
"Entities" => positive_grouping::QualifierRestricted::Entities,
|
||||
"Context" => positive_grouping::QualifierRestricted::Context,
|
||||
"Reactants" => positive_grouping::QualifierRestricted::Reactants,
|
||||
"ReactantsAbsent" => positive_grouping::QualifierRestricted::ReactantsAbsent,
|
||||
"Inhibitors" => positive_grouping::QualifierRestricted::Inhibitors,
|
||||
"InhibitorsPresent" => positive_grouping::QualifierRestricted::InhibitorsPresent,
|
||||
"Products" => positive_grouping::QualifierRestricted::Products,
|
||||
}
|
||||
|
||||
GroupQualifierLabel: positive_grouping::QualifierLabel = {
|
||||
"AvailableEntities" => positive_grouping::QualifierLabel::AvailableEntities,
|
||||
"AllReactants" => positive_grouping::QualifierLabel::AllReactants,
|
||||
"AllInhibitors" => positive_grouping::QualifierLabel::AllInhibitors,
|
||||
}
|
||||
|
||||
GroupQualifierSystem: positive_grouping::QualifierSystem = {
|
||||
"SystemEntities" => positive_grouping::QualifierSystem::Entities,
|
||||
"SystemContext" => positive_grouping::QualifierSystem::Context,
|
||||
}
|
||||
|
||||
GroupQualifierEdge: positive_grouping::QualifierEdge = {
|
||||
"source" => positive_grouping::QualifierEdge::Source,
|
||||
"target" => positive_grouping::QualifierEdge::Target,
|
||||
}
|
||||
|
||||
GroupQualifierNode: positive_grouping::QualifierNode = {
|
||||
"neighbours" => positive_grouping::QualifierNode::Neighbours,
|
||||
"system" => positive_grouping::QualifierNode::System,
|
||||
}
|
||||
|
||||
GroupQualifier: positive_grouping::PositiveQualifier = {
|
||||
<q: GroupQualifierSystem> => positive_grouping::PositiveQualifier::System(q),
|
||||
<q: GroupQualifierLabel> => positive_grouping::PositiveQualifier::Label(q),
|
||||
<q: GroupQualifierRestricted> => positive_grouping::PositiveQualifier::Restricted(q),
|
||||
<q: GroupQualifierEdge> => positive_grouping::PositiveQualifier::Edge(q),
|
||||
<q: GroupQualifierNode> => positive_grouping::PositiveQualifier::Node(q),
|
||||
}
|
||||
|
||||
GroupBinary: positive_grouping::PositiveBinary = {
|
||||
"&&" => positive_grouping::PositiveBinary::And,
|
||||
"||" => positive_grouping::PositiveBinary::Or,
|
||||
"^^" => positive_grouping::PositiveBinary::Xor,
|
||||
"<" => positive_grouping::PositiveBinary::Less,
|
||||
"<=" => positive_grouping::PositiveBinary::LessEq,
|
||||
">" => positive_grouping::PositiveBinary::More,
|
||||
">=" => positive_grouping::PositiveBinary::MoreEq,
|
||||
"==" => positive_grouping::PositiveBinary::Eq,
|
||||
"!=" => positive_grouping::PositiveBinary::NotEq,
|
||||
"+" => positive_grouping::PositiveBinary::Plus,
|
||||
"-" => positive_grouping::PositiveBinary::Minus,
|
||||
"*" => positive_grouping::PositiveBinary::Times,
|
||||
"^" => positive_grouping::PositiveBinary::Exponential,
|
||||
"/" => positive_grouping::PositiveBinary::Quotient,
|
||||
"%" => positive_grouping::PositiveBinary::Reminder,
|
||||
"::" => positive_grouping::PositiveBinary::Concat,
|
||||
}
|
||||
|
||||
GroupBinaryPrefix: positive_grouping::PositiveBinary = {
|
||||
"substr" => positive_grouping::PositiveBinary::SubStr,
|
||||
"min" => positive_grouping::PositiveBinary::Min,
|
||||
"max" => positive_grouping::PositiveBinary::Max,
|
||||
"commonsubstr" => positive_grouping::PositiveBinary::CommonSubStr,
|
||||
}
|
||||
Reference in New Issue
Block a user