scriptreader.cxx

changeset 28
fb46d3d40064
parent 22
b48e10ca8832
child 30
6c4efed2dbdd
equal deleted inserted replaced
27:15c06a191f9b 28:fb46d3d40064
52 52
53 return false; 53 return false;
54 } 54 }
55 55
56 ScriptReader::ScriptReader (str path) { 56 ScriptReader::ScriptReader (str path) {
57 atnewline = false;
58 filepath = path;
59 if (!(fp = fopen (path, "r"))) { 57 if (!(fp = fopen (path, "r"))) {
60 error ("couldn't open %s for reading!\n", path.chars ()); 58 error ("couldn't open %s for reading!\n", path.chars ());
61 exit (1); 59 exit (1);
62 } 60 }
63 61
62 filepath = path;
64 curline = 1; 63 curline = 1;
65 curchar = 1; 64 curchar = 1;
66 pos = 0; 65 pos = 0;
67 token = ""; 66 token = "";
67 atnewline = false;
68 commentmode = 0;
68 } 69 }
69 70
70 ScriptReader::~ScriptReader () { 71 ScriptReader::~ScriptReader () {
72 FinalChecks ();
71 fclose (fp); 73 fclose (fp);
72 } 74 }
73 75
74 char ScriptReader::ReadChar () { 76 char ScriptReader::ReadChar () {
75 char* c = (char*)malloc (sizeof (char)); 77 char* c = (char*)malloc (sizeof (char));
88 90
89 curchar++; 91 curchar++;
90 return c[0]; 92 return c[0];
91 } 93 }
92 94
95 char ScriptReader::PeekChar (int offset) {
96 // Store current position
97 long curpos = ftell (fp);
98
99 // Forward by offset
100 fseek (fp, offset, SEEK_CUR);
101
102 // Read the character
103 char* c = (char*)malloc (sizeof (char));
104 if (!fread (c, sizeof (char), 1, fp))
105 return 0;
106
107 // Rewind back
108 fseek (fp, curpos, SEEK_SET);
109
110 return c[0];
111 }
112
93 // true if was found, false if not. 113 // true if was found, false if not.
94 bool ScriptReader::Next () { 114 bool ScriptReader::Next () {
95 str tmp = ""; 115 str tmp = "";
116
96 while (!feof (fp)) { 117 while (!feof (fp)) {
118 // Check if the next token possibly starts a comment.
119 if (PeekChar () == '/' && !tmp.len()) {
120 char c2 = PeekChar (1);
121 // C++-style comment
122 if (c2 == '/')
123 commentmode = 1;
124 else if (c2 == '*')
125 commentmode = 2;
126
127 // We don't need to actually read in the
128 // comment characters, since they will get
129 // ignored due to comment mode anyway.
130 }
131
97 c = ReadChar (); 132 c = ReadChar ();
133
134 // If this is a comment we're reading, check if this character
135 // gets the comment terminated, otherwise ignore it.
136 if (commentmode > 0) {
137 if (commentmode == 1 && c == '\n') {
138 // C++-style comments are terminated by a newline
139 commentmode = 0;
140 continue;
141 } else if (commentmode == 2 && c == '*') {
142 // C-style comments are terminated by a `*/`
143 if (PeekChar() == '/') {
144 commentmode = 0;
145 // Now the char has to be read in since we
146 // no longer are reading a comment
147 ReadChar ();
148 }
149 }
150
151 // Otherwise, ignore it.
152 continue;
153 }
98 154
99 // Non-alphanumber characters (sans underscore) break the word too. 155 // Non-alphanumber characters (sans underscore) break the word too.
100 // If there was prior data, the delimeter pushes the cursor back so 156 // If there was prior data, the delimeter pushes the cursor back so
101 // that the next character will be the same delimeter. If there isn't, 157 // that the next character will be the same delimeter. If there isn't,
102 // the delimeter itself is included (and thus becomes a token itself.) 158 // the delimeter itself is included (and thus becomes a token itself.)
242 case RETURNVAL_INT: MustNumber (); break; 298 case RETURNVAL_INT: MustNumber (); break;
243 case RETURNVAL_STRING: MustString (); break; 299 case RETURNVAL_STRING: MustString (); break;
244 case RETURNVAL_BOOLEAN: MustBool (); break; 300 case RETURNVAL_BOOLEAN: MustBool (); break;
245 } 301 }
246 } 302 }
303
304 // Checks to be performed at the end of file
305 void ScriptReader::FinalChecks () {
306 // If comment mode is 2 by the time the file ended, the
307 // comment was left unterminated. 1 is no problem, since
308 // it's terminated by newlines anyway.
309 if (commentmode == 2)
310 ParserError ("unterminated `/*`-style comment");
311 }

mercurial