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)
}
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() {
let build_type = build["build"].as_str().unwrap();
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);
VecChildToBuild::Type(VecTypeChildToBuild::new(
build_as_str,
build_as_str.to_case(Case::Snake).as_str(),
name,
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(
name,
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| {
if child_spec.is_hash() {
let as_hash = child_spec.as_hash().unwrap();
let only_pair = as_hash.iter().next().unwrap();
let name = only_pair.0.as_str().unwrap();
let props = only_pair.1;
let (name, props) = as_hash
.iter()
.next()
.map(|(name, props)| (name.as_str().unwrap(), props))
.unwrap();
let rule = props["rule"].as_str().unwrap();

View File

@ -31,20 +31,25 @@ fn handle_vec_child(
annotated_members: &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) => (
format_ident!("{}", vec_type_child.var_name()),
format_ident!("{}_mut", vec_type_child.var_name()),
format_ident!("{}", vec_type_child.build()),
),
};
member_names.push(child_ident.clone());
annotated_members.push(quote! {
#child_ident: Vec<#child_type_ident>
#child_ident: Vec<Box<#child_type_ident>>
});
accessors.push(quote! {
pub fn #child_ident(&self) -> &[#child_type_ident] {
&self.#child_ident
pub fn #child_ident(&self) -> impl Iterator<Item = &#child_type_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>,
) {
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());
member_names.push(child_ident.clone());
annotated_members.push(quote! {
#child_ident: #child_type_ident
#child_ident: Box<#child_type_ident>
});
accessors.push(quote! {
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:
children:
- namespace
@ -29,6 +30,8 @@ ModuleLevelDeclaration:
build: ModuleDeclaration
- rule: Interface
build: InterfaceDeclaration
- rule: Class
build: ClassDeclaration
- FunctionDefinition
- PlatformFunction
ModuleDeclaration:
@ -46,7 +49,7 @@ ModuleDeclaration:
- declarations:
rule: ModuleLevelDeclaration
vec: true
Class:
ClassDeclaration:
children:
- is_public:
rule: Pub
@ -63,3 +66,22 @@ Class:
- class_level_declarations:
rule: ClassLevelDeclaration
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