freenode/#lisp - IRC Chatlog
Search
6:59:17
vtomole
I don't know where to ask this, but I've been trying to implement a lisp parser in C using recursive decent, and it's recursive more than in should. I've looked at it for a week now, so this is my last resort:https://gist.github.com/vtomole/5ec6bb35080c3c544682eaa58c19604e
7:05:16
jasom
vtomole: unless it's specifically a common lisp parser, that's off-topic here, perhaps ##lisp? One on-topic answer I can give you is to point you to http://clhs.lisp.se/Body/02_b.htm which describes the algorithm used by common lisp for parsing
7:06:18
jasom
jasom: http://www.lispworks.com/documentation/HyperSpec/Body/02_da.htm describes the default behavior of the "(" character
7:08:17
vtomole
Yeah. I've read those, and I'm pretty sure my implementation idoes it. There is just a small bug with mine. It recurses more than it should using a token list
7:08:19
jasom
The core algorithm is a very simple parser with essentially only 1 character lookahead
7:09:21
jasom
vtomole: slight nit-pick; you do not use that algorithm, since it is character based and you are tokenizing your parens
7:14:47
jasom
consider perhaps using a debugger to inspect your call stacks, that would make what is going on obvious
7:16:49
vtomole
next for token_list? That's what I had earlier. I switch it back to that after the remove front segfaults
7:19:38
vtomole
token list before car :+ ( - 2 3 ) 7 ). token list after car: + ( - 2 3 ) 7 ) ( - 2 3 ) 7 ) - 2 3 ) 7 )
7:23:55
jasom
hmm, I would expect that you'd end up with a cons containing two pluses, but I can't see all the code, so don't know for sure
7:25:26
jasom
parse_pair is called with a token list beginning with the token before the CAR. That is very counterintuitive
7:27:42
beach
vtomole: A function such as parse_pair or atom must return two things, the result of the parse, and the remaining token list. Otherwise, you will end up calling the same function over and over again on the same list of tokens.
7:29:11
vtomole
jasom: Sorry sorry it is. i forgot to change that, but is call strcmp, but i don't have to type "==0".
7:30:03
beach
vtomole: Also, in parse_pair, once you parse the CAR, you parse the CDR by calling parse_pair, but parse_pair starts by removing the first token, assuming it is an opening parenthesis, but that is not the case for the remainder of the list of tokens.
7:30:23
jasom
vtomole: alternatively to returning the remaining token list, you can destructively modify it, since lisp's parsing algorithm will never backtrack. But you need *some* way of signaling how much was parsed
7:32:31
vtomole
jasom: I tried destructively modfiying it by calling a remove_front() procedure, but that caused a segfault after a couple of calls to parse_pair()
7:33:11
jasom
vtomole: destructively modifying it is perhaps harder to get right, but getting anything right without planning it out is going to be hard
7:33:21
vtomole
beach: Would removing the token from the list be a better solution than returning two things?
7:33:45
jasom
vtomole: for returning multiple values in C, it is idiomatic to have the return value be an indication of success, and then pass all of the "output" values as pointer parameters
7:35:33
beach
vtomole: You need to return two things, both the result of the parse, and the remaining tokens. But you can do it as jasom says, or you can return a struct.
7:36:07
jasom
so e.g. int parse(object **parsedObject, token_list ** tokenList); // which is invoked like {object *result; if(parse(&result, &theList)) ...
7:46:27
beach
vtomole: And you need to remove the left parenthesis before calling parse_pair. And parse_pair should be renamed. Call it parse_list instead, because the list can be empty.
7:48:00
pjb
vtomole: you cannot implement a Common Lisp parser without implementing the whole Common Lisp. Read chapter 2.
7:48:01
beach
vtomole: By having blank lines, there are fewer lines displayed simultaneously, making it harder to read.
7:48:49
beach
pjb: vtomole has some more fundamental problems with programming in general that we need to address first.
7:56:37
pjb
vtomole: you could use an enum for the token type instead of strings. This would simplify testing, and also it would be faster.
7:57:24
vtomole
Yeah. I'm going to do that now that it works. I always try to get a dirty implementation working first.
7:58:11
pjb
vtomole: you should start by writing the grammar you want to parse. Then you can either implement the parser by hand, or use a parser generator from the grammar.
7:58:48
pjb
Using flex and bison (or lex and yacc), you could implement the lexer and parser in 2 hours.
8:09:38
beach
vtomole: Then, when you get this version to work, I suggest you rewrite it completely using getchar() so that it will be closer to what Common Lisp READ does. As you can see from the Common Lisp HyperSpec, the Common Lisp READ function does not tokenize first.
8:10:31
beach
vtomole: Also, by using getchar() you don't have to return two values, since the stream is destructively modified by getchar().
8:11:43
beach
vtomole: Section 2.2 of the Common Lisp HyperSpec is very detailed and phrased in terms of an input stream.
8:32:37
loke`
On page 24, the following sentence can be foundL “The commas in writing S-expressions may be omitted. This is an accident.”
8:33:54
pjb
Yes, the initial sexp syntax used comma instead of space, so symbols could have space in their name!
8:35:18
pjb
loke`: see: http://informatimago.com/develop/lisp/com/informatimago/small-cl-pgms/m-expression/index.html
8:55:23
loke`
pjb: I saw that in the original paper from McCarthy. But I didn't know how it worked in LISP 1
8:56:00
loke`
So are you saying that spaces was not allowed in symbols in LISP 1, but it was intended to work just like the original paper?
8:57:11
loke`
This means that they have four different notations in this document: Maths, M-exprs, comma-separated expr and finally, the actual sexprs used in the implementation.
8:59:04
loke`
It's clear that at the time of writing, they still saw sexprs as being a hack, and something to be replaced by m-exprs at a later time.
9:01:47
loke`
Hmm, they use the term SAP in this document. It seems the history of that term's use in SBCL dates back to the beginning.
14:40:56
Josh_2
Was about you saying you worked in a warehouse or a factory, something like that a long while ago
14:43:24
jmercouris
Can someone please explain to me why in CLOS we define both an accessor and a slot name?
14:44:19
oleo
jmercouris, when the class layer abstraction terminology has to be different than the application layer terminology maybe ?
14:44:35
kami
orivej: I'm trying to (ql:quickload :quickdist) and get an error re com.informatimago.common-lisp.lisp-reader. Does it work for you?
14:45:59
jmercouris
beach: Also you are right, the struct type way of naming acessors is unbelievably verbose and painful
14:46:04
Shinmera
eudoxia: Accessors can also have around, after/before, so you can implement checks and computations.
14:47:30
jmercouris
beach: Yeah you said it like a month or so ago, I've only now found myself agreeing with it
14:48:22
jmercouris
Shinmera: So basically this aids in the encapsulation by being able to effectively define something akin to "setters" and "getters" in java?
14:48:41
Shinmera
It's just much more convenient than setters and getters, so you don't notice it usually.
14:49:50
kami
orivej: where does the system c.i.c-l.lisp-reader gets loaded from in your case? Is it in Quicklisp?
14:52:09
orivej
kami: sorry, no, it is from the commit a1ef00b of my checkout of lisp-reader. Feel free to fix it and submit a PR, or I'll look into it in a few days.
15:01:27
kami
orivej: what exactly is 'my checkout of lisp-reader'? I assumed you forked com.informatimago either on gitlab or on github, but don't find anything.
15:03:41
orivej
kami: it is not a fork, just a checkout of the source repo: https://github.com/informatimago/lisp/tree/a1ef00b
15:29:47
jmercouris
I'm trying to include parenscript in my program (which I distribute as a binary), I see the function (ps:ps-compile-stream), so I should be able to compile parenscript into javascript from some stream
15:30:13
jmercouris
Therefore, my question is, where, and how to save my parenscript such that I can load it using ps-compile-stream
15:31:52
eudoxia
you can use asdf:system-relative-pathname to get the absolute path of a file in your source tree
15:32:08
jmercouris
eudoxia: A good idea, but when I compile my program, I don't ship it with ASDF in the image
15:32:46
eudoxia
this would require building an ASDF extension, but I'm certain someone must've built one for parenscript
15:34:00
eudoxia
oh, apparently I have https://github.com/eudoxia0/asdf-linguist/blob/master/src/www/js.lisp#L20
15:34:03
jmercouris
eudoxia: It says here: http://quickdocs.org/asdf-linguist/ that you yourself have worked on this system
15:37:42
eudoxia
something like (defparameter +my-code+ `(progn ... parenscript code here ...)) and then use (ps:ps +my-code+)
15:39:24
jmercouris
I was about to suggest making a macro that automatically compiles parenscript inline and wraps them in defaparams
15:40:21
jmercouris
so we're looking at something like (defparameter ps-function-1 (ps:ps <ps code>))
15:41:29
jmercouris
Maybe at some latter point, if it ever actually matters, I'll make a robust way to load resources from my executable regardless of platform
15:42:06
jmercouris
I can create resources robustly, and access those created ones, what I cannot do is robustly ship resources (e.g. including parenscript file with my sources)
16:09:44
mfiano
jmercouris: the path to the asdf system may be different on a user's machine from the path when it was compiled. i have a hacky solution to that problem