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