Skip to content

Commit

Permalink
refactor(peg): match on rules instead of tags
Browse files Browse the repository at this point in the history
  • Loading branch information
desbma-s1n committed Jun 13, 2024
1 parent 852b37c commit cb97a99
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 67 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ log = { version = "0.4.19", default-features = false, features = ["max_level_tra
nix = { version = "0.26.2", default-features = false, features = ["fs"] }
nom = { version = "7.1.3", default-features = false, features = ["std"], optional = true }
pest = { version = "2.7.10", default-features = false, features = ["std", "memchr"], optional = true }
pest_derive = { version = "2.7.10", default-features = false, features = ["std", "grammar-extras"], optional = true}
pest_derive = { version = "2.7.10", default-features = false, features = ["std"], optional = true}
rand = { version = "0.8.5", default-features = false, features = ["std", "std_rng"] }
regex = { version = "1.9.1", default-features = false, features = ["std", "perf"] }
serde = { version = "1.0.193", default-features = false, features = ["std", "derive"] }
Expand Down
51 changes: 25 additions & 26 deletions src/strace/parser/peg.pest
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
// Line formats

syscall_line = {
#complete = syscall_line_complete |
#start = syscall_line_start |
#end = syscall_line_end
syscall_line_complete |
syscall_line_start |
syscall_line_end
}
syscall_line_complete = { SOI ~ pid ~ " "+ ~ rel_ts ~ " " ~ name ~ "(" ~ arguments ~ ") " ~ " "* ~ "= " ~ ret_val ~ EOI }
syscall_line_start = { SOI ~ pid ~ " "+ ~ rel_ts ~ " " ~ name ~ "(" ~ arguments ~ " <unfinished ...>" ~ EOI }
Expand All @@ -21,8 +21,8 @@ rel_ts = { ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ }
name = { symbol_name }

arguments = {
#named = named_arguments |
#unnamed = unnamed_arguments
named_arguments |
unnamed_arguments
}

ret_val = { int ~ (" " ~ ANY*)? }
Expand All @@ -35,8 +35,8 @@ named_arguments = { named_affectation ~ (", " ~ named_affectation)* }
unnamed_arguments = { (argument ~ (", " ~ argument)*)? }

argument = {
#in_out = in_out_argument |
#in = in_argument
in_out_argument |
in_argument
}
in_argument = { expression }
in_out_argument = {
Expand All @@ -46,12 +46,12 @@ in_out_argument = {

expression = {
(
#macro = macro |
#int = int |
#struct = struct |
#buf = buffer |
#set = set |
#array = array
macro |
int |
struct |
buffer |
set |
array
) ~
comment?
}
Expand All @@ -60,16 +60,16 @@ symbol_name = { (ASCII_ALPHA | "_") ~ (ASCII_ALPHA | ASCII_DIGIT | "_")* }
comment = { " /* " ~ (!" */" ~ ANY)+ ~ " */" }

int = {
#or = or |
#mul = multiplication |
#lshift = left_bit_shift |
#lit = literal_int |
#named = named_constant
or |
multiplication |
left_bit_shift |
literal_int |
named_constant
}
literal_int = {
#oct = literal_int_oct |
#hex = literal_int_hex |
#dec = literal_int_dec
literal_int_oct |
literal_int_hex |
literal_int_dec
}
or = { named_constant ~ ("|" ~ int)+ }
left_bit_shift = { literal_int ~ "<<" ~ int }
Expand Down Expand Up @@ -101,8 +101,8 @@ struct = {
"}"
}
struct_member = {
#member_named = named_affectation |
#macro_addr = macro
named_affectation |
macro
}

buffer = {
Expand All @@ -121,8 +121,8 @@ buffer_byte = { "\\x" ~ ASCII_HEX_DIGIT{2} }
macro = { symbol_name ~ "(" ~ macro_arguments ~ ")" }
macro_arguments = { (macro_argument ~ (", " ~ macro_argument)*)? }
macro_argument = {
#addr = pseudo_addr |
#expr = expression
pseudo_addr |
expression
}
pseudo_addr = { "&" ~ symbol_name }

Expand All @@ -140,4 +140,3 @@ set = {
)? ~
"]"
}

80 changes: 40 additions & 40 deletions src/strace/parser/peg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ pub fn parse_line(line: &str) -> anyhow::Result<ParseResult> {
Ok(mut p) => pair_descend(p.next().unwrap(), 1).unwrap(),
};
log::trace!("{:#?}", pair);
match pair.as_node_tag() {
Some("complete") => Ok(ParseResult::Syscall(pair.try_into()?)),
Some("start") => Ok(ParseResult::SyscallStart(pair.try_into()?)),
Some("end") => Ok(ParseResult::SyscallEnd(pair.try_into()?)),
match pair.as_rule() {
Rule::syscall_line_complete => Ok(ParseResult::Syscall(pair.try_into()?)),
Rule::syscall_line_start => Ok(ParseResult::SyscallStart(pair.try_into()?)),
Rule::syscall_line_end => Ok(ParseResult::SyscallEnd(pair.try_into()?)),
_ => anyhow::bail!("Unhandled pair: {pair:?}"),
}
}
Expand All @@ -45,23 +45,23 @@ impl TryFrom<Pair<'_, Rule>> for Expression {
type Error = anyhow::Error;

fn try_from(pair: Pair<Rule>) -> Result<Self, Self::Error> {
match pair.as_node_tag() {
Some("int") => Ok(Expression::Integer(pair_descend(pair, 1)?.try_into()?)),
Some("buf") => Ok(Expression::Buffer(pair.try_into()?)),
Some("struct") => Ok(Expression::Struct(
match pair.as_rule() {
Rule::int => Ok(Expression::Integer(pair_descend(pair, 1)?.try_into()?)),
Rule::buffer => Ok(Expression::Buffer(pair.try_into()?)),
Rule::r#struct => Ok(Expression::Struct(
pair.into_inner()
.map(|m| -> anyhow::Result<_> {
let m = pair_descend(m, 1)?;
match m.as_node_tag() {
Some("member_named") => {
match m.as_rule() {
Rule::named_affectation => {
let (name_pair, val_pair) =
m.into_inner().next_tuple().ok_or_else(|| {
anyhow::anyhow!("Missing struct member name/value")
})?;
let val: Expression = pair_descend(val_pair, 1)?.try_into()?;
Ok((name_pair.as_str().to_owned(), val))
}
Some("macro_addr") => {
Rule::r#macro => {
let macro_: Expression = m.try_into()?;
let member_name = if let Expression::Macro { args, .. } = &macro_ {
args.iter()
Expand All @@ -85,7 +85,7 @@ impl TryFrom<Pair<'_, Rule>> for Expression {
})
.collect::<Result<_, _>>()?,
)),
Some("macro") | Some("macro_addr") => {
Rule::r#macro => {
let (name, args) = pair
.into_inner()
.next_tuple()
Expand All @@ -96,9 +96,9 @@ impl TryFrom<Pair<'_, Rule>> for Expression {
.into_inner()
.map(|p| {
let p = pair_descend(p, 1)?;
match p.as_node_tag() {
Some("expr") => Expression::try_from(pair_descend(p, 1)?),
Some("addr") => Ok(Expression::DestinationAddress(
match p.as_rule() {
Rule::expression => Expression::try_from(pair_descend(p, 1)?),
Rule::pseudo_addr => Ok(Expression::DestinationAddress(
pair_descend(p, 1)?.as_str().to_owned(),
)),
_ => anyhow::bail!("Unhandled pair: {p:?}"),
Expand All @@ -107,14 +107,14 @@ impl TryFrom<Pair<'_, Rule>> for Expression {
.collect::<Result<_, _>>()?,
})
}
Some("array") => Ok(Expression::Collection {
Rule::array => Ok(Expression::Collection {
complement: false,
values: pair
.into_inner()
.map(|p| Expression::try_from(pair_descend(p, 1)?))
.collect::<Result<_, _>>()?,
}),
Some("set") => {
Rule::set => {
let complement = pair.as_str().starts_with('~');
Ok(Expression::Collection {
complement,
Expand Down Expand Up @@ -163,16 +163,16 @@ impl TryFrom<Pair<'_, Rule>> for BufferExpression {

/// Helper to parse 'literal' pair
fn lit_pair(pair: Pair<Rule>) -> anyhow::Result<IntegerExpression> {
let (val, metadata) = match pair.as_node_tag() {
Some("oct") => (i128::from_str_radix(pair.as_str(), 8)?, None),
Some("hex") => (
let (val, metadata) = match pair.as_rule() {
Rule::literal_int_oct => (i128::from_str_radix(pair.as_str(), 8)?, None),
Rule::literal_int_hex => (
pair.as_str()
.strip_prefix("0x")
.map(|s| i128::from_str_radix(s, 16))
.unwrap()?,
None,
),
Some("dec") => {
Rule::literal_int_dec => {
let mut children = pair.into_inner();
let val_pair = children
.next()
Expand All @@ -181,7 +181,7 @@ fn lit_pair(pair: Pair<Rule>) -> anyhow::Result<IntegerExpression> {
// TODO use Option::take_if if it gets stable
if metadata_pair
.as_ref()
.is_some_and(|p| p.as_node_tag() == Some("com"))
.is_some_and(|p| matches!(p.as_rule(), Rule::comment))
{
metadata_pair = None;
}
Expand All @@ -204,12 +204,12 @@ impl TryFrom<Pair<'_, Rule>> for IntegerExpression {
type Error = anyhow::Error;

fn try_from(pair: Pair<Rule>) -> Result<Self, Self::Error> {
match pair.as_node_tag() {
Some("lit") => {
match pair.as_rule() {
Rule::literal_int => {
let pair = pair_descend(pair, 1)?;
lit_pair(pair)
}
Some("named") => {
Rule::named_constant => {
let mut children = pair.into_inner();
let val_pair = children
.next()
Expand All @@ -222,7 +222,7 @@ impl TryFrom<Pair<'_, Rule>> for IntegerExpression {
.map_or(Ok(None), |v| v.map(Some))?,
})
}
Some("or") => {
Rule::or => {
let mut children = pair.into_inner();
let mut or_elems = Vec::with_capacity(children.len());
or_elems.push(IntegerExpressionValue::NamedConst(
Expand Down Expand Up @@ -251,7 +251,7 @@ impl TryFrom<Pair<'_, Rule>> for IntegerExpression {
metadata: None,
})
}
Some("mul") => {
Rule::multiplication => {
let mut children = pair.into_inner();
let mut mul_elems = Vec::with_capacity(children.len());
mul_elems.push(
Expand All @@ -273,7 +273,7 @@ impl TryFrom<Pair<'_, Rule>> for IntegerExpression {
metadata: None,
})
}
Some("lshift") => {
Rule::left_bit_shift => {
let (left_pair, right_pair) = pair
.into_inner()
.next_tuple()
Expand Down Expand Up @@ -319,22 +319,22 @@ impl TryFrom<Pair<'_, Rule>> for Syscall {
.next()
.ok_or_else(|| anyhow::anyhow!("Missing arguments node"))?;
let args_pair = pair_descend(args_pair, 1)?;
let args = match args_pair.as_node_tag() {
Some("unnamed") => args_pair
let args = match args_pair.as_rule() {
Rule::unnamed_arguments => args_pair
.into_inner()
.map(|p| {
let p = pair_descend(p, 1)?;
match p.as_node_tag() {
Some("in") => pair_descend(p, 2)?.try_into(),
Some("in_out") => {
match p.as_rule() {
Rule::in_argument => pair_descend(p, 2)?.try_into(),
Rule::in_out_argument => {
// Only take the 'in' part, ignore the rest
pair_descend(p, 2)?.try_into()
}
_ => anyhow::bail!("Unhandled pair: {p:?}"),
}
})
.collect::<Result<_, _>>()?,
Some("named") => {
Rule::named_arguments => {
// Handle name arguments as a single struct
vec![Expression::Struct(
args_pair
Expand Down Expand Up @@ -401,22 +401,22 @@ impl TryFrom<Pair<'_, Rule>> for SyscallStart {
.next()
.ok_or_else(|| anyhow::anyhow!("Missing arguments node"))?;
let args_pair = pair_descend(args_pair, 1)?;
let args = match args_pair.as_node_tag() {
Some("unnamed") => args_pair
let args = match args_pair.as_rule() {
Rule::unnamed_arguments => args_pair
.into_inner()
.map(|p| {
let p = pair_descend(p, 1)?;
match p.as_node_tag() {
Some("in") => pair_descend(p, 2)?.try_into(),
Some("in_out") => {
match p.as_rule() {
Rule::in_argument => pair_descend(p, 2)?.try_into(),
Rule::in_out_argument => {
// Only take the 'in' part, ignore the rest
pair_descend(p, 2)?.try_into()
}
_ => anyhow::bail!("Unhandled pair: {p:?}"),
}
})
.collect::<Result<_, _>>()?,
Some("named") => {
Rule::named_arguments => {
// Handle name arguments as a single struct
vec![Expression::Struct(
args_pair
Expand Down

0 comments on commit cb97a99

Please sign in to comment.