1 
2 #include "yacas/lispparser.h"
3 #include "yacas/lispatom.h"
4 #include "yacas/lispenvironment.h"
5 #include "yacas/lisperror.h"
6 
LispParser(LispTokenizer & aTokenizer,LispInput & aInput,LispEnvironment & aEnvironment)7 LispParser::LispParser(LispTokenizer& aTokenizer,
8                        LispInput& aInput,
9                        LispEnvironment& aEnvironment) :
10     iTokenizer(aTokenizer),
11     iInput(aInput),
12     iEnvironment(aEnvironment),
13     iListed(false)
14 {
15 }
16 
Parse(LispPtr & aResult)17 void LispParser::Parse(LispPtr& aResult)
18 {
19     aResult = nullptr;
20 
21     // Get token.
22     const LispString* token =
23         iEnvironment.HashTable().LookUp(iTokenizer.NextToken(iInput));
24 
25     if (token->empty()) {
26         aResult = iEnvironment.iEndOfFile->Copy();
27         return;
28     }
29     ParseAtom(aResult, token);
30 }
31 
ParseAtom(LispPtr & aResult,const LispString * aToken)32 void LispParser::ParseAtom(LispPtr& aResult, const LispString* aToken)
33 {
34     // if token is empty string, return null pointer (no expression)
35     if (aToken->empty())
36         return;
37     // else if token is "(" read in a whole array of objects until ")",
38     //   and make a sublist
39     if (aToken == iEnvironment.iBracketOpen->String()) {
40         LispPtr subList;
41         ParseList(subList);
42         aResult = LispSubList::New(subList);
43         return;
44     }
45     // else make a simple atom, and return it.
46     aResult = LispAtom::New(iEnvironment, *aToken);
47 }
48 
ParseList(LispPtr & aResult)49 void LispParser::ParseList(LispPtr& aResult)
50 {
51     LispPtr* iter = &aResult;
52     if (iListed) {
53         aResult = iEnvironment.iList->Copy();
54         iter = &(aResult->Nixed());
55     }
56     for (;;) {
57         // Get token.
58         const LispString* token =
59             iEnvironment.HashTable().LookUp(iTokenizer.NextToken(iInput));
60 
61         // if token is empty string, error!
62         if (token->empty())
63             throw InvalidToken();
64 
65         // if token is ")" return result.
66         if (token == iEnvironment.iBracketClose->String())
67             return;
68 
69         // else parse simple atom with Parse, and append it to the
70         // results list.
71         ParseAtom(*iter, token);
72         iter = &((*iter)->Nixed());
73     }
74 }
75 
Print(const LispPtr & aExpression,std::ostream & aOutput,LispEnvironment & aEnvironment)76 void LispPrinter::Print(const LispPtr& aExpression,
77                         std::ostream& aOutput,
78                         LispEnvironment& aEnvironment)
79 {
80     PrintExpression(aExpression, aOutput, aEnvironment, 0);
81 }
82 
Indent(std::ostream & aOutput,int aDepth)83 void LispPrinter::Indent(std::ostream& aOutput, int aDepth)
84 {
85     aOutput.put('\n');
86     int i;
87     for (i = aDepth; i > 0; i--) {
88         aOutput.write("  ", 2);
89     }
90 }
91 
PrintExpression(const LispPtr & aExpression,std::ostream & aOutput,LispEnvironment & aEnvironment,int aDepth)92 void LispPrinter::PrintExpression(const LispPtr& aExpression,
93                                   std::ostream& aOutput,
94                                   LispEnvironment& aEnvironment,
95                                   int aDepth)
96 {
97     const LispPtr* iter = &aExpression;
98     int item = 0;
99     while (!!(*iter)) {
100         // if String not null pointer: print string
101         const LispString* string = (*iter)->String();
102 
103         if (string) {
104             aOutput << *string << ' ';
105         } // else print "(", print sublist, and print ")"
106         else if ((*iter)->SubList()) {
107             if (item != 0) {
108                 Indent(aOutput, aDepth + 1);
109             }
110             aOutput.put('(');
111             PrintExpression(
112                 *((*iter)->SubList()), aOutput, aEnvironment, aDepth + 1);
113             aOutput.put(')');
114             item = 0;
115         } else {
116             aOutput << "[GenericObject]";
117         }
118         iter = &((*iter)->Nixed());
119         item++;
120     } // print next element
121 }
122 
123 // does nothing in the LispPrinter but is used in derived classes
124 
RememberLastChar(char aChar)125 void LispPrinter::RememberLastChar(char aChar) {}
126