IPFLang Formal Grammar in BNF
A Domain-Specific Language for Modern IP Fees Calculation
Program Structure
<program> ::= <statement_list>
<statement_list> ::= <statement> | <statement> <statement_list>
<statement> ::= <input_definition> | <fee_definition> | <group_definition> | <return_statement>
Input Definitions
<input_definition> ::= <list_definition> | <multilist_definition> | <number_definition> | <boolean_definition> | <date_definition>
<list_definition> ::= "DEFINE" "LIST" <identifier> "AS" <string_literal> <group_clause>? <choice_list> "DEFAULT" <identifier> "ENDDEFINE"
<multilist_definition> ::= "DEFINE" "MULTILIST" <identifier> "AS" <string_literal> <group_clause>? <choice_list> "DEFAULT" <identifier_list> "ENDDEFINE"
<number_definition> ::= "DEFINE" "NUMBER" <identifier> "AS" <string_literal> <group_clause>? "BETWEEN" <number> "AND" <number> "DEFAULT" <number> "ENDDEFINE"
<boolean_definition> ::= "DEFINE" "BOOLEAN" <identifier> "AS" <string_literal> <group_clause>? "DEFAULT" <boolean_value> "ENDDEFINE"
<date_definition> ::= "DEFINE" "DATE" <identifier> "AS" <string_literal> <group_clause>? "BETWEEN" <date_literal> "AND" <date_literal> "DEFAULT" <date_literal> "ENDDEFINE"
<group_clause> ::= "GROUP" <identifier>
<choice_list> ::= <choice> | <choice> <choice_list>
<choice> ::= "CHOICE" <identifier> "AS" <string_literal>
<identifier_list> ::= <identifier> | <identifier> "," <identifier_list>
Group Definition
<group_definition> ::= "DEFINE" "GROUP" <identifier> "AS" <string_literal> "WITH" "WEIGHT" <number>
Fee Definition
<fee_definition> ::= "COMPUTE" "FEE" <identifier> <optional_clause>? <fee_body> "ENDCOMPUTE"
<optional_clause> ::= "OPTIONAL"
<fee_body> ::= <fee_statement_list>
<fee_statement_list> ::= <fee_statement> | <fee_statement> <fee_statement_list>
<fee_statement> ::= <yield_statement> | <case_statement> | <let_statement>
<yield_statement> ::= "YIELD" <expression> <condition_clause>?
<case_statement> ::= "CASE" <condition> "AS" <yield_statement_list> "ENDCASE"
<let_statement> ::= "LET" <identifier> "AS" <expression>
<yield_statement_list> ::= <yield_statement> | <yield_statement> <yield_statement_list>
Conditions and Expressions
<condition_clause> ::= "IF" <condition>
<condition> ::= <comparison> | <inclusion_test> | <logical_expression>
<comparison> ::= <expression> <comparison_op> <expression>
<inclusion_test> ::= <identifier> <inclusion_op> <identifier>
<logical_expression> ::= <condition> <logical_op> <condition> | "(" <condition> ")"
<comparison_op> ::= "EQ" | "NEQ" | "LT" | "LTE" | "GT" | "GTE"
<inclusion_op> ::= "IN" | "NIN"
<logical_op> ::= "AND" | "OR"
Expressions
<expression> ::= <term> | <expression> <binary_op> <term>
<term> ::= <factor> | <term> <multiply_op> <factor>
<factor> ::= <number> | <identifier> | <property_access> | <function_call> | "(" <expression> ")"
<property_access> ::= <identifier> "!" <property_name>
<property_name> ::= "COUNT" | "YEARSTONOW" | "MONTHSTONOW" | "MONTHSTONOW_FROMLASTDAY" | "DAYSTONOW"
<function_call> ::= <function_name> "(" <expression> ")"
<function_name> ::= "FLOOR" | "ROUND" | "CEIL"
<binary_op> ::= "+" | "-"
<multiply_op> ::= "*" | "/"
Return Statement
<return_statement> ::= "RETURN" <identifier> "AS" <string_literal>
Literals and Identifiers
<identifier> ::= <letter> | <identifier> <letter> | <identifier> <digit>
<string_literal> ::= "'" <string_content> "'"
<string_content> ::= <char> | <char> <string_content>
<number> ::= <integer> | <float>
<integer> ::= <digit> | <integer> <digit>
<float> ::= <integer> "." <integer>
<date_literal> ::= <day> "." <month> "." <year> | "TODAY"
<day> ::= <digit> <digit>
<month> ::= <digit> <digit>
<year> ::= <digit> <digit> <digit> <digit>
<boolean_value> ::= "TRUE" | "FALSE"
Basic Tokens
<letter> ::= "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<char> ::= <letter> | <digit> | " " | "!" | "@" | "#" | "$" | "%" | "^" | "&" | "*" | "(" | ")" | "-" | "_" | "=" | "+" | "[" | "]" | "{" | "}" | "|" | "\" | ":" | ";" | "<" | ">" | "?" | "," | "." | "/" | "`" | "~"