dejavu-parser 0.1.1

Parser of DejaVu Language
Documentation
@export
SahaParser = parsed:SahaStatementNodes $;

@no_skip_ws
SahaStatementNodes = { statements:SahaStatement };

SahaStatement =
	@:SlotFor |
	@:SlotIf |
	@:SlotExpressionNode |
	@:UnicodeText
;

@position
@no_skip_ws
SlotIf = start:SlotIfStart body:SahaStatementNodes {else_if:SlotElseIf} [else:SlotElse] end:SlotEndIf;

SlotIfStart = left:SlotL "if" cond:ExpressionNode right:SlotR;

SlotElseIf = left:SlotL ("else" "if" | "else-if") cond:ExpressionNode right:SlotR body:SahaStatementNodes;

SlotElse = left:SlotL "else" right:SlotR body:SahaStatementNodes;

SlotEndIf = left:SlotL EndIf right:SlotR;

EndIf = "end-if" | "endif" | "end";



@position
@no_skip_ws
SlotFor = start:SlotForStart body:SahaStatementNodes [else:SlotElse] end:SlotEndFor;

SlotForStart = left:SlotL "for" pattern:ValueNode "in" expression:ExpressionNode right:SlotR;

SlotEndFor = left:SlotL EndFor right:SlotR;

@no_skip_ws
EndFor = "end" ['-' "for"];

@check(crate::utils::check_slot_expression)
SlotExpressionNode = left:SlotL e:ExpressionNode right:SlotR;

@position
ExpressionNode = head:TermNode {infix:ExpressionNodeInfix};
ExpressionNodeInfix = op:InfixOp value:TermNode;

@position
TermNode = {prefix:PrefixOp} term:ValueNode {suffix:Suffix};

@string
PrefixOp = "&" | "+" | "-" | "*";

@string
InfixOp = "+" | "-" | "==" | "<=" | "<" | ">=" | ">";

Suffix = @:SuffixOp | @:DotCall;

@string
SuffixOp = "!";

DotCall = '.' call:IdentifierNode [FunctionArgs];


FunctionArgs = '(' args:ExpressionNode {[','] args:ExpressionNode}  [','] ')';


ValueNode =
	@:BooleanNode |
	@:DecimalNode |
	@:IntegerNode |
	@:StringNode  |
	@:NamespaceNode
;

@no_skip_ws
@position
SlotL = "{%" [trim:TrimMode];

@no_skip_ws
@position
SlotR = [trim:TrimMode] "%}";

@char
TrimMode = '_' | '-' | '~' | '=' | '!';

@position
NamespaceNode = path:IdentifierNode ['::' path:IdentifierNode];

@string
@position
@no_skip_ws
IdentifierNode = (XID_START | '_' | '-') {XID_CONTINUE | '-'};

@char
@check(unicode_ident::is_xid_start)
XID_START = char;

@char
@check(unicode_ident::is_xid_continue)
XID_CONTINUE = char;

@string
@position
BooleanNode = "true" | "false";

@position
@string
IntegerNode = {'0'..'9'}+ ;

@position
@string
DecimalNode =
	{'0'..'9'}+ ['.' {'0'..'9'}+] [('**'|'e'|'E') ['+'|'-'] {'0'..'9'}+] |
	'.' {'0'..'9'}+
	;

@position
@string
UnicodeText = {!("{%" | "{#") char}+;

@position
@no_skip_ws
StringNode =
    dq:DQ {!DQ body:StringItem } DQ |
    sq:SQ {!SQ body:StringItem } SQ ;

@no_skip_ws
StringItem =
	@:EscapeUnicode |
	@:EscapeOther   |
	@:char          ;

SQ = "'";

DQ = '"';


EscapeOther = '\\' @:char;

EscapeUnicode = '\\' 'u';

@no_skip_ws
Comment = left:CommentL {!CommentR|char}+ right:CommentR;

@no_skip_ws
@position
CommentL = "{#" [trim:TrimMode];

@no_skip_ws
@position
CommentR = [trim:TrimMode] "#}";