63 ms·
> Lisp will read it for you, giving you the tree The Lisp reader just reads s-expressions. It knows nothing about Lisp syntax and thus does not check it.
by lispm 4y ago
> Lisp will read it for you, giving you the tree
The Lisp reader just reads s-expressions. It knows nothing about Lisp syntax and thus does not check it.
- kazinator 4y agoIn fact, in some cases there is nothing to do, syntactically, after the reader is done. An expression like (+ (* x y) (sqrt z)), after being read, is ready for evaluation by performing the function calls. (In principle; of course since we have macros, it has to be walked.) It was the reader which settled all the syntactic facts about what operation is applied to what operands. At this point we could move the goalposts: even eval and compile don't know anything about Lisp syntax. Because, look: (- 10) and (- 10 1) behave differently: the 10 operand changes semantic role between minuend and subtrahend based on syntax. All that eval knows is that it's passing arguments. A function can treat its argument values as the tokens of a syntax which are shored up according to arbitrary phrase structure rules, similarly to Unix programs like find and tcpdump.
- lispm 4y ago> It was the reader which settled all the syntactic facts about what operation is applied to what operands. The reader does not know anything about operands or operators. It does not even know if the thing read is data or code. It also does not know if it is valid code. Enter (3 4 *) and the reader happily takes that expression, not caring about operators and operands. The reader will print zero warning about such expressions. To really know what the symbols in an expression actually are, one would need eval, compile or a code walker. Are they used as literal symbols? variables? functions? macros? block names? type names? ... > Because, look: (- 10) and (- 10 1) behave differently: the 10 operand changes semantic role between minuend and subtrahend based on syntax. All that eval knows is that it's passing arguments. That's semantics, not syntax. EVAL and COMPILE check that it is a function call, what arglist it expects (zero or more args, &optional args, &rest args, keyword args, and process them recursively. But Lisp has also special operators, macro operators and a lambda expression. There the syntax requirements are different or even context depended. Also if Lisp reads the expression (foo * +), the reader does not know if FOO is a function or a macro, it thus does not know what * and + are. Are they variables? Are they operators? Something else? They don't even need to have a definition at read time.
- kazinator 4y agoThe parser for a C grammar (e.g. Yacc job) also doesn't know anything. Is the output used for pretty-printing (the code is just data), completion, or generating code? The reader doesn't know about opperands or operators, but it certainly knows a symbol from an integer or string. We've cleverly arranged things so that it doesn't have to know anything else in order to produce output that, in some cases, can be evaluated directly. > That's semantics, not syntax Syntax versus semantics is sometimes about where you put the goalposts. What if I make it a macro that looks at the argument count and chooses a different function? (defmacro minus (&rest args) (if (eql 1 (length args)) `(unary-minus ,(car args)) ;; takes exactly one arg `(nary-minus ,@args))) ;; blows up if not given at least two args Is that still "semantics, not syntax"? Why does it become semantics if one function does it itself by switching on the argument count internally? Everything is syntax! Adding two floating-point value is syntax: the representation has to be parsed into sign bit, exponent and mantissa, and so on before anything happens. Sure, those fields are accessed conveniently by position, but so are the elements of the list (sign exponent mantissa), and our goalposts say that that is syntax. The parsing never stops. The CPU fetches instructions, decodes (== parsing!) and executes. When the Lisp run-time looks at a value to extract the tag bits, and then further delves into the object accordingly, it is parsing syntax.
- lispm 4y ago> The reader doesn't know about opperands or operators, but it certainly knows a symbol from an integer or string. That's the s-expression syntax. Beyond that, symbols have no special meaning for the reader. > Everything is syntax Syntax describes the structure of a language. Wikipedia: "the syntax of a computer language is the rules that defines the combinations of symbols that are considered to be correctly structured statements or expressions in that language." CLHS 1.4.1.2 "This specification uses an extended Backus Normal Form (BNF) to describe the syntax of Common Lisp macro forms and special forms." So the ANSI CL standard claims that its macro forms and special forms have syntax and that this syntax is described by an eBNF? Example: DO do ({var | (var [init-form [step-form]])}*) (end-test-form result-form*) declaration* {tag | statement}* If I try this in SBCL * (do "hello") debugger invoked on a SB-KERNEL::ARG-COUNT-ERROR in thread #<THREAD "main thread" RUNNING {1004AC01C3}>: Error while parsing arguments to DEFMACRO DO: too few elements in ("hello") to satisfy lambda list (VARLIST ENDLIST &BODY BODY): at least 2 expected, but got 1 It tells me that there is an error while parsing (!) arguments to the DEFMACRO DO. Woops? There is a parser? There is an error detected? So, beyond the the reader SBCL seems to claim it has a parser?