parser.common-rules

API Reference

parser.common-rules

Provides common parsing rules that are useful in many grammars.

PARSER.COMMON-RULES

This package contains parsing rules and macros for common parsing
    tasks that are hopefully useful in many grammars.
  • Macro DEFRULE/S (name-and-options expression &body options)
    Like `esrap:defule' but define additional rules named NAME/s and NAME/?s which respectively require/allow EXPRESSION to be followed by skippable input (e.g. whitespace). NAME-AND-OPTIONS can be either just a rule name or a list of the form (NAME &key SKIPPABLE-EXPRESSION S? SKIPPABLE?-EXPRESSION ?S? DEFINER) where SKIPPABLE-EXPRESSION and SKIPPABLE?-EXPRESSION name the rules used to parse skippable input in the NAME/s and NAME/?s variants. Default to `skippable' and `skippable?' respectively. S? and ?S? control which of the NAME/S and NAME/?S rules should be generated. Default is generating both. DEFINER is the name of the macro used to define the "main" rule. Defaults to `esrap:defrule'.

parser.common-rules.operators

Provides macros for defining grammar rules for infix operators.

PARSER.COMMON-RULES.OPERATORS

This package provides functions and macros for defining grammar
    rules for parsing unary and binary operators.
  • Macro DEFINE-UNARY-OPERATOR-RULE (name operator-expression next &key (fixity :prefix) (skippable?-expression (skippable-rule-for-name 'skippable? name)) (definer 'defrule) (node-kind :unary-operator))
    Define a rule NAME for parsing an unary operator expressions with operator OPERATOR-EXPRESSION and operand NEXT. FIXITY has to be one of :prefix Generate a prefix operator, i.e. (and OPERATOR-EXPRESSION SKIPPABLE?-EXPRESSION NEXT) :postfix Generate a postfix operator, i.e. (and NEXT SKIPPABLE?-EXPRESSION OPERATOR-EXPRESSION) If supplied, SKIPPABLE?-EXPRESSION is the expression to be used for parsing skippable input (usually whitespace) between OPERATOR-EXPRESSION and NEXT. If SKIPPABLE?-EXPRESSION is not supplied, a rule whose name is (find-symbol (string '#:skippable?) (symbol-package OPERATOR-NAME)) is used. If supplied, DEFINER names the macro that should be used to define the rule. Otherwise `esrap:defrule' is used.
  • Macro DEFINE-BINARY-OPERATOR-RULE (name operator-expression next &key (associativity :left) (skippable?-expression (skippable-rule-for-name 'skippable? name)) (definer 'defrule) (node-kind :binary-operator))
    Define a rule NAME for parsing a binary operator expressions with operator OPERATOR-EXPRESSION and operands NEXT. ASSOCIATIVITY has to be one of :none The defined binary operator will be non-associative, i.e. for an OPERATOR-EXPRESSION ":=", the expressions x:=y:=z will not be syntatically legal. :left The defined binary operator will associate to the left, i.e. x+y+z will be parsed as (x+y)+z. :right The defined binary operator will associate to the right, i.e. x^y^z will be parsed as x^(y^z). :associative The defined binary operator will associate to the left (but this should not be relied upon). If supplied, SKIPPABLE?-EXPRESSION is the expression to be used for parsing skippable input (usually whitespace) between OPERATOR-EXPRESSION and NEXT. If SKIPPABLE?-EXPRESSION is not supplied, a rule whose name is (find-symbol (string '#:skippable?) (symbol-package OPERATOR-NAME)) is used. If supplied, DEFINER names the macro that should be used to define the rule. Otherwise `esrap:defrule' is used.
  • Macro DEFINE-TERNARY-OPERATOR-RULE (name operator1-expression operator2-expression next &key (skippable?-expression (skippable-rule-for-name 'skippable? name)) (definer 'defrule) (node-kind :ternary-operator))
    Define a rule NAME for parsing a ternary operator expressions with operators OPERATOR1-EXPRESSION and OPERATOR2-EXPRESSION and operands NEXT. If supplied, SKIPPABLE?-EXPRESSION is the expression to be used for parsing skippable input (usually whitespace) between OPERATOR-EXPRESSION and NEXT. If SKIPPABLE?-EXPRESSION is not supplied, a rule whose name is (find-symbol (string '#:skippable?) (symbol-package OPERATOR-NAME)) is used. If supplied, DEFINER names the macro that should be used to define the rule. Otherwise `esrap:defrule' is used.
  • Macro DEFINE-OPERATOR-RULES ((&key skippable?-expression (unary-node-kind :unary-operator) (binary-node-kind :binary-operator) (ternary-node-kind :ternary-operator)) &body clauses)
    Define rules for parsing infix operators according to CLAUSES. The order of clauses in CLAUSES determines the precedence of operators: (define-operator-rules () OPERATOR-WITH-LOWEST-BINDING-POWER ? OPERATOR-WITH-HIGHEST-BINDING-POWER LEAF-EXPRESSION) All but the final clause in CLAUSES are of the form (ARITY RULE-NAME OPERATOR-EXPRESSION &rest ARGS &key) where * ARITY is the number of operands accepted by the operator being defined. The ARITY must be either 1, 2 or 3. * RULE-NAME is the name of the rule generated for the operator. * OPERATOR-EXPRESSION is an expression for parsing the operator token, e.g. #\* for multiplication. * ARGS can be any of the keyword arguments accepted by `define-unary-operator-rule', `define-binary-operator-rule' or `define-ternary-operator-rule' depending on ARITY, i.e. * :fixity (:prefix | :postfix) Only for unary operators. Fixity of the operator being defined. * :associativity (:none | :left | :right | :associative) Only for binary operators. Associativity of the operator being defined. * :skippable?-expression EXPRESSION See below. * :definer RULE-NAME The macro used to define the operator rule. Defaults to `esrap:defrule'. The final LEAF-EXPRESSION clause is just a rule expression, describing the "leafs" (i.e. not operator expressions) of the operator grammar. Whitespace handling can be controlled by specifying rules for "skippable" input using the :skippable?-expression keyword argument in ARGS. If supplied, SKIPPABLE?-EXPRESSION is applied to all defined operators. If SKIPPABLE?-EXPRESSION is not supplied, a rule whose name is (find-symbol (string '#:skippable?) (symbol-package OPERATOR-NAME)) is used. Example (define-operator-rules (:skippable?-expression (* #\Space)) (2 term "+") ; lowest binding power (2 factor "*") (1 neg "-") ; highest binding power #\x) ; leaf expression (architecture.builder-protocol:with-builder ('list) (esrap:parse 'term "x + x * -x")) => (:BINARY-OPERATOR (:OPERAND (("x") ((:BINARY-OPERATOR (:OPERAND (("x") ((:UNARY-OPERATOR (:OPERAND (("x"))) :OPERATOR "-" :BOUNDS (4 . 6))))) :OPERATOR "*" :BOUNDS (2 . 6))))) :OPERATOR "+" :BOUNDS (0 . 6)) Note that this macro is not concerned with forcing operator bindings via parentheses. See the documentation for recommendations on that.