Skip to content

Instantly share code, notes, and snippets.

@nikomatsakis
Created March 25, 2023 18:18
Show Gist options
  • Save nikomatsakis/d93463b2430abe65264a7578ab86d810 to your computer and use it in GitHub Desktop.
Save nikomatsakis/d93463b2430abe65264a7578ab86d810 to your computer and use it in GitHub Desktop.
use crate::class_info::*;
grammar;
pub ClassInfo: ClassInfo = {
Header?
<l:Flags> "class" <n:DotId>
<g:Generics>
<e:("extends" <ClassRef>)?>
<i:("implements" <Comma<ClassRef>>)?>
"{"
<f:Field*>
<c:Constructor*>
<m:Method*>
"}" => {
ClassInfo {
flags: l,
name: n,
generics: g,
extends: e,
implements: i.unwrap_or(vec![]),
constructors: c,
methods: m,
fields: f,
}
}
};
// #[inline]
Generics: Vec<Id> = {
() => vec![],
("<" <Comma<Id>> ">"),
};
Header: () = r#"Compiled from "[a-zA-Z.]+""#;
DotId: Id = {
<a:Id> "." <b:ID> => a.dot(b),
<i:DotId> "." <s:ID> => i.dot(s),
};
Id: Id = {
<a:ID> => Id::from(a),
};
ID: &'input str = {
r"[a-zA-Z][a-zA-Z0-9]*"
}
Constructor: Constructor = {
<f:Flags> <n:DotId> "(" <a:Comma<Type>> ")" <t:Throws> ";" <d:Descriptor> => {
Constructor { flags: f, args: a, throws: t, descriptor: d, }
}
};
Method: Method = {
<f:Flags> <g:Generics> <r:Type> <n:Id> "(" <a:Comma<Type>> ")" <t:Throws> ";" <d:Descriptor> => {
Method { flags: f, name: n, argument_tys: a, return_ty: r, throws: t, descriptor: d, generics: g }
}
};
Field: Field = {
<f:Flags> <t:Type> <n:Id> ";" => {
Field { flags: f, name: n, ty: t }
}
};
Flags: Flags = {
<p:Privacy> => Flags::new(p),
<f:Flags> "final" => Flags { is_final: true, ..f },
<f:Flags> "synchronized" => Flags { is_synchronized: true, ..f },
<f:Flags> "native" => Flags { is_native: true, ..f },
};
Privacy: Privacy = {
"public" => Privacy::Public,
"protected" => Privacy::Protected,
() => Privacy::Package,
};
Descriptor: Descriptor = {
r"descriptor: \([\[\]a-zA-Z0-9/;]*\)[\[\]a-zA-Z0-9/;]+" => {
Descriptor::from(&<>["descriptor: ".len()..])
}
};
Throws: Vec<ClassRef> = {
() => vec![],
"throws" <Comma1<ClassRef>>,
}
Type: Type = {
<ScalarType> => Type::Scalar(<>),
<RefType> => Type::Ref(<>),
};
ScalarType: ScalarType = {
"byte" => ScalarType::Byte,
"short" => ScalarType::Short,
"int" => ScalarType::Int,
"long" => ScalarType::Long,
"float" => ScalarType::F32,
"double" => ScalarType::F64,
"boolean" => ScalarType::Boolean,
};
RefType: RefType = {
ClassRefOrId,
<RefType> "[" "]" => RefType::Array(Arc::new(<>)),
"?" "extends" <ClassRefOrId> => RefType::Extends(Arc::new(<>)),
"?" "super" <ClassRefOrId> => RefType::Super(Arc::new(<>)),
"?" => RefType::Wildcard,
};
ClassRefOrId: RefType = {
<ClassRef> => RefType::Class(<>),
<Id> => RefType::TypeParameter(<>),
};
ClassRef: ClassRef = {
<name:DotId> => ClassRef { name, generics: vec![] },
<name:DotId> "<" <generics:Comma<RefType>> ">" => ClassRef { <> },
};
Comma<E>: Vec<E> = {
() => vec![],
Comma1<E>,
};
Comma1<E>: Vec<E> = {
E => vec![<>],
<v:Comma<E>> "," <e:E> => {
let mut v = v;
v.push(e);
v
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment