Compare commits

...

3 Commits

Author SHA1 Message Date
Jesse Brault
e79c22db72 Using Boxed children and name fix. 2025-08-31 09:44:17 -05:00
Jesse Brault
3ca488b76d AST gen tweaks. 2025-08-30 09:43:11 -05:00
Jesse Brault
673a008e16 Add schema and function declaration. 2025-08-29 20:24:35 -05:00
4 changed files with 170 additions and 14 deletions

View File

@ -15,7 +15,7 @@ fn get_vec(vec: &Yaml) -> bool {
vec.as_bool().unwrap_or_else(|| false) vec.as_bool().unwrap_or_else(|| false)
} }
fn get_vec_child_to_build(build: &Yaml, rule: &str) -> VecChildToBuild { fn get_vec_child_to_build(build: &Yaml, name: &str, rule: &str) -> VecChildToBuild {
if build.is_hash() { if build.is_hash() {
let build_type = build["build"].as_str().unwrap(); let build_type = build["build"].as_str().unwrap();
let var_name = build["var"] let var_name = build["var"]
@ -32,7 +32,7 @@ fn get_vec_child_to_build(build: &Yaml, rule: &str) -> VecChildToBuild {
let build_as_str = build.as_str().unwrap_or(rule); let build_as_str = build.as_str().unwrap_or(rule);
VecChildToBuild::Type(VecTypeChildToBuild::new( VecChildToBuild::Type(VecTypeChildToBuild::new(
build_as_str, build_as_str,
build_as_str.to_case(Case::Snake).as_str(), name,
make_build_fn_name(build_as_str).as_str(), make_build_fn_name(build_as_str).as_str(),
)) ))
} }
@ -42,7 +42,7 @@ fn get_vec_child(name: &str, rule: &str, build: &Yaml) -> ChildSpec {
ChildSpec::VecChild(VecChild::new( ChildSpec::VecChild(VecChild::new(
name, name,
rule, rule,
get_vec_child_to_build(build, rule), get_vec_child_to_build(build, name, rule),
)) ))
} }
@ -86,10 +86,11 @@ fn get_child_specs(children: &Yaml) -> Vec<ChildSpec> {
.map(|child_spec| { .map(|child_spec| {
if child_spec.is_hash() { if child_spec.is_hash() {
let as_hash = child_spec.as_hash().unwrap(); let as_hash = child_spec.as_hash().unwrap();
let only_pair = as_hash.iter().next().unwrap(); let (name, props) = as_hash
.iter()
let name = only_pair.0.as_str().unwrap(); .next()
let props = only_pair.1; .map(|(name, props)| (name.as_str().unwrap(), props))
.unwrap();
let rule = props["rule"].as_str().unwrap(); let rule = props["rule"].as_str().unwrap();

View File

@ -31,20 +31,25 @@ fn handle_vec_child(
annotated_members: &mut Vec<TokenStream>, annotated_members: &mut Vec<TokenStream>,
accessors: &mut Vec<TokenStream>, accessors: &mut Vec<TokenStream>,
) { ) {
let (child_ident, child_type_ident) = match vec_child.build() { let (child_ident, child_ident_mut, child_type_ident) = match vec_child.build() {
VecChildToBuild::Type(vec_type_child) => ( VecChildToBuild::Type(vec_type_child) => (
format_ident!("{}", vec_type_child.var_name()), format_ident!("{}", vec_type_child.var_name()),
format_ident!("{}_mut", vec_type_child.var_name()),
format_ident!("{}", vec_type_child.build()), format_ident!("{}", vec_type_child.build()),
), ),
}; };
member_names.push(child_ident.clone()); member_names.push(child_ident.clone());
annotated_members.push(quote! { annotated_members.push(quote! {
#child_ident: Vec<#child_type_ident> #child_ident: Vec<Box<#child_type_ident>>
}); });
accessors.push(quote! { accessors.push(quote! {
pub fn #child_ident(&self) -> &[#child_type_ident] { pub fn #child_ident(&self) -> impl Iterator<Item = &#child_type_ident> {
&self.#child_ident self.#child_ident.iter().map(Box::as_ref)
}
pub fn #child_ident_mut(&mut self) -> impl Iterator<Item = &mut #child_type_ident> {
self.#child_ident.iter_mut().map(Box::as_mut)
} }
}); });
} }
@ -56,14 +61,19 @@ fn handle_single_type_child(
accessors: &mut Vec<TokenStream>, accessors: &mut Vec<TokenStream>,
) { ) {
let child_ident = format_ident!("{}", single_type_child.var_name()); let child_ident = format_ident!("{}", single_type_child.var_name());
let child_ident_mut = format_ident!("{}_mut", single_type_child.var_name());
let child_type_ident = format_ident!("{}", single_type_child.build()); let child_type_ident = format_ident!("{}", single_type_child.build());
member_names.push(child_ident.clone()); member_names.push(child_ident.clone());
annotated_members.push(quote! { annotated_members.push(quote! {
#child_ident: #child_type_ident #child_ident: Box<#child_type_ident>
}); });
accessors.push(quote! { accessors.push(quote! {
pub fn #child_ident(&self) -> &#child_type_ident { pub fn #child_ident(&self) -> &#child_type_ident {
&self.#child_ident self.#child_ident.as_ref()
}
pub fn #child_ident_mut(&mut self) -> &mut #child_type_ident {
self.#child_ident.as_mut()
} }
}); });
} }

123
src/parser/ast.schema.yaml Normal file
View File

@ -0,0 +1,123 @@
$schema: https://json-schema.org/draft/2020-12/schema
title: Deimos AST generation spec
type: object
description: Top level is a map of node names in Pascal case (e.g., CompilationUnit) to node definitions.
additionalProperties:
$ref: "#/$defs/NodeDefinition"
$defs:
NodeDefinition:
type: object
additionalProperties: false
description: A definition of a node type.
properties:
children:
type: array
description: Ordered child fields for this node.
items:
$ref: "#/$defs/StructChildDefinition"
rules:
type: array
description: Alternative parse rules that build this node.
items:
$ref: "#/$defs/EnumChildDefinition"
oneOf:
- required:
- "children"
- required:
- "rules"
StructChildDefinition:
description: A definition of a node's child. Either a bare child name (string) in snake case, or an object.
oneOf:
- type: string
description: Shorthand where child name, var, build, and with are inferred from the given snake-case child name.
- $ref: "#/$defs/ChildDefinitionWrapper"
ChildDefinitionWrapper:
type: object
description: Single-key object mapping the child-name to its spec.
minProperties: 1
maxProperties: 1
additionalProperties: false
patternProperties:
"^[a-z][a-z0-9_]*$":
$ref: "#/$defs/ChildDefinition"
ChildDefinition:
type: object
description: One of skip/vec/single child specs.
oneOf:
- $ref: "#/$defs/SkipChildDefinition"
- $ref: "#/$defs/VecChildDefinition"
- $ref: "#/$defs/SingleChildDefinition"
SkipChildDefinition:
type: object
additionalProperties: false
description: A definition for a child rule that does nothing, i.e., is skipped.
properties:
rule:
type: string
skip:
type: boolean # note: must be true
required:
- rule
- skip
VecChildDefinition:
type: object
additionalProperties: false
description: A definition for a child rule that can be matched multiple times.
properties:
rule:
type: string
vec:
type: boolean
required:
- rule
- vec
SingleChildDefinition:
type: object
additionalProperties: false
description: A definition for a child rule that builds one item.
properties:
rule:
type: string
build:
oneOf:
- type: string
- $ref: "#/$defs/SingleChildBuildDefinition"
required:
- rule
SingleChildBuildDefinition:
type: object
additionalProperties: false
description: A definition of what exactly to build for a given child rule.
oneOf:
- $ref: "#/$defs/BuildBooleanChild"
BuildBooleanChild:
type: object
additionalProperties: false
description: A definition for building a boolean child.
properties:
type:
type: string
enum:
- boolean
on:
type: string
enum:
- rule_present
EnumChildDefinition:
description: A definition of an enum node's child. Either a bare rule (string) in Pascal case, or an object.
oneOf:
- type: string
description: Shorthand where child name, var, build, and with are inferred from the given Pascal-case rule name.
- $ref: "#/$defs/LongEnumChildDefinition"
LongEnumChildDefinition:
type: object
additionalProperties: false
description: A format for specifying more specific information for an enum child.
properties:
rule:
type: string
build:
type: string
required:
- rule
- build

View File

@ -1,3 +1,4 @@
# $schema: ./ast.schema.yaml
CompilationUnit: CompilationUnit:
children: children:
- namespace - namespace
@ -29,6 +30,8 @@ ModuleLevelDeclaration:
build: ModuleDeclaration build: ModuleDeclaration
- rule: Interface - rule: Interface
build: InterfaceDeclaration build: InterfaceDeclaration
- rule: Class
build: ClassDeclaration
- FunctionDefinition - FunctionDefinition
- PlatformFunction - PlatformFunction
ModuleDeclaration: ModuleDeclaration:
@ -46,7 +49,7 @@ ModuleDeclaration:
- declarations: - declarations:
rule: ModuleLevelDeclaration rule: ModuleLevelDeclaration
vec: true vec: true
Class: ClassDeclaration:
children: children:
- is_public: - is_public:
rule: Pub rule: Pub
@ -63,3 +66,22 @@ Class:
- class_level_declarations: - class_level_declarations:
rule: ClassLevelDeclaration rule: ClassLevelDeclaration
vec: true vec: true
FunctionDeclaration:
children:
- is_public:
rule: Pub
build:
type: boolean
on: rule_present
- modifier:
rule: Modifier
build: FunctionModifier
- fn_kw:
rule: Fn
skip: true
- generics:
rule: GenericParameters
- identifier
- parameters
- return_type
- function_body