diff --git a/src/languages/azure_policy/expr.rs b/src/languages/azure_policy/expr.rs index f09641a..ba0d909 100644 --- a/src/languages/azure_policy/expr.rs +++ b/src/languages/azure_policy/expr.rs @@ -70,6 +70,13 @@ impl<'source> ExprParser<'source> { fn new(source: &'source Source) -> Self { let mut lexer = Lexer::new(source); lexer.set_unknown_char_is_symbol(true); + // ARM template expressions inside Azure Policy JSON values can be + // very long (e.g. deeply nested `if(...)` / `concat(...)` spanning + // thousands of characters on a single line). Use a generous column + // limit so these expressions parse successfully. + if let Some(limit) = core::num::NonZeroU32::new(65536) { + lexer.set_max_col(limit); + } let tok = Token( TokenKind::Eof, Span { diff --git a/src/languages/azure_policy/parser/core.rs b/src/languages/azure_policy/parser/core.rs index 321aff9..493c896 100644 --- a/src/languages/azure_policy/parser/core.rs +++ b/src/languages/azure_policy/parser/core.rs @@ -148,8 +148,21 @@ pub(super) struct Parser<'source> { impl<'source> Parser<'source> { /// Create a new parser for the given source. pub fn new(source: &'source Source) -> Result { + Self::new_with_max_col(source, None) + } + + /// Create a new parser with an optional column-width override. + /// + /// When `max_col` is `None`, the lexer's default limit applies. + pub fn new_with_max_col( + source: &'source Source, + max_col: Option, + ) -> Result { let mut lexer = Lexer::new(source); lexer.set_unknown_char_is_symbol(true); + if let Some(mc) = max_col { + lexer.set_max_col(mc); + } let tok = lexer .next_token() diff --git a/src/languages/azure_policy/parser/mod.rs b/src/languages/azure_policy/parser/mod.rs index b18f127..1a29211 100644 --- a/src/languages/azure_policy/parser/mod.rs +++ b/src/languages/azure_policy/parser/mod.rs @@ -34,6 +34,8 @@ pub use error::ParseError; use alloc::string::ToString as _; +use ::core::num::NonZeroU32; + use crate::lexer::{Source, TokenKind}; use super::ast::{Constraint, FieldKind, OperatorKind, PolicyDefinition, PolicyRule}; @@ -57,7 +59,15 @@ use self::core::Parser; /// /// Returns a span-annotated [`PolicyRule`] AST. pub fn parse_policy_rule(source: &Source) -> Result { - let mut parser = Parser::new(source)?; + parse_policy_rule_with_max_col(source, None) +} + +/// Like [`parse_policy_rule`] but with an optional column-width override. +pub fn parse_policy_rule_with_max_col( + source: &Source, + max_col: Option, +) -> Result { + let mut parser = Parser::new_with_max_col(source, max_col)?; let rule = parser.parse_policy_rule()?; if parser.tok.0 != TokenKind::Eof { @@ -79,7 +89,15 @@ pub fn parse_policy_rule(source: &Source) -> Result { /// Returns a [`PolicyDefinition`] with typed fields for known properties /// and a catch-all list of `extra` entries for everything else. pub fn parse_policy_definition(source: &Source) -> Result { - let mut parser = Parser::new(source)?; + parse_policy_definition_with_max_col(source, None) +} + +/// Like [`parse_policy_definition`] but with an optional column-width override. +pub fn parse_policy_definition_with_max_col( + source: &Source, + max_col: Option, +) -> Result { + let mut parser = Parser::new_with_max_col(source, max_col)?; let defn = parser.parse_policy_definition()?; if parser.tok.0 != TokenKind::Eof {