Skip to content

nt_type and Box #596

@jgoppert

Description

@jgoppert

When I change my grammar so that parol detects it needs to use box-types, it appears the type casting to user defined non-terminal types isn't happening as expected:

build.rs (I'm using minimize boxed types option)

fn main() {
    // CLI equivalent is:
    // parol -f ./modelica.par -e ./modelica-exp.par -p ./src/modelica_parser.rs -a ./src/modelica_grammar_trait.rs -t ModelicaGrammar -m modelica_grammar -g
    if let Err(err) = Builder::with_explicit_output_dir("src")
        .grammar_file("modelica.par")
        .expanded_grammar_output_file("../modelica-exp.par")
        .parser_output_file("modelica_parser.rs")
        .actions_output_file("modelica_grammar_trait.rs")
        .user_type_name("ModelicaGrammar")
        .user_trait_module_name("modelica_grammar")
        .trim_parse_tree()
        .minimize_boxed_types()
        .generate_parser()
    {
        ParolErrorReporter::report_error(&err, "modelica.par").unwrap_or_default();
        process::exit(1);
    }
}

crate::ir::ComponentReference

#[derive(Default, Clone)]
#[allow(unused)]
pub struct ComponentReference {
    pub name: Vec<Token>,
    pub node: NodeData,
}

Excerpt of grammar

primary
    : unsigned_number
    | string
    | false
    | true
    // | ( component_reference | der | initial | pure ) function_call_args
    | component_reference
    // | '('^ output_expression_list ')' [ ( array_subscripts | '.'^ ident ) ]
    // | '['^ expression_list { ';' expression_list } ']'^
    // | '{'^ array_arguments '}'^
    | end
    ;

array_subscripts :
    '['^ subscript { ','^ subscript } ']'^
    ;

subscript :
    ':' | expression
    ;

works:

%nt_type component_reference = crate::ir::ComponentReference
...

component_reference
    : [ '.'^ ] ident
    //[ array_subscripts ]
    { '.'^ ident
    [ array_subscripts ]
    }
    ;

doesn't work:

%nt_type component_reference = crate::ir::ComponentReference
...

component_reference
    : [ '.'^ ] ident
    [ array_subscripts ]
    { '.'^ ident
    [ array_subscripts ]
    }
    ;

I think this second grammar with array_subscript option has expression which needs to be boxed, so causes reported issue.

If I adapt my modelica_grammar.rs code to use Box, it still doesn't compile as the try_into is not called before boxing. I suspect this might be a bug, but could also be user error :-).

Generated code without array_subscripts option:

    /// Semantic action for production 200:
    ///
    /// `primary: component_reference;`
    ///
    #[parol_runtime::function_name::named]
    fn primary_4(&mut self, _component_reference: &ParseTreeType<'t>) -> Result<()> {
        let context = function_name!();
        trace!("{}", self.trace_item_stack(context));
        let component_reference = pop_item!(self, component_reference, ComponentReference, context);
        let primary_4_built = PrimaryComponentReference {
            component_reference: Box::new(component_reference),
        };
        let primary_4_built = Primary::ComponentReference(primary_4_built);
        // Calling user action here
        self.user_grammar.primary(&primary_4_built)?;
        self.push(ASTType::Primary(primary_4_built), context);
        Ok(())
    }

Generated code with array_subscripts option:

    /// Semantic action for production 200:
    ///
    /// `primary: component_reference;`
    ///
    #[parol_runtime::function_name::named]
    fn primary_4(&mut self, _component_reference: &ParseTreeType<'t>) -> Result<()> {
        let context = function_name!();
        trace!("{}", self.trace_item_stack(context));
        let component_reference = pop_item!(self, component_reference, ComponentReference, context);
        let primary_4_built = PrimaryComponentReference {
            component_reference: (&component_reference)
                .try_into()
                .map_err(parol_runtime::ParolError::UserError)?,
        };
        let primary_4_built = Primary::ComponentReference(primary_4_built);
        // Calling user action here
        self.user_grammar.primary(&primary_4_built)?;
        self.push(ASTType::Primary(primary_4_built), context);
        Ok(())
    }

modelica_grammar.rs

impl TryFrom<&modelica_grammar_trait::Primary> for ir::Expression {
    type Error = anyhow::Error;

    fn try_from(ast: &modelica_grammar_trait::Primary) -> std::result::Result<Self, Self::Error> {
        match &ast {
            modelica_grammar_trait::Primary::ComponentReference(comp_ref) => Ok(
                ir::Expression::ComponentReference(comp_ref.component_reference.clone()),
            ),
            ...
        }
    }
}

Full source code is here: https://github.com/cognipilot/rumoca_parol

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions