X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/sod/blobdiff_plain/dea4d05507e59ab779ed4bb209e05971d87e260c..bf090e021a5c20da452a4841cdfb8eb78e29544e:/src/parser/proto-parser-expr.lisp diff --git a/src/parser/proto-parser-expr.lisp b/src/parser/proto-parser-expr.lisp index b2919d6..7fc2609 100644 --- a/src/parser/proto-parser-expr.lisp +++ b/src/parser/proto-parser-expr.lisp @@ -36,7 +36,7 @@ (defgeneric push-operator (operator state) This should apply existing stacked operators as necessary to obey the language's precedence rules.")) -(export 'push-vlaue) +(export 'push-value) (defgeneric push-value (value state) (:documentation "Push VALUE onto the STATE's value stack. @@ -76,7 +76,19 @@ (defgeneric operator-push-action (left right) (export 'expr) (defparse expr ((&key (nestedp (gensym "NESTEDP-"))) operand binop preop postop) - "Parse an expression involving unary and binary operators." + "Parse an expression involving unary and binary operators. + + Within the parsers for operands and operators, the variable NESTEDP is + bound to a generalized boolean which is true if an unmatched open- + parenthesis has been seen. + + The OPERAND parser should produce a value; the various operator parsers + (BINOP, PREOP, and POSTOP) should produce objects obeying the `operator' + protocol. The final output of the `expr' parse is the result of + evaluating the parsed expression. (Of course, the definition of + `evaluation' here is determined entirely by the methods on + `apply-operator', so the final value may be a parse tree, for example.)" + (flet ((wrap (parser) `(parser (,nestedp) (declare (ignorable ,nestedp)) @@ -106,7 +118,7 @@ (defgeneric operator-right-precedence (operator) Higher precedence numbers indicate tighter rightward binding. Under the default method for `operator-push-action', a new operator's left - precedence may be compared to the existing OPERATOR'S right precedences to + precedence may be compared to the existing OPERATOR's right precedences to determine the parser's behaviour: if it is higher, then the new operator is pushed; otherwise the existing OPERATOR is applied. Thus, equal precedences cause left-associative parsing.")) @@ -206,6 +218,12 @@ (defclass simple-prefix-operator (prefix-operator simple-unary-operator) (export 'preop) (defmacro preop (name (x prec) &body body) + "Define a prefix operator. + + The operator will be called NAME in error messages, and have right + precedence PREC. To apply the operator, BODY is evaluated with X bound to + the operand." + `(make-instance 'simple-prefix-operator :name ,name :precedence ,prec @@ -213,6 +231,12 @@ (defmacro preop (name (x prec) &body body) (export 'postop) (defmacro postop (name (x prec &key rprec) &body body) + "Define a postfix operator. + + The operator will be called NAME in error messages, and have left + precedence PREC and right precendence RPREC (defaulting to PREC). To + apply the operator, BODY is evaluated with X bound to the operand." + (once-only (name prec rprec) `(make-instance 'simple-postfix-operator :name ,name @@ -222,6 +246,14 @@ (defmacro postop (name (x prec &key rprec) &body body) (export 'binop) (defmacro binop (name (x y prec &key rprec (assoc :left)) &body body) + "Define a binary operator. + + The operator will be called NAME in error messages, and have left + precedence PREC and right precedence RPREC (defaulting to PREC, implying + left associativity under the default `operator-push-action' + implementation. To apply the operator, BODY is evaluated with X and Y + bound to the operands in the order they were parsed" + (once-only (name prec rprec assoc) `(make-instance 'simple-binary-operator :name ,name