├── Makefile ├── bld ├── authenticatedInstall.sh ├── genDist.sh ├── getChecksumProgram.sh ├── hexTruncate.awk ├── hyacc │ ├── GPL_license │ ├── gen_compiler.c │ ├── gen_graphviz.c │ ├── get_options.c │ ├── get_yacc_grammar.c │ ├── hyacc.1 │ ├── hyacc_path.c │ ├── hyacc_path_dos.c │ ├── hyaccmanpage │ ├── hyaccmanpage.html │ ├── hyaccpar │ ├── inst.c │ ├── lane_tracing.c │ ├── lane_tracing.h │ ├── lr0.c │ ├── makefile │ ├── mrt.c │ ├── mrt.h │ ├── queue.c │ ├── readme.txt │ ├── stack_config.c │ ├── stack_config.h │ ├── state_hash_table.c │ ├── symbol_table.c │ ├── upe.c │ ├── version.c │ ├── y.c │ └── y.h ├── hyaccMake.sh ├── lexerStructGen.cpp ├── parserStructGen.cpp ├── runTests.sh └── version.cpp ├── man └── anic.1 ├── src ├── constantDefs.h ├── driver.cpp ├── driver.h ├── genner.cpp ├── genner.h ├── globalDefs.h ├── lexer.cpp ├── lexer.h ├── lexerNodeStruct.h ├── lexerTable.txt ├── outputOperators.cpp ├── outputOperators.h ├── parser.cpp ├── parser.h ├── parserGrammar.y ├── parserNodeStruct.h ├── semmer.cpp ├── semmer.h ├── types.cpp └── types.h └── tst └── debug.ani /Makefile: -------------------------------------------------------------------------------- 1 | TARGET = anic 2 | INSTALL_PATH = /usr/local/bin 3 | MAN_PATH = /usr/share/man/man1 4 | 5 | CXX = g++ 6 | CFLAGS = -D VERSION_STRING=$(VERSION_STRING) -D VERSION_YEAR=$(VERSION_YEAR) -O$(OPTIMIZATION_LEVEL) -g -fomit-frame-pointer -ffast-math -pipe -Wall 7 | OPTIMIZATION_LEVEL = 3 8 | 9 | VERSION = "0.74" 10 | VERSION_YEAR = "2010" 11 | VERSION_STRING = "\"$(VERSION)\"" 12 | 13 | MAN_PAGE = tmp/$(TARGET).1 14 | INSTALL_SCRIPT = tmp/$(TARGET)-install 15 | UNINSTALL_SCRIPT = tmp/$(TARGET)-uninstall 16 | 17 | MAKE_PROGRAM = make 18 | HYACC_PATH = bld/hyacc 19 | 20 | PRINT_VERSION = @echo Version stamp is 21 | 22 | CORE_DEPENDENCIES = Makefile \ 23 | bin/version bld/getChecksumProgram.sh bld/hexTruncate.awk \ 24 | src/globalDefs.h src/constantDefs.h src/driver.h src/outputOperators.h \ 25 | tmp/lexerStruct.o tmp/parserStruct.h \ 26 | src/lexer.h src/parser.h src/types.h src/semmer.h src/genner.h \ 27 | src/driver.cpp src/outputOperators.cpp tmp/lexerStruct.o src/lexer.cpp src/parser.cpp src/types.cpp src/semmer.cpp src/genner.cpp 28 | 29 | TEST_FILES = tst/debug.ani 30 | 31 | 32 | 33 | ### BUILD TYPES 34 | 35 | main: start $(TARGET) 36 | 37 | all: start clean test install 38 | 39 | version: start var/versionStamp.txt 40 | @$(PRINT_VERSION) $(VERSION)."`cat var/versionStamp.txt`" 41 | 42 | test: start $(TARGET) bld/runTests.sh 43 | @chmod +x bld/runTests.sh 44 | @./bld/runTests.sh $(TARGET) -v -c $(TEST_FILES) 45 | 46 | install: start $(TARGET) man $(INSTALL_SCRIPT) bld/authenticatedInstall.sh 47 | @chmod +x bld/authenticatedInstall.sh 48 | @./bld/authenticatedInstall.sh $(INSTALL_SCRIPT) 49 | 50 | uninstall: start $(UNINSTALL_SCRIPT) 51 | @./$(UNINSTALL_SCRIPT) 52 | 53 | man: start $(MAN_PAGE).gz 54 | 55 | dist: start $(TARGET) $(MAN_PAGE).gz $(INSTALL_SCRIPT) $(UNINSTALL_SCRIPT) bld/genDist.sh 56 | @chmod +x bld/genDist.sh 57 | @./bld/genDist.sh $(TARGET) $(VERSION) $(MAN_PAGE) $(INSTALL_SCRIPT) $(UNINSTALL_SCRIPT) 58 | 59 | clean: start bld/hyaccMake.sh 60 | @echo Cleaning build output... 61 | @rm -f $(TARGET) 62 | @rm -f bin/version 63 | @rm -f bin/{lexer,parser}StructGen 64 | @chmod +x bld/hyaccMake.sh 65 | @./bld/hyaccMake.sh $(MAKE_PROGRAM) $(HYACC_PATH) clean 66 | @rm -f -R bin 67 | @rm -f $(MAN_PAGE).gz 68 | @rm -f $(INSTALL_SCRIPT) 69 | @rm -f $(UNINSTALL_SCRIPT) 70 | @rm -f $(TARGET)-*.gz 71 | @rm -f tmp/parserTable.txt 72 | @rm -f tmp/{lexer,parser}Struct.{h,cpp,o} 73 | @rm -f tmp/{lexerNode,parserNode,ruleLhsTokenString,ruleLhsTokenType,ruleRhsLength}Raw.h 74 | @rm -f -R tmp 75 | 76 | reset: start clean 77 | @echo Resetting build variables... 78 | @rm -f var/versionStamp.txt 79 | @rm -f var/testCertificate.dat 80 | @rm -R -f var 81 | 82 | purge: start uninstall reset 83 | 84 | 85 | 86 | ### SHORTCUT ALIASES 87 | 88 | a: all 89 | 90 | v: version 91 | 92 | t: test 93 | 94 | i: install 95 | 96 | u: uninstall 97 | 98 | m: man 99 | 100 | d: dist 101 | 102 | c: clean 103 | 104 | r: reset 105 | 106 | p: purge 107 | 108 | 109 | 110 | ### WRAPPER RULES 111 | 112 | start: 113 | @echo $(TARGET) ANI Compiler Makefile 114 | @echo 115 | 116 | 117 | 118 | ### BUILD AUXILIARIES 119 | 120 | # VERSION CONTROLLER 121 | 122 | bin/version: bld/version.cpp 123 | @echo Building version controller... 124 | @mkdir -p var 125 | @mkdir -p bin 126 | @$(CXX) bld/version.cpp $(CFLAGS) -o bin/version 127 | 128 | # VERSION STAMP 129 | 130 | var/versionStamp.txt: $(CORE_DEPENDENCIES) 131 | @echo Stamping version... 132 | @mkdir -p var 133 | @chmod +x bld/getChecksumProgram.sh 134 | @./bin/version $(VERSION) var/versionStamp.txt "`date | \` ./bld/getChecksumProgram.sh \` | awk -f bld/hexTruncate.awk`" 135 | $(PRINT_VERSION) $(VERSION)."`cat var/versionStamp.txt`" 136 | 137 | # INSTALLER 138 | 139 | $(INSTALL_SCRIPT): Makefile var/versionStamp.txt 140 | @echo Generating installer script... 141 | @mkdir -p tmp 142 | @printf "#!/bin/sh\n\n\ 143 | ### $(INSTALL_SCRIPT) -- generated script for installing $(TARGET) ANI Compiler v.[$(VERSION_STRING).`cat var/versionStamp.txt`]\n\n\ 144 | echo Installing binary...\n\ 145 | cp -f $(TARGET) $(INSTALL_PATH)/$(TARGET)\n\ 146 | echo Installing man page...\n\ 147 | cp -f $(MAN_PAGE).gz $(MAN_PATH)\n\ 148 | echo Installation complete.\n\ 149 | exit" > $(INSTALL_SCRIPT) 150 | @chmod +x $(INSTALL_SCRIPT) 151 | 152 | $(UNINSTALL_SCRIPT): Makefile 153 | @echo Generating uninstaller script... 154 | @mkdir -p tmp 155 | @printf "#!/bin/sh\n\n\ 156 | ### $(UNINSTALL_SCRIPT) -- generated script for uninstalling $(TARGET) ANI Compiler\n\n\ 157 | echo Uninstalling man page...\n\ 158 | rm -f $(MAN_PATH)/$(TARGET).1.gz\n\ 159 | echo Uninstalling binary...\n\ 160 | rm -f $(INSTALL_PATH)/$(TARGET)\n\ 161 | echo Uninstallation complete.\n\ 162 | exit" > $(UNINSTALL_SCRIPT) 163 | @chmod +x $(UNINSTALL_SCRIPT) 164 | 165 | # MANPAGE 166 | 167 | $(MAN_PAGE).gz: man/$(TARGET).1 168 | @echo Packaging man page... 169 | @gzip -9 man/$(TARGET).1 -c > $(MAN_PAGE).gz 170 | 171 | 172 | 173 | # LEXER 174 | 175 | tmp/lexerStruct.cpp: bin/lexerStructGen src/lexerTable.txt src/lexer.h 176 | @echo Generating lexer structures... 177 | @mkdir -p tmp 178 | @./bin/lexerStructGen 179 | 180 | tmp/lexerStruct.o: tmp/lexerStruct.cpp 181 | @echo Compiling lexer structure object... 182 | @$(CXX) tmp/lexerStruct.cpp $(CFLAGS) -c -o tmp/lexerStruct.o 183 | 184 | bin/lexerStructGen: bld/lexerStructGen.cpp src/globalDefs.h src/constantDefs.h 185 | @echo Building lexer structure generator... 186 | @mkdir -p bin 187 | @$(CXX) bld/lexerStructGen.cpp -o bin/lexerStructGen 188 | 189 | # PARSER 190 | 191 | tmp/parserStruct.h: bin/parserStructGen tmp/parserTable.txt tmp/lexerStruct.o src/parserNodeStruct.h 192 | @echo Generating parser structures... 193 | @mkdir -p tmp 194 | @./bin/parserStructGen 195 | 196 | bin/parserStructGen: bld/parserStructGen.cpp tmp/lexerStruct.o src/parserNodeStruct.h src/globalDefs.h src/constantDefs.h 197 | @echo Building parser structure generator... 198 | @mkdir -p bin 199 | @$(CXX) bld/parserStructGen.cpp tmp/lexerStruct.o -o bin/parserStructGen 200 | 201 | bin/hyacc: bld/hyaccMake.sh bld/hyacc/makefile 202 | @echo Building parser table generator... 203 | @mkdir -p bin 204 | @chmod +x bld/hyaccMake.sh 205 | @./bld/hyaccMake.sh $(MAKE_PROGRAM) bld/hyacc 206 | 207 | tmp/parserTable.txt: bin/hyacc src/parserGrammar.y 208 | @echo Constructing parser table... 209 | @./bin/hyacc -c -v -D1 -D2 -O1 -Q src/parserGrammar.y 210 | @mv y.output tmp/parserTable.txt 211 | 212 | 213 | 214 | ### CORE APPLICATION 215 | 216 | $(TARGET): var/versionStamp.txt 217 | @echo Building main executable... 218 | @rm -f var/testCertificate.dat 219 | @mkdir -p bin 220 | @$(CXX) src/driver.cpp src/outputOperators.cpp tmp/lexerStruct.o src/lexer.cpp src/parser.cpp src/types.cpp src/semmer.cpp src/genner.cpp \ 221 | -D VERSION_STAMP="\"`cat var/versionStamp.txt`\"" \ 222 | $(CFLAGS) \ 223 | -o $(TARGET) 224 | @chmod +x $(TARGET) 225 | @echo Done building main executable. 226 | -------------------------------------------------------------------------------- /bld/authenticatedInstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### Installation authentication script 4 | 5 | echo Running installer... 6 | 7 | if test -f var/testCertificate.dat 8 | then 9 | ./$*; 10 | else 11 | echo 12 | echo Warning: Default test cases have not been passed. To run them, use \'make test\'. 13 | printf "Proceed anyway (y/n)? " 14 | read yn 15 | case $yn in 16 | [Yy]* ) ./$*;; 17 | [Nn]* ) exit;; 18 | * ) echo "Assuming 'no'.";; 19 | esac 20 | fi 21 | exit 22 | -------------------------------------------------------------------------------- /bld/genDist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### Redistributable package generator script 4 | ### arguments: $(TARGET) $(VERSION_STRING) $(MAN_PAGE) $(INSTALL_SCRIPT) $(UNINSTALL_SCRIPT) 5 | 6 | if test ! -f $1-$2."`cat var/versionStamp.txt`".tar.gz ; then 7 | echo Packing redistributable... 8 | ls $1.exe 1> /dev/null 2> /dev/null 9 | if test $? = 0 ; then 10 | tar -cf $1-$2."`cat var/versionStamp.txt`".tar $1.exe $3.gz $4 $5 11 | else 12 | tar -cf $1-$2."`cat var/versionStamp.txt`".tar $1 $3.gz $4 $5 13 | fi 14 | gzip -f $1-$2."`cat var/versionStamp.txt`".tar 15 | echo Done packing to $1-$2."`cat var/versionStamp.txt`".tar.gz 16 | fi 17 | exit 18 | -------------------------------------------------------------------------------- /bld/getChecksumProgram.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### Checksum program location script 4 | 5 | # Cygwin/Linux 6 | type sha256sum > /dev/null 7 | if test $? = 0 8 | then 9 | printf "sha256sum" 10 | exit 11 | fi 12 | 13 | # Mac OSX / Sun OS 14 | type shasum > /dev/null 15 | if test $? = 0 16 | then 17 | printf "shasum" 18 | exit 19 | fi 20 | 21 | # FreeBSD 22 | type sha256 > /dev/null 23 | if test $? = 0 24 | then 25 | printf "sha256" 26 | exit 27 | fi 28 | 29 | echo Cannot find checksum program! > 2 30 | exit 1 31 | -------------------------------------------------------------------------------- /bld/hexTruncate.awk: -------------------------------------------------------------------------------- 1 | BEGIN { 2 | for (i = 0; i < 10; i++) 3 | hex[i] = i 4 | hex["a"] = hex["A"] = 10 5 | hex["b"] = hex["B"] = 11 6 | hex["c"] = hex["C"] = 12 7 | hex["d"] = hex["D"] = 13 8 | hex["e"] = hex["E"] = 14 9 | hex["f"] = hex["F"] = 15 10 | } 11 | 12 | { 13 | hexVal = $0 14 | for (i = 1; i <= length(hexVal) && decVal <= 99999999; i++) 15 | decVal = int(decVal)*16 + hex[substr(hexVal, i, 1)] 16 | printf "%s", substr(int(decVal),1,8) 17 | } 18 | -------------------------------------------------------------------------------- /bld/hyacc/gen_graphviz.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Hyacc, a LR(0)/LALR(1)/LR(1) parser generator. 3 | Copyright (C) 2007 Xin Chen. chenx@hawaii.edu 4 | 5 | Hyacc is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Hyacc is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Hyacc; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /* 21 | * graphviz.c 22 | * 23 | * To produce an input file for graphviz. 24 | * 25 | * @author: Xin Chen 26 | * @created on: 12/14/2007 27 | * @last modified: 12/15/2007 28 | * @Copyright (C) 2007 29 | */ 30 | 31 | #include "y.h" 32 | 33 | #define DEBUG_GEN_GVIZ 0 34 | 35 | 36 | typedef struct _gvNode gvNode; 37 | struct _gvNode { 38 | int target_state; 39 | SymbolNode * labels; 40 | SymbolNode * labels_tail; 41 | gvNode * next; 42 | }; 43 | 44 | 45 | static gvNode * createGvNode(int targetState) { 46 | gvNode * gvn; 47 | HYY_NEW(gvn, gvNode, 1); 48 | gvn->target_state = targetState; 49 | gvn->labels = NULL; 50 | gvn->labels_tail = NULL; 51 | gvn->next = NULL; 52 | return gvn; 53 | } 54 | 55 | 56 | static void destroyGvNode(gvNode * n) { 57 | if (NULL == n) return; 58 | freeSymbolNodeList(n->labels); 59 | free(n); 60 | } 61 | 62 | 63 | static void destroyGvNodeList(gvNode * list) { 64 | gvNode * tmp; 65 | if (NULL == list) return; 66 | while ((tmp = list) != NULL) { 67 | list = list->next; 68 | destroyGvNode(tmp); 69 | } 70 | } 71 | 72 | 73 | static gvNode * findGvNodeInList(gvNode * list, int targetState) { 74 | if (NULL == list) return NULL; 75 | while (list != NULL) { 76 | if (list->target_state == targetState) return list; 77 | list = list->next; 78 | } 79 | return NULL; 80 | } 81 | 82 | 83 | /* 84 | * find label in label list. 85 | */ 86 | static void insertLabelToList(gvNode * n, SymbolTblNode * snode) { 87 | if (NULL == n || NULL == snode) return; // should not happen. 88 | 89 | if (NULL == n->labels) { 90 | n->labels = n->labels_tail = createSymbolNode(snode); 91 | } else { 92 | SymbolNode * m = n->labels; 93 | while (m->next != NULL) { 94 | if (m->snode == snode) return; // already exists. 95 | m = m->next; 96 | } 97 | // now m->next == NULL 98 | if (m->snode == snode) return; // exists as the last one. 99 | // else, not exist. 100 | m->next = createSymbolNode(snode); 101 | } 102 | } 103 | 104 | 105 | /* 106 | * If exists a node n in list, s.t. 107 | * n->target_state == targetState, then add snode to n->label_list. 108 | * else 109 | * create a new node and insert it to list. 110 | */ 111 | static gvNode * addGvNodeToList(gvNode * list, 112 | int targetState, SymbolTblNode * snode) { 113 | gvNode * n = findGvNodeInList(list, targetState); 114 | if (NULL == n) { // targetState NOT found. Add to list. 115 | #if DEBUG_GEN_GVIZ 116 | printf("target state %d not found (label %s)\n", 117 | targetState, snode->symbol); 118 | #endif 119 | n = createGvNode(targetState); 120 | n->labels = n->labels_tail = createSymbolNode(snode); 121 | if (NULL == list) { // first node in list. 122 | list = n; 123 | } else { // add to tail of list. 124 | gvNode * m = list; 125 | while (m->next != NULL) { m = m->next; } 126 | m->next = n; 127 | } 128 | } else { // found. 129 | // add snode to the label list of n. 130 | #if DEBUG_GEN_GVIZ 131 | printf("target state %d found, add label %s\n", 132 | targetState, snode->symbol); 133 | #endif 134 | insertLabelToList(n, snode); 135 | } 136 | return list; 137 | } 138 | 139 | 140 | /* 141 | * dump r list 142 | */ 143 | static void dumpGvNodeList_r( 144 | gvNode * list, int srcState, FILE * fp) { 145 | SymbolNode * labels; 146 | if (NULL == list) return; 147 | while (list != NULL) { 148 | fprintf(fp, " %d -> r%d [ label=\"", 149 | srcState, list->target_state); 150 | // write label list 151 | for (labels = list->labels; 152 | labels->next != NULL; labels = labels->next) { 153 | fprintf(fp, "%s,", labels->snode->symbol); 154 | } 155 | fprintf(fp, "%s", labels->snode->symbol); 156 | fprintf(fp, "\" style=\"dashed\" ];\n"); 157 | list = list->next; 158 | } 159 | } 160 | 161 | 162 | /* 163 | * dump s list 164 | */ 165 | static void dumpGvNodeList_s( 166 | gvNode * list, int srcState, FILE * fp) { 167 | SymbolNode * labels; 168 | if (NULL == list) return; 169 | while (list != NULL) { 170 | fprintf(fp, " %d -> %d [ label=\"", 171 | srcState, list->target_state); 172 | // write label list 173 | for (labels = list->labels; 174 | labels->next != NULL; labels = labels->next) { 175 | fprintf(fp, "%s,", labels->snode->symbol); 176 | } 177 | fprintf(fp, "%s", labels->snode->symbol); 178 | fprintf(fp, "\" ];\n"); 179 | list = list->next; 180 | } 181 | } 182 | 183 | 184 | static int getGvNodeListLen(gvNode * list) { 185 | int len = 0; 186 | 187 | while (list != NULL) { 188 | list = list->next; 189 | len ++; 190 | } 191 | 192 | return len; 193 | } 194 | 195 | 196 | /* 197 | * Update the reduction list if the following is satisfied: 198 | * 199 | * In case of --lr0 or --lalr: 200 | * If a reduction is the single only REDUCTION at this state, 201 | * replace it by ".". Similar to the use of final_state_list 202 | * in writing y.output. 3-11-2008. 203 | * Else (LR(1)): 204 | * If a reduction is the single only ACTION at this state, 205 | * do the same as above. 206 | * 207 | * @created on: 3/11/2008 208 | */ 209 | static gvNode * update_r_list(gvNode * r_list, gvNode * s_list) { 210 | int state; 211 | char * strAny = "(any)"; // means: any terminal can cause reduction. 212 | 213 | if (USE_LR0 || USE_LALR) { 214 | if (getGvNodeListLen(r_list) == 1) { 215 | state = r_list->target_state; 216 | destroyGvNodeList(r_list); 217 | r_list = NULL; 218 | r_list = addGvNodeToList(r_list, state, hashTbl_insert(strAny)); 219 | } 220 | } else { 221 | if (s_list == NULL && getGvNodeListLen(r_list) == 1) { 222 | state = r_list->target_state; 223 | destroyGvNodeList(r_list); 224 | r_list = NULL; 225 | r_list = addGvNodeToList(r_list, state, hashTbl_insert(strAny)); 226 | } 227 | } 228 | 229 | return r_list; 230 | } 231 | 232 | 233 | /* 234 | * Has the same logic as printParsingTable() in y.c. 235 | * For O0, O1. 236 | */ 237 | void gen_graphviz_input() { 238 | char action; 239 | int state; 240 | int row, col; 241 | int row_size = ParsingTblRows; 242 | int col_size = ParsingTblCols; 243 | SymbolTblNode * n; 244 | gvNode * r_list; 245 | gvNode * s_list; 246 | FILE * fp_gviz; 247 | 248 | if ((fp_gviz = fopen(y_gviz, "w")) == NULL) { 249 | printf("cannot open file %s\n", y_gviz); 250 | return; 251 | } 252 | 253 | fputs("digraph abstract {\n\n", fp_gviz); 254 | fputs(" node [shape = doublecircle]; 0 acc;\n", fp_gviz); 255 | fputs(" node [shape = circle];\n", fp_gviz); 256 | 257 | for (row = 0; row < row_size; row ++) { 258 | r_list = NULL; 259 | s_list = NULL; 260 | 261 | for (col = 0; col < ParsingTblCols; col ++) { 262 | n = ParsingTblColHdr[col]; 263 | if (isGoalSymbol(n) == FALSE) { 264 | getAction(n->type, col, row, & action, & state); 265 | /* printf("%c%d\t", action, state); */ 266 | if (action == 0) { 267 | /* do nothing */ 268 | } else if (action == 'r') { 269 | r_list = addGvNodeToList(r_list, state, n); 270 | } else if (action == 's' || action == 'g') { 271 | s_list = addGvNodeToList(s_list, state, n); 272 | } else if (action == 'a') { 273 | fprintf(fp_gviz, " %d -> acc [ label = \"%s\" ];\n", 274 | row, n->symbol); 275 | } 276 | } // end of if 277 | } // end of for. 278 | 279 | r_list = update_r_list(r_list, s_list); 280 | 281 | dumpGvNodeList_r(r_list, row, fp_gviz); 282 | dumpGvNodeList_s(s_list, row, fp_gviz); 283 | destroyGvNodeList(r_list); 284 | destroyGvNodeList(s_list); 285 | } 286 | 287 | fputs("\n}\n", fp_gviz); 288 | fclose(fp_gviz); 289 | } 290 | 291 | 292 | /* 293 | * Has the same logic as printCondensedFinalParsingTable() in y.c. 294 | * For O2, O3. 295 | */ 296 | void gen_graphviz_input2() { 297 | SymbolTblNode * n; 298 | char action; 299 | int row, col, i, state, srcState; 300 | int col_size = ParsingTblCols; 301 | /* value assigned at the end of generate_parsing_table(). */ 302 | int row_size = ParsingTblRows; 303 | gvNode * r_list; 304 | gvNode * s_list; 305 | FILE * fp_gviz; 306 | 307 | if ((fp_gviz = fopen(y_gviz, "w")) == NULL) { 308 | printf("cannot open file %s\n", y_gviz); 309 | return; 310 | } 311 | 312 | fputs("digraph abstract {\n\n", fp_gviz); 313 | fputs(" node [shape = doublecircle]; 0 acc;\n", fp_gviz); 314 | fputs(" node [shape = circle];\n", fp_gviz); 315 | 316 | i = 0; 317 | for (row = 0; row < row_size; row ++) { 318 | r_list = NULL; 319 | s_list = NULL; 320 | if (isReachableState(row) == TRUE) { 321 | for (col = 0; col < ParsingTblCols; col ++) { 322 | n = ParsingTblColHdr[col]; 323 | if (isGoalSymbol(n) == FALSE && isParentSymbol(n) == FALSE) { 324 | getAction(n->type, col, row, & action, & state); 325 | if (action == 's' || action == 'g') 326 | state = getActualState(state); 327 | /* yyprintf3("%c%d\t", action, state); */ 328 | if (action == 0) { 329 | /* do nothing */ 330 | } else if (action == 'r') { 331 | r_list = addGvNodeToList(r_list, state, n); 332 | } else if (action == 's' || action == 'g') { 333 | s_list = addGvNodeToList(s_list, state, n); 334 | } else if (action == 'a') { 335 | fprintf(fp_gviz, " %d -> acc [ label = \"%s\" ];\n", 336 | row, n->symbol); 337 | } 338 | } 339 | } 340 | i ++; 341 | 342 | r_list = update_r_list(r_list, s_list); 343 | 344 | srcState = getActualState(row); 345 | dumpGvNodeList_r(r_list, srcState, fp_gviz); 346 | dumpGvNodeList_s(s_list, srcState, fp_gviz); 347 | destroyGvNodeList(r_list); 348 | destroyGvNodeList(s_list); 349 | } /* end if */ 350 | } 351 | 352 | fputs("\n}\n", fp_gviz); 353 | fclose(fp_gviz); 354 | } 355 | 356 | -------------------------------------------------------------------------------- /bld/hyacc/hyacc.1: -------------------------------------------------------------------------------- 1 | .TH HYACC 1 "Version 0.95: 15 March 2009" 2 | .SH NAME 3 | hyacc \- LR(0)/LALR(1)/LR(1) parser generator. Similar utility as yacc and bison. 4 | .SH SYNOPSIS 5 | .B "hyacc -?" 6 | .br 7 | .B "hyacc -h" 8 | .br 9 | .B "hyacc --help" 10 | .br 11 | .B "hyacc -V" 12 | .br 13 | .B "hyacc --version" 14 | .br 15 | .B "hyacc [-bcCdDghlmnoOPQRStvV]" 16 | .br 17 | .B " [-b file-name-prefix] [--file-prefix==file-name-prefix]" 18 | .br 19 | .B " [-c] [--no-compiler]" 20 | .br 21 | .B " [-C] [--keep-unit-production-with-action]" 22 | .br 23 | .B " [-d] [--defines]" 24 | .br 25 | .B " [-Di] (i = 0~15)" 26 | .br 27 | .B " [-g] [--graphviz]" 28 | .br 29 | .B " [-h] [--help]" 30 | .br 31 | .B " [-l] [--no-lines]" 32 | .br 33 | .B " [-m] [--man-page]" 34 | .br 35 | .B " [-o output-file-name] [--output-file==output-file-name]" 36 | .br 37 | .B " [-Oi] (i = 0~3)" 38 | .br 39 | .B " [-P] [--lane-tracing-pgm]" 40 | .br 41 | .B " [-Q] [--lane-tracing-ltt]" 42 | .br 43 | .B " [-R] [--lalr1]" 44 | .br 45 | .B " [-S] [--lr0]" 46 | .br 47 | .B " [-t] [--debug]" 48 | .br 49 | .B " [-v] [--verbose]" 50 | .br 51 | .B " [-V] [--version]" 52 | .br 53 | 54 | .SH DESCRIPTION 55 | .I Hyacc 56 | is a program similar to 57 | .IR yacc (1) 58 | and 59 | .I bison 60 | (LALR(1) parser generators), but which accepts all LR(1) grammars 61 | and thus is more powerful than 62 | .IR yacc (1) 63 | and 64 | .IR bison . 65 | It is backward compatible with input files of 66 | .IR yacc (1) 67 | and 68 | .IR bison . 69 | Hyacc also supports LALR(1) (based on lane-tracing) and LR(0). 70 | 71 | Input files should better follow the yacc convention of ending in .y, 72 | but don't have to. By default, the output file is y.tab.c. When 73 | you use -d you also get y.tab.h, and when you use -v you also get 74 | y.output, same as yacc. The user can use the -b or -o switches to 75 | specify the output file names. 76 | 77 | Hyacc supports both traditional single letter options and 78 | mnemonic long option names. Long option names are indicated 79 | with -- instead of -. When a long option takes an argument, 80 | like file-prefix, connect the option name and the argument 81 | with ==. 82 | 83 | .SS OPTIONS 84 | Command line options are decribed below. 85 | .PP 86 | Most options may be give in one of two forms: 87 | either a dash followed by a single letter, 88 | or two dashes followed by a long option name. 89 | 90 | .TP 91 | .BI "-b fileprefix" 92 | .br 93 | .ns 94 | .TP 95 | .BI "--file-prefix==fileprefix" 96 | Specify a prefix to use for all hyacc output file names. 97 | The names are chosen as if the input file were named 98 | fileprefix.c. 99 | 100 | .TP 101 | .BI "-c" 102 | .br 103 | .ns 104 | Use this switch to not generate parser files (y.tab.c and y.tab.h). 105 | This is useful when the user only wants to use the -v and -D 106 | switches to parse the grammar and check the y.output file 107 | about the grammar's information. 108 | 109 | -c generally is used with -v, -D and -C. 110 | 111 | .TP 112 | .BI "-C" 113 | .br 114 | .ns 115 | For the unit production removal optimization (when -O2 or -O3 116 | is used), if a unit production rule has semantic action, 117 | when it is removed the semantic action won't be preserved, so the 118 | output compiler will miss some code. 119 | 120 | To solve this problem, by default 121 | HYACC adds a placeholder nonterminal to unit production rules 122 | with actions, so they won't be removed. E.g., from 123 | .br 124 | program : expression {printf("answer = %d\\n", $1);} 125 | ; 126 | .br 127 | to 128 | .br 129 | program : expression $PlaceHolder {printf("answer = %d\\n", $1);} 130 | ; 131 | .br 132 | $PlaceHolder : /* empty */ 133 | ; 134 | 135 | If the -C switch is used, this default action will not be taken. 136 | This is used when the user wants to just parse the grammar and 137 | does not care about generating a useful compiler. Specifically, 138 | -C is used together with switch -c. 139 | 140 | .TP 141 | .BI "-d" 142 | .br 143 | .ns 144 | .TP 145 | .BI "--define" 146 | Write an extra output file containing macro definitions for 147 | the token type names defined in the grammar. 148 | 149 | The file is named y.tab.h. 150 | 151 | This output file is essential if you wish to put the definition 152 | of yylex in a separate source file, because yylex needs to be 153 | able to refer to token type codes and the variable yylaval. 154 | In such case y.tab.h should be included into the file containing 155 | yylex. 156 | 157 | .TP 158 | .BI "-D" 159 | .br 160 | .ns 161 | Change the print option to debug file y.output. A user who 162 | checks the debug file should assume certain degree of 163 | knowledge to the LR(1) compiler theory and optimization algorithms. 164 | 165 | If the -v options is used, a debug file y.output will be 166 | generated when hyacc parses the grammar file. Use of 167 | -D switch will automatically turn on the -v switch, 168 | and will allow to specify what kind of information to be included into 169 | y.output. 170 | 171 | By default, use -v will output the information about the states, 172 | plus a short statistics summary of the number of 173 | the grammar's terminals, nonterminals, grammar rules and states. 174 | like the y.output file of yacc. 175 | 176 | -D should be followed by a parameter from 0 ~ 14: 177 | 178 | -D0 179 | .br 180 | Include all the information available. 181 | 182 | -D1 183 | .br 184 | Include the grammar. 185 | 186 | -D2 187 | .br 188 | Include the parsing table. 189 | 190 | -D3 191 | .br 192 | Include the process of generating the parsing 193 | machine, basically, the number of states and the current state 194 | in each cycle. 195 | 196 | -D4 197 | .br 198 | This is useful only if at the time of compilation, in y.h 199 | USE_CONFIG_QUEUE_FOR_GET_CLOSURE is set to 0. 200 | This then will include the information of combining compatible 201 | configurations: the number of configurations before and 202 | after the combination. -D4 can be used together with -D3. 203 | 204 | -D5 205 | .br 206 | Include the information of the multi-rooted tree(s) 207 | built for the optimization of removing unit productions. 208 | 209 | -D6 210 | .br 211 | Include the information 212 | in the optimization of removing unit productions. Specifically, 213 | the new states created and the original states from which 214 | the new states are combined from. 215 | 216 | -D7 217 | .br 218 | Include the information of the step 4 in the 219 | optimization of removing unit productions. Specifically, 220 | this shows the states reachable from state 0. 221 | 222 | -D8 223 | .br 224 | Show the entire parsing table after removing unit 225 | productions, including those states that will be removed. 226 | 227 | -D9 228 | .br 229 | Show a list of configurations and the theads of 230 | the strings after the scanning symbol. 231 | 232 | -D10 233 | .br 234 | Include information of the symbol hash table. 235 | 236 | -D11 237 | .br 238 | Include the information of shift/shift conflicts 239 | if any. This happens when the input grammar is not LR(1) 240 | or ambiguous, and the optimization of removing unit production 241 | is used. The occurrence of shift/shift conflicts means 242 | the optimization of removing unit productions (-O2 and -O3) cannot 243 | be applied to this grammar. 244 | 245 | -D12 246 | .br 247 | NOT to include the default information about states 248 | when the -v option is used. Use -D12 to show only the short 249 | statistics summary, and not the states list. 250 | 251 | -D13 252 | .br 253 | Include the statistics of configurations for each state, 254 | and also dump the state hash table. 255 | 256 | -D14 257 | .br 258 | Include the information of actual/pseudo states. 259 | An actual state number is the row number of that state in 260 | the parsing table. After the step of unit production removal, 261 | some states are removed but their rows still remain in the 262 | parsing table, thus the state's pseudo state number (counted 263 | by ignoring those removed states/rows) will be different. 264 | 265 | -D15 266 | .br 267 | Shows the originator and transitor list of each configuration, 268 | as well as the parent state list of each state. 269 | This is relevant when lane tracing is used. 270 | 271 | 272 | .TP 273 | .BI "-g" 274 | .br 275 | .ns 276 | .TP 277 | .BI "--graphviz" 278 | Generate a graphviz input file for the parsing machine. 279 | 280 | 281 | .TP 282 | .BI "-h" 283 | .br 284 | .ns 285 | .TP 286 | .BI "--help" 287 | Print a usage summary of hyacc. 288 | 289 | 290 | .TP 291 | .BI "-l" 292 | .br 293 | .ns 294 | .TP 295 | .BI "--nolines" 296 | Don't put any #line preprocessor commands in the parser file. 297 | Ordinarily hyacc puts them in the parser file so that the 298 | C compiler and debuggers will associate errors with your 299 | source file, the grammar file. This options causes them to 300 | associate errors with the parser file, treating it as an 301 | independent source file in its own right. 302 | 303 | .TP 304 | .BI "-m" 305 | .br 306 | .ns 307 | .TP 308 | .BI "--man-page" 309 | Show man page. Same as "man hyacc". This is used when the man page 310 | file exists in the same directory as the hyacc executable. So if 311 | installation moves this man page file to another location, you 312 | must use "man hyacc". 313 | 314 | .TP 315 | .BI "-o outfile" 316 | .br 317 | .ns 318 | .TP 319 | .BI "--output-file==outfile" 320 | Specify the name outfile for the parser file. 321 | 322 | The other output files' names are constructed from outfile 323 | as described under the v and d switches. 324 | 325 | .TP 326 | .BI "-O" 327 | .br 328 | .ns 329 | Specify the kind of optimization used to parse the yacc 330 | input file. 331 | 332 | Basically, three optimizations are used: 333 | 1) Combine compatible states based on weak compatibility. 334 | 2) Remove unit productions. 335 | 3) Remove repeated states after optimization 2). 336 | 337 | The -O switch should be followed by a parameter from 0 to 3: 338 | 339 | -O0 340 | .br 341 | No optimization is used. 342 | 343 | -O1 344 | .br 345 | Optimization 1) is used. 346 | 347 | -O2 348 | .br 349 | Optimizations 1) and 2) are used. 350 | 351 | -O3 352 | .br 353 | Optimizations 1), 2) and 3) are used. 354 | 355 | By default, when -O switch is not specified, the optimization 1) of 356 | combining compatible states is used. 357 | So "hyacc file.y" is equivalent to 358 | "hyacc file.y -O1" or "hyacc -O1 file.y". 359 | 360 | .TP 361 | .BI "-P" 362 | .br 363 | .ns 364 | .TP 365 | .BI "--lane-tracing-pgm" 366 | Use LR(1) based on the lane-tracing algorithm. The lane-tracing 367 | algorithm starts from a LR(0) parsing machine, uses 368 | lane-tracing to obtain contexts to resolve shift/reduce 369 | and reduce/reduce conflicts. If some reduce/reduce conflicts 370 | are not resolved, then state-splitting based on the 371 | practical general method is used to resolve such conflicts. 372 | 373 | .TP 374 | .BI "-Q" 375 | .br 376 | .ns 377 | .TP 378 | .BI "--lane-tracing-ltt" 379 | Use LR(1) based on the lane-tracing algorithm. The lane-tracing 380 | algorithm starts from a LR(0) parsing machine, uses 381 | lane-tracing to obtain contexts to resolve shift/reduce 382 | and reduce/reduce conflicts. If some reduce/reduce conflicts 383 | are not resolved, then state-splitting based on a 384 | lane-tracing table is used to resolve such conflicts. 385 | 386 | .TP 387 | .BI "-R" 388 | .br 389 | .ns 390 | .TP 391 | .BI "--lalr1" 392 | Use LALR(1) based on lane-tracing. 393 | 394 | .TP 395 | .BI "-S" 396 | .br 397 | .ns 398 | .TP 399 | .BI "--lr0" 400 | Use LR(0). 401 | 402 | .TP 403 | .BI "-t" 404 | .br 405 | .ns 406 | .TP 407 | .BI "--debug" 408 | In the parser files, define the macro YYDEBUG to 1 if it is 409 | not already defined, so that the debugging facilities are 410 | compiled. When the generated compiler parses an input 411 | yacc file, the parse process will be recorded in an output 412 | file y.parse, which includes all the shift/reduce actions, 413 | associated state number and lookahead, as well as the 414 | content of state stack and symbol stack. 415 | 416 | .TP 417 | .BI "-v" 418 | .br 419 | .ns 420 | .TP 421 | .BI "--verbose" 422 | Write an extra output file containing verbose descriptions 423 | of the parser states and what is done for each type of 424 | lookahead token in that state. 425 | 426 | This file also describes all the conflicts, both those 427 | resolved by operator precedence and the unresolved ones. 428 | 429 | The file's name is y.output. 430 | 431 | .TP 432 | .BI "-V" 433 | .br 434 | .ns 435 | .TP 436 | .BI "--version" 437 | Print the version number of hyacc and exit. 438 | 439 | 440 | .SS EXAMPLES 441 | 442 | Assume the input grammar file is arith.y. 443 | 444 | .TP 445 | The user wants y.tab.c only: 446 | hyacc arith.y 447 | 448 | .TP 449 | The user wants y.tab.c and y.tab.h: 450 | hyacc -d arith.y 451 | 452 | .TP 453 | The user wants the generated compiler create y.parse when parsing a program: 454 | hyacc -dt arith.y 455 | .br 456 | or 457 | .br 458 | hyacc arith.y -d -t 459 | 460 | .TP 461 | The user wants y.ta.b, y.tab.h, and create a y.output file when parsing the grammar: 462 | hyacc -dv arith.y 463 | 464 | .TP 465 | The user wants, y.tab.c, y.tab.h, y.output and wants to include no other information than the short statistics summary in y.output: 466 | hyacc -dD12 arith.y 467 | 468 | .TP 469 | Here -D12 will suppress the states list. 470 | 471 | .TP 472 | The user wants y.tab.c and y.tab.h, use optimization 1) only, and wants a default y.output: 473 | hyacc -d -O1 -v arith.y 474 | .br 475 | or 476 | .br 477 | hyacc -dO1v arith.y 478 | 479 | .TP 480 | The user wants to parse the grammar and check y.output for information, \ 481 | and doesn't need a compiler. While use all the optimizations, \ 482 | he wants to keep those unit productions with semantic actions: 483 | hyacc -cCv arith.y 484 | 485 | .SH DIAGNOSITICS 486 | Self explanatory. 487 | 488 | .SH AUTHOR 489 | .PP 490 | Xin Chen 491 | .br 492 | Send bug report or comments to the above address. 493 | .br 494 | 495 | -------------------------------------------------------------------------------- /bld/hyacc/hyacc_path.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Generated by inst.c 3 | * This file is used to retrieve files hyaccpar and hyaccmanpage. 4 | * This file is updated each time hyacc is installed. 5 | */ 6 | 7 | #include "y.h" 8 | 9 | void show_manpage() { 10 | system("less /home/ThomasXC/yacc3/sourceforge/yacc2b/hyacc/hyaccmanpage"); 11 | } 12 | 13 | char * HYACC_PATH = 14 | "/home/ThomasXC/yacc3/sourceforge/yacc2b/hyacc/hyaccpar"; 15 | 16 | -------------------------------------------------------------------------------- /bld/hyacc/hyacc_path_dos.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Hyacc, a LR(0)/LALR(1)/LR(1) parser generator. 3 | Copyright (C) 2007 Xin Chen. chenx@hawaii.edu 4 | 5 | Hyacc is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Hyacc is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Hyacc; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /* 21 | * hyacc_path_dos.c 22 | * 23 | * Retrieve files hyaccpar and hyaccmanpage. 24 | * This is used by DOS/Windows version only. 25 | * 26 | * 1) If set USE_CUR_DIR to 0: 27 | * 28 | * After compilation, put hyacc.exe, hyaccmanpage and hyaccpar 29 | * to c:\windows\. Since this folder by default is in the system 30 | * path variable, hyacc becomes a command that you can use 31 | * wherever you are in windows. 32 | * 33 | * You can also change the path here, and put hyacc and hyaccmanpage 34 | * and hyaccpar elsewhere, but then you may need to add the path 35 | * to system searchable path, so the system can find it. 36 | * 37 | * You also can remove the c:\\windows from the path here, then 38 | * hyacc will search in the current directory for them. 39 | * 40 | * 2) Otherwise, if set USE_CUR_DIR to 1: 41 | * 42 | * Then hyacc searches in the current directory. 43 | * 44 | * @Author: Xin Chen 45 | * @Date started: February 8, 2007 46 | * @Last modified: March 21, 2007 47 | * @Copyright (C) 2007. 48 | */ 49 | 50 | #include "y.h" 51 | 52 | #define USE_CUR_DIR 1 53 | 54 | #if USE_CUR_DIR 55 | 56 | void show_manpage() { 57 | system("more hyaccmanpage"); 58 | } 59 | 60 | char * HYACC_PATH = "hyaccpar"; 61 | 62 | #else 63 | 64 | void show_manpage() { 65 | system("more c:\\windows\\hyaccmanpage"); 66 | } 67 | 68 | char * HYACC_PATH = "c:\\windows\\hyaccpar"; 69 | 70 | #endif 71 | 72 | 73 | -------------------------------------------------------------------------------- /bld/hyacc/inst.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Hyacc, a LR(1) parser generator. 3 | Copyright (C) 2007 Xin Chen. chenx@hawaii.edu 4 | 5 | Hyacc is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Hyacc is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Hyacc; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /* 21 | * inst.c 22 | * 23 | * Used by makefile when calling 'make install'. 24 | * This will generate a new hyacc_path.c file given the 25 | * installation path, which is passed to main() as a 26 | * command line argument by makefile. 27 | * 28 | * @compile: gcc inst.c -o inst 29 | * 30 | * @Author: Xin Chen 31 | * @Created on: Feb 10, 2007 32 | * @Last updated: Feb 10, 2007 33 | */ 34 | 35 | #include 36 | #include /* system, exit. */ 37 | 38 | static char * s1 = 39 | "/*\n\ 40 | * Generated by inst.c \n\ 41 | * This file is used to retrieve files hyaccpar and hyaccmanpage.\n\ 42 | * This file is updated each time hyacc is installed.\n\ 43 | */\n\n\ 44 | #include \"y.h\"\n\n\ 45 | void show_manpage() {\n \ 46 | system(\"less "; 47 | 48 | static char * s2 = 49 | "/hyaccmanpage\");\n\ 50 | }\n\n\ 51 | char * HYACC_PATH = \n \ 52 | \""; 53 | 54 | static char * s3 = "/hyaccpar\";\n\n"; 55 | 56 | int main(int argc, char ** argv) { 57 | FILE * fp; 58 | char * filename; 59 | 60 | if (argc == 1) return 0; 61 | 62 | filename = "hyacc_path.tmp"; 63 | if ((fp = fopen(filename, "w")) == NULL) { 64 | printf("inst.c: cannot open file %s\n", filename); 65 | exit(0); 66 | } 67 | 68 | fprintf(fp, "%s%s%s%s%s", s1, argv[1], s2, argv[1], s3); 69 | fclose(fp); 70 | 71 | system("mv -f hyacc_path.tmp hyacc_path.c"); 72 | 73 | return 0; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /bld/hyacc/lane_tracing.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Hyacc, a LR(0)/LALR(1)/LR(1) parser generator. 3 | Copyright (C) 2008, 2009 Xin Chen. chenx@hawaii.edu 4 | 5 | Hyacc is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Hyacc is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Hyacc; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef _LANE_TRACING_H_ 21 | #define _LANE_TRACING_H_ 22 | 23 | #include "y.h" 24 | 25 | /* 26 | * lane_tracing.h 27 | * 28 | * Used by lane_tracing.c only. 29 | * 30 | * @Author: Xin Chen 31 | * @Created on: 7/26/2008 32 | * @Last modified: 3/24/2009 33 | * @Copyright (C) 2008, 2009 34 | */ 35 | 36 | 37 | 38 | /* 39 | * A macro to determine if a config is the goal production 40 | * of state 0. Used for getting the "$end" context 41 | * before testA() in lane-tracing. 42 | * Single it out and put here, so it's easier to understand. 43 | */ 44 | #define IS_GOAL(o) (o->owner->state_no == 0 && o->ruleID == 0) 45 | 46 | 47 | /** Data structure for the state-combination in phase 2 table. START */ 48 | 49 | typedef struct _llist_int llist_int; /* linked list of states */ 50 | struct _llist_int { 51 | int n; 52 | llist_int * next; 53 | }; 54 | 55 | /* 56 | * Similar to llist_int, but has two int fields. 57 | * Used by LT_cluster only. 58 | */ 59 | typedef struct _llist_int2 llist_int2; /* linked list of states */ 60 | struct _llist_int2 { 61 | int n1; 62 | int n2; 63 | llist_int2 * next; 64 | }; 65 | 66 | typedef struct _llist_context_set llist_context_set; 67 | struct _llist_context_set { 68 | Configuration * config; // in INC order of config->ruleID. 69 | SymbolList ctxt; // in INC order of symbol. 70 | llist_context_set * next; 71 | }; 72 | 73 | 74 | /* 75 | * to get a State pointer from the state_no, use 76 | * states_new_array->state_list[state_no]. 77 | */ 78 | typedef struct _LT_tbl_entry LT_tbl_entry; 79 | struct _LT_tbl_entry { 80 | BOOL processed; // whether this entry was processed during regeration. 81 | int from_state; 82 | llist_context_set * ctxt_set; // in INC order of config->ruleID. 83 | llist_int * to_states; // in INC order of state_no. 84 | LT_tbl_entry * next; 85 | }; 86 | 87 | 88 | /* 89 | * For state combining purpose. 90 | */ 91 | typedef struct _LT_cluster LT_cluster; 92 | struct _LT_cluster { 93 | BOOL pairwise_disjoint; 94 | llist_int2 * states; // in INC order of state_no. 95 | llist_context_set * ctxt_set; // in INC order of config->ruleID. 96 | LT_cluster * next; 97 | }; 98 | 99 | 100 | extern LT_cluster * all_clusters; 101 | 102 | 103 | /* Functions */ 104 | 105 | extern LT_tbl_entry * LT_tbl_entry_find(State * from); 106 | extern LT_cluster * find_actual_containing_cluster(int state_no); 107 | extern void cluster_dump(LT_cluster * c); 108 | extern llist_int * llist_int_add_inc(llist_int * list, int n); 109 | extern int cluster_contain_state(LT_cluster * c, int state_no); 110 | extern llist_int2 * llist_int2_find_n2(llist_int2 * list, int n2); 111 | extern void llist_int_dump(llist_int * list); 112 | 113 | 114 | /* 115 | * For conflicting lanes' head states and associated conflicting contexts. 116 | */ 117 | typedef struct laneHeadState laneHead; 118 | struct laneHeadState { 119 | State * s; // conflicting lane head state. 120 | SymbolList contexts; // list of conflicting contexts. 121 | laneHead * next; 122 | }; 123 | 124 | 125 | /* 126 | * For (conflict_config, lane_end_config) pairs. 127 | */ 128 | typedef struct _ConfigPairNode ConfigPairNode; 129 | struct _ConfigPairNode { 130 | Configuration * end; // conflict_config 131 | Configuration * start; // lane_start_config 132 | ConfigPairNode * next; 133 | }; 134 | typedef ConfigPairNode * ConfigPairList; 135 | 136 | 137 | /* 138 | * Functions in lane_tracing.c 139 | */ 140 | extern laneHead * trace_back( 141 | Configuration * c0, Configuration * c, laneHead * lh_list); 142 | 143 | 144 | /* 145 | * Functions in lrk_util.c 146 | */ 147 | extern ConfigPairList ConfigPairList_combine( 148 | ConfigPairList t, ConfigPairList s); 149 | extern ConfigPairList ConfigPairList_insert(ConfigPairList list, 150 | Configuration * conflict_config, Configuration * lane_start_config); 151 | extern void ConfigPairList_dump(ConfigPairList list); 152 | extern ConfigPairNode * ConfigPairList_find( 153 | ConfigPairList list, Configuration * conflict_config); 154 | extern void ConfigPairList_destroy(ConfigPairList list); 155 | 156 | /* Set - a linked list of objects. */ 157 | typedef struct _Object_item Object_item; 158 | struct _Object_item { 159 | void * object; 160 | Object_item * next; 161 | }; 162 | typedef Object_item Set; 163 | extern Set * Set_insert(Set * set, void * object); 164 | extern Object_item * Set_find(Set * set, void * object); 165 | extern Set * Set_delete(Set * set, void * object); 166 | extern void Set_dump(Set * set, void (* set_item_dump)(void *)); 167 | 168 | 169 | /* List - a single linked list. */ 170 | typedef struct { 171 | int count; 172 | Object_item * head; 173 | Object_item * tail; 174 | } List; 175 | extern List * List_create(); 176 | extern void List_insert_tail(List * t, void * object); 177 | extern void List_destroy(List * t); 178 | extern void List_dump(List * t, void (* list_item_dump)(void *)); 179 | 180 | extern void print_symbolList(void * object); 181 | 182 | 183 | /* 184 | * for (configuration, conflict context) pair 185 | */ 186 | typedef struct { 187 | Configuration * c; 188 | SymbolList ctxt; // conflict context symbols 189 | Configuration * tail; 190 | } cfg_ctxt; 191 | 192 | extern cfg_ctxt * cfg_ctxt_create( 193 | Configuration * c, SymbolList s, Configuration * tail); 194 | extern void cfg_ctxt_destroy(cfg_ctxt * cc); 195 | extern void cfg_ctxt_dump(cfg_ctxt * cc); 196 | 197 | 198 | #endif 199 | 200 | 201 | -------------------------------------------------------------------------------- /bld/hyacc/lr0.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Hyacc, a LR(0)/LALR(1)/LR(1) parser generator. 3 | Copyright (C) 2008, 2009 Xin Chen. chenx@hawaii.edu 4 | 5 | Hyacc is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Hyacc is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Hyacc; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /* 21 | * LR(0) functions. 22 | * 23 | * @Author: Xin Chen 24 | * @Created on: 2/24/2008 25 | * @Last modified: 3/24/2009 26 | * @Copyright (C) 2008, 2009 27 | */ 28 | 29 | #include "y.h" 30 | 31 | 32 | static void propagateOriginatorChange(State * s); 33 | 34 | 35 | void addSuccessorConfigToState_LR0(State * s, int ruleID) { 36 | Configuration * c; 37 | 38 | if (s->config_count >= s->config_max_count - 1) { 39 | s->config_max_count *= 2; 40 | HYY_EXPAND(s->config, Configuration *, s->config_max_count); 41 | } 42 | 43 | // marker = 0, isCoreConfig = 0. 44 | c = createConfig(ruleID, 0, 0); 45 | c->owner = s; 46 | 47 | s->config[s->config_count] = c; 48 | s->config_count ++; 49 | } 50 | 51 | 52 | /* 53 | * Assumption: public variable config_queue contains 54 | * the configurations to be processed. 55 | */ 56 | void getConfigSuccessors_LR0(State * s) { 57 | RuleIDNode * r; 58 | SymbolTblNode * scanned_symbol = NULL; 59 | Configuration * config; 60 | int index; 61 | 62 | while (queue_count(config_queue) > 0) { 63 | config = s->config[queue_pop(config_queue)]; 64 | 65 | if (config->marker >= 0 && 66 | config->marker < grammar.rules[config->ruleID]->RHS_count) { 67 | scanned_symbol = getScannedSymbol(config); 68 | 69 | if (isNonTerminal(scanned_symbol) == TRUE) { 70 | 71 | for (r = scanned_symbol->ruleIDList; r != NULL; r = r->next) { 72 | // Grammar.rules[r->ruleID] starts with this scanned symbol. 73 | 74 | // If not an existing config, add to state s. 75 | index = isCompatibleSuccessorConfig(s, r->ruleID); 76 | 77 | if (index == -1) { // new config. 78 | addSuccessorConfigToState_LR0(s, r->ruleID); 79 | queue_push(config_queue, s->config_count - 1); 80 | index = s->config_count - 1; 81 | } // else is an existing old config, do nothing. 82 | 83 | } // end for 84 | } // else, is a terminal, stop. 85 | } // end if config-marker >= 0 ... 86 | } // end of while 87 | } 88 | 89 | 90 | void getClosure_LR0(State * s) { 91 | int i; 92 | //queue_clear(config_queue); 93 | for (i = 0; i < s->config_count; i ++) { 94 | queue_push(config_queue, i); 95 | } 96 | getConfigSuccessors_LR0(s); 97 | } 98 | 99 | 100 | /* 101 | * For LR(0). Insert a/r actions to the ENTIRE row. 102 | */ 103 | void insertReductionToParsingTable_LR0( 104 | Configuration * c, int state_no) { 105 | int col; 106 | SymbolTblNode * n; 107 | int max_col = grammar.terminal_count + 1; 108 | 109 | if (grammar.rules[c->ruleID]->nLHS->snode == 110 | grammar.goal_symbol->snode) { //accept, action = "a"; 111 | // note this should happen only if the end is $end. 112 | insertAction(hashTbl_find(strEnd), state_no, CONST_ACC); 113 | } else { //reduct, action = "r"; 114 | for (col = 0; col < max_col; col ++) { 115 | n = ParsingTblColHdr[col]; 116 | insertAction(n, state_no, (-1) * c->ruleID); 117 | } 118 | } 119 | } 120 | 121 | 122 | /* 123 | * if context set is empty, fill all cells in the ENTIRE row; 124 | * otherwise, fill cells with lookaheads in the context set. 125 | */ 126 | void insertReductionToParsingTable_LALR( 127 | Configuration * c, int state_no) { 128 | SymbolNode * a; 129 | int col; 130 | SymbolTblNode * n; 131 | int max_col = grammar.terminal_count + 1; 132 | 133 | if (grammar.rules[c->ruleID]->nLHS->snode == 134 | grammar.goal_symbol->snode) { //accept, action = "a"; 135 | // note this should happen only if the end is $end. 136 | insertAction(hashTbl_find(strEnd), state_no, CONST_ACC); 137 | } else { //reduct, action = "r"; 138 | a = c->context->nContext; 139 | if (a != NULL) { 140 | for (a = c->context->nContext; a != NULL; a = a->next) { 141 | insertAction(a->snode, state_no, (-1) * c->ruleID); 142 | } 143 | } else { 144 | for (col = 0; col < max_col; col ++) { 145 | n = ParsingTblColHdr[col]; 146 | insertAction(n, state_no, (-1) * c->ruleID); 147 | } 148 | } 149 | } 150 | } 151 | 152 | 153 | /* 154 | * For each of the new temp states, 155 | * If it is not one of the existing states in 156 | * states_new, then add it to states_new. 157 | * Also always add the transition to parsing table. 158 | * 159 | * Note: 160 | * The "is_compatible" variable is of NO use here, 161 | * since configurations don't have contexts. So such 162 | * states are always the "same", but not compatible. 163 | */ 164 | void addTransitionStates2New_LR0( 165 | State_collection * coll, State * src_state) { 166 | State * os, * next, * s; 167 | s = coll->states_head; 168 | 169 | while (s != NULL) { 170 | next = s->next; 171 | 172 | // searchSameStateHashTbl() checks for SAME (not compatible) states. 173 | if ((os = searchSameStateHashTbl(s)) == NULL) { 174 | insert_state_to_PM(s); 175 | 176 | // Add this new state as successor to src_state. 177 | addSuccessor(src_state, s); 178 | 179 | } else { // same with an existing state. 180 | addSuccessor(src_state, os); 181 | destroyState(s); // existing or compatible. No use. 182 | } 183 | 184 | s = next; 185 | } // end of while. 186 | } 187 | 188 | 189 | /* 190 | * Perform transition opertaion on a state to get successors. 191 | * 192 | * For each config c in the state s, 193 | * If c is a final config, stop 194 | * Else, get the scanned symbol x, 195 | * If a new temp state for x does not exist yet, create it. 196 | * add x to the temp state. 197 | * (Now get several new temp states) 198 | * Add these new temp states to states_new if not existed, 199 | * and add transition to parsing table as well. 200 | */ 201 | void transition_LR0(State * s) { 202 | int i; 203 | Configuration * c, * new_config; 204 | SymbolTblNode * scanned_symbol = NULL; 205 | State_collection * coll = createStateCollection(); 206 | State * new_state = NULL; 207 | 208 | for (i = 0; i < s->config_count; i ++) { 209 | c = s->config[i]; 210 | if (isFinalConfiguration(c)) { 211 | // do nothing. 212 | } else { // do transit operation. 213 | scanned_symbol = getScannedSymbol(c); 214 | if (strlen(scanned_symbol->symbol) == 0) { // empty reduction. 215 | continue; 216 | } 217 | new_state = 218 | findStateForScannedSymbol(coll, scanned_symbol); 219 | if (new_state == NULL) { 220 | new_state = createState(); 221 | // record which symbol this state is a successor by. 222 | new_state->trans_symbol = 223 | createSymbolNode(scanned_symbol); 224 | addState2Collection(coll, new_state); 225 | } 226 | // create a new core config for new_state. 227 | new_config = createConfig(-1, 0, 1); 228 | 229 | new_config->owner = new_state; 230 | copyConfig(new_config, c); 231 | new_config->isCoreConfig = 1; 232 | new_config->marker ++; 233 | if (new_config->nMarker != NULL) 234 | new_config->nMarker = new_config->nMarker->next; 235 | 236 | addCoreConfig2State(new_state, new_config); 237 | } 238 | } // end for 239 | 240 | if (coll->state_count > 0) { 241 | addTransitionStates2New_LR0(coll, s); 242 | } 243 | } 244 | 245 | 246 | /* 247 | * First fill acc, s, g. 248 | * Then fill r. r is filled to terminal symbols only. And if 249 | * a cell is already a/s/g, don't fill this r. 250 | */ 251 | static void outputParsingTableRow_LR0(State * s) { 252 | int i, ct; 253 | Configuration * c; 254 | State * t; 255 | 256 | ct = s->config_count; 257 | 258 | // insert a/r actions. 259 | for (i = 0; i < ct; i ++) { 260 | c = s->config[i]; 261 | 262 | if (isFinalConfiguration(c) == TRUE || 263 | isEmptyProduction(c) == TRUE) { 264 | insertReductionToParsingTable_LR0(c, s->state_no); 265 | } 266 | } 267 | 268 | // insert s/g actions. 269 | ct = s->successor_count; 270 | for (i = 0; i < ct; i ++) { 271 | t = s->successor_list[i]; 272 | insertAction(t->trans_symbol->snode, s->state_no, t->state_no); 273 | } 274 | } 275 | 276 | 277 | static void outputParsingTableRow_LALR(State * s) { 278 | int i, ct; 279 | Configuration * c; 280 | State * t; 281 | 282 | ct = s->config_count; 283 | 284 | // insert a/r actions. 285 | for (i = 0; i < ct; i ++) { 286 | c = s->config[i]; 287 | //printf("%d.%d\n", s->state_no, c->ruleID); 288 | 289 | if (isFinalConfiguration(c) == TRUE || 290 | isEmptyProduction(c) == TRUE) { 291 | insertReductionToParsingTable_LALR(c, s->state_no); 292 | } 293 | } 294 | 295 | // insert s/g actions. 296 | ct = s->successor_count; 297 | for (i = 0; i < ct; i ++) { 298 | t = s->successor_list[i]; 299 | insertAction(t->trans_symbol->snode, s->state_no, t->state_no); 300 | } 301 | } 302 | 303 | 304 | /* 305 | * Output parsing table from the parsing machine. 306 | * This is different from before. The previous implementation 307 | * for LR(1) is this is done when transitioning states. Now for 308 | * LR(0) since all default actions are reduce, the previous 309 | * method does not work very well. 310 | */ 311 | void outputParsingTable_LR0() { 312 | State * s; 313 | int i, cols, rows; 314 | rows = states_new_array->state_count; 315 | cols = n_symbol + 1; 316 | 317 | // expand size of parsing table array if needed. 318 | if (rows >= PARSING_TABLE_SIZE) { 319 | expandParsingTable(); 320 | } 321 | 322 | memset((void *) ParsingTable, 0, cols * rows * 4); 323 | 324 | for (i = 0; i < rows; i ++) { 325 | s = states_new_array->state_list[i]; 326 | outputParsingTableRow_LR0(s); 327 | } 328 | } 329 | 330 | 331 | /* 332 | * 333 | */ 334 | void outputParsingTable_LALR() { 335 | State * s; 336 | int i, cols, rows; 337 | rows = states_new_array->state_count; 338 | cols = n_symbol + 1; 339 | 340 | // expand size of parsing table array if needed. 341 | if (rows >= PARSING_TABLE_SIZE) { 342 | expandParsingTable(); 343 | } 344 | 345 | memset((void *) ParsingTable, 0, cols * rows * 4); 346 | 347 | for (i = 0; i < rows; i ++) { 348 | s = states_new_array->state_list[i]; 349 | outputParsingTableRow_LALR(s); 350 | } 351 | } 352 | 353 | 354 | void updateParsingTable_LR0() { 355 | ParsingTblRows = states_new->state_count; 356 | n_state_opt1 = states_new->state_count; 357 | 358 | // this fills the conflict list, so is need for lalr processing. 359 | outputParsingTable_LR0(); 360 | } 361 | 362 | 363 | void generate_LR0_parsing_machine() { 364 | State * new_state = states_new->states_head; 365 | 366 | if (DEBUG_GEN_PARSING_MACHINE == TRUE) { 367 | yyprintf("\n\n--generate parsing machine--\n"); 368 | } 369 | 370 | while (new_state != NULL) { 371 | if (DEBUG_GEN_PARSING_MACHINE == TRUE) { 372 | yyprintf3("%d states, current state is %d\n", 373 | states_new->state_count, new_state->state_no); 374 | } 375 | 376 | getClosure_LR0(new_state); // get closure of this state. 377 | 378 | // get successor states and add them to states_new. 379 | transition_LR0(new_state); 380 | 381 | new_state = new_state->next; // point to next unprocessed state. 382 | } 383 | 384 | updateParsingTable_LR0(); 385 | 386 | //show_conflict_count(); 387 | } 388 | 389 | -------------------------------------------------------------------------------- /bld/hyacc/makefile: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # This file is part of Hyacc, a LR(1) parser generator. 3 | # Copyright (C) 2007 Xin Chen. chenx@hawaii.edu 4 | # 5 | # Hyacc is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Hyacc is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Hyacc; if not, write to the Free Software Foundation, Inc., 17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | # 19 | ############################################################ 20 | # 21 | # makefile for hyacc 22 | # 23 | # These targets are used: 24 | # y, release, debug, clean install, uninstall, pack 25 | # Here target y is the same as release. 26 | # 27 | # To use this makefile, the only configuration needed is 28 | # to change the value of INSTALL_PATH below to the 29 | # destination path you want to install hyacc. 30 | # 31 | # @Author: Xin Chen 32 | # @Created on: Feb 10, 2007 33 | # @Last modified: Oct 25, 2007 34 | ############################################################# 35 | 36 | # NOTE: choose your installation directory here. 37 | #INSTALL_PATH = /usr/bin 38 | INSTALL_PATH = `pwd` # current directory 39 | 40 | SRC_HEADER = y.h stack_config.h mrt.h lane_tracing.h 41 | SRC = y.c get_yacc_grammar.c gen_compiler.c get_options.c \ 42 | version.c hyacc_path.c symbol_table.c state_hash_table.c \ 43 | queue.c gen_graphviz.c lr0.c lane_tracing.c stack_config.c \ 44 | mrt.c upe.c 45 | OBJS = y.o get_yacc_grammar.o gen_compiler.o get_options.o \ 46 | version.o hyacc_path.o symbol_table.o state_hash_table.o \ 47 | queue.o gen_graphviz.o lr0.o lane_tracing.o \ 48 | stack_config.o mrt.o upe.o 49 | PACK_SRC = $(SRC) $(SRC_HEADER) inst.c hyacc_path_dos.c makefile \ 50 | hyaccpar hyaccmanpage hyaccmanpage.html \ 51 | hyacc.1 GPL_license readme.pdf readme.txt calc.y 52 | TARGET = ../../bin/hyacc 53 | CC = gcc 54 | DATE = `date '+%m-%d-%y'` 55 | PACK_NAME = hyacc_$(DATE).tar 56 | FFLAG = -c -g 57 | 58 | 59 | $(TARGET) : $(OBJS) $(SRC_HEADER) 60 | @$(CC) -o $(TARGET) $(OBJS) 61 | 62 | # 63 | # all - the old default. 64 | # 65 | all : $(SRC) $(SRC_HEADER) 66 | @$(CC) -o $(TARGET) $(SRC) 67 | 68 | release : $(SRC) $(SRC_HEADER) 69 | @make create_path_file 70 | @$(CC) -o $(TARGET) $(SRC) 71 | 72 | debug : $(SRC) $(SRC_HEADER) 73 | @make create_path_file 74 | @$(CC) -g -o $(TARGET) $(SRC) 75 | 76 | clean : 77 | @rm -f ./$(TARGET) ./$(OBJS) 78 | 79 | install : create_path_file 80 | @make release 81 | @-cp -f ./$(TARGET) $(INSTALL_PATH)/. 82 | @-cp -f ./hyaccpar $(INSTALL_PATH)/. 83 | @-cp -f ./hyaccmanpage $(INSTALL_PATH)/. 84 | 85 | create_path_file: inst.c 86 | @$(CC) inst.c -o inst 87 | @./inst $(INSTALL_PATH) 88 | @rm -f inst 89 | 90 | uninstall: 91 | @echo to uninstall, manually remove the following files: 92 | @echo $(INSTALL_PATH)/$(TARGET) 93 | @echo $(INSTALL_PATH)/hyaccpar 94 | @echo $(INSTALL_PATH)/hyaccmanpage 95 | 96 | dist: 97 | @-rm -f $(PACK_NAME).gz 98 | @tar cvf $(PACK_NAME) $(PACK_SRC) 99 | @gzip $(PACK_NAME) 100 | @ls $(PACK_NAME).gz 101 | 102 | # 103 | # for object files. 104 | # 105 | 106 | gen_compiler.o : gen_compiler.c y.h 107 | @$(CC) $(FFLAG) gen_compiler.c 108 | 109 | gen_graphviz.o : gen_graphviz.c y.h 110 | @$(CC) $(FFLAG) gen_graphviz.c 111 | 112 | get_options.o : get_options.c y.h 113 | @$(CC) $(FFLAG) get_options.c 114 | 115 | get_yacc_grammar.o : get_yacc_grammar.c y.h 116 | @$(CC) $(FFLAG) get_yacc_grammar.c 117 | 118 | hyacc_path.o : hyacc_path.c y.h 119 | @$(CC) $(FFLAG) hyacc_path.c 120 | 121 | lane_tracing.o : lane_tracing.c lane_tracing.h y.h stack_config.h 122 | @$(CC) $(FFLAG) lane_tracing.c 123 | 124 | lr0.o : lr0.c y.h 125 | @$(CC) $(FFLAG) lr0.c 126 | 127 | mrt.o : mrt.c mrt.h y.h 128 | @$(CC) $(FFLAG) mrt.c 129 | 130 | queue.o : queue.c y.h 131 | @$(CC) $(FFLAG) queue.c 132 | 133 | stack_config.o : stack_config.c y.h 134 | @$(CC) $(FFLAG) stack_config.c 135 | 136 | state_hash_table.o : state_hash_table.c y.h 137 | @$(CC) $(FFLAG) state_hash_table.c 138 | 139 | symbol_table.o : symbol_table.c y.h 140 | @$(CC) $(FFLAG) symbol_table.c 141 | 142 | upe.o : upe.c y.h mrt.h 143 | @$(CC) $(FFLAG) upe.c 144 | 145 | version.o : version.c y.h 146 | @$(CC) $(FFLAG) version.c 147 | 148 | y.o : y.c y.h lane_tracing.h 149 | @$(CC) $(FFLAG) y.c 150 | 151 | 152 | -------------------------------------------------------------------------------- /bld/hyacc/mrt.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Hyacc, a LR(0)/LALR(1)/LR(1) parser generator. 3 | Copyright (C) 2007, 2008 Xin Chen. chenx@hawaii.edu 4 | 5 | Hyacc is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Hyacc is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Hyacc; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef _MRT_H_ 21 | #define _MRT_H_ 22 | 23 | /* 24 | * mrt.h 25 | * 26 | * Functions for multi-rooted tree. Used by unit production elimination 27 | * algorithm. 28 | * 29 | * @Author: Xin Chen 30 | * @Date started: March 9, 2007 31 | * @Last modified: March 9, 2007 32 | * @Copyright (C) 2007, 2008 33 | */ 34 | 35 | 36 | /* 37 | * MRTreeNode.parent is a dynamically allocated array. 38 | */ 39 | struct _MRTreeNode { 40 | SymbolNode * symbol; 41 | struct _MRTreeNode ** parent; // dynamic array. 42 | int parent_count; 43 | int parent_max_count; // expand parent array if reached. 44 | }; 45 | 46 | #define MRTreeNode_INIT_PARENT_COUNT 8 47 | 48 | 49 | typedef struct _MRTreeNode MRTreeNode; // multi-rooted tree node. 50 | 51 | 52 | /* 53 | * The Multi-rooted forest grows upon this array. 54 | * The Multi-rooted forest consists of 1 or more trees. 55 | * The leaves of the each tree are in this array, 56 | * the leaves then link to the internal nodes of the tree. 57 | */ 58 | MRTreeNode ** MRLeaves; 59 | int MRLeaves_count; 60 | int MRLeaves_max_count; 61 | #define MRLeaves_INIT_MAX_COUNT 8 62 | 63 | /* 64 | * Stores the parent symbols in all multirooted trees. 65 | * 66 | * Used in steps 3 and 5 of unit production removal 67 | * algorithm, to avoid having to traverse through 68 | * the MRTree to find out if a symbol is a parent symbol 69 | * each time. 70 | */ 71 | 72 | #define MRParents_INIT_MAX_COUNT 8 73 | 74 | typedef struct { 75 | SymbolNode ** parents; // dynamic array. 76 | int count; 77 | int max_count; 78 | } MRParents; 79 | 80 | MRParents * all_parents; 81 | 82 | 83 | /* 84 | * Used in step 5. 85 | * Value obtained when calling getAllMRParents(). 86 | * It eventually calls getNode(), which does the work. 87 | * 88 | * Used to retrieve a leaf for a parent. 89 | * There may be more than one leaf for a parent, 90 | * just choose the first one in the order of grammar rules. 91 | * 92 | * The correspondence relationship is: 93 | * all_parents[index] => MRLeaves[leafIndexForParent[index]] 94 | * 95 | * Has the same size as all_parents->max_count. 96 | */ 97 | int * leafIndexForParent; 98 | 99 | 100 | /* 101 | * leafIndexForParent[] array is build in function 102 | * getNode(), which is called by getParentsForMRLeaf(). 103 | * getParentsForMRLeaf() is called by functions 104 | * (1) getAllMRParents() and 105 | * (2) remove_unit_production_step1and2(). 106 | * This boolean varaible is set to TRUE after calling (1), 107 | * so calling (2) won't change the values stored in 108 | * leafIndexForParent[]. 109 | * 110 | * Used in functions getAllMRParents() and getNode(). 111 | */ 112 | BOOL leafIndexForParent_Done; 113 | 114 | 115 | /* function declarations */ 116 | 117 | extern MRParents * createMRParents(); 118 | extern int getIndexInMRParents(SymbolTblNode * s, MRParents * p); 119 | extern void getParentsForMRLeaf(int leaf_index, 120 | MRParents * parents); 121 | extern void destroyMRParents(MRParents * p); 122 | extern void buildMultirootedTree(); 123 | 124 | #endif 125 | 126 | -------------------------------------------------------------------------------- /bld/hyacc/queue.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Hyacc, a LR(0)/LALR(1)/LR(1) parser generator. 3 | Copyright (C) 2007 Xin Chen. chenx@hawaii.edu 4 | 5 | Hyacc is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Hyacc is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Hyacc; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /* 21 | * queue.c 22 | * 23 | * A circular, expandable integer queue. 24 | * 25 | * @Author: Xin Chen 26 | * @Created on: 3/3/2007 27 | * @Last modified: 3/21/2007 28 | * @Copyright (C) 2007 29 | */ 30 | 31 | #include "y.h" 32 | 33 | 34 | #define QUEUE_INIT_SIZE 256 // hidden from outside 35 | #define DEBUG_QUEUE 0 36 | 37 | 38 | Queue * queue_create() { 39 | Queue * q = (Queue *) malloc(sizeof(Queue)); 40 | if (q == NULL) { 41 | printf("out of memory\n"); 42 | exit(1); 43 | } 44 | 45 | q->size = QUEUE_INIT_SIZE; 46 | q->array = (int *) malloc(sizeof(int) * q->size); 47 | if (q->array == NULL) { 48 | printf("out of memory\n"); 49 | exit(1); 50 | } 51 | 52 | q->head = 0; 53 | q->tail = 0; 54 | q->count = 0; 55 | 56 | q->max_count = q->sum_count = q->call_count = 0; 57 | 58 | return q; 59 | } 60 | 61 | 62 | void queue_destroy(Queue * q) { 63 | free(q->array); 64 | free(q); 65 | } 66 | 67 | 68 | void queue_clear(Queue * q) { 69 | q->head = 0; 70 | q->tail = 0; 71 | q->count = 0; 72 | } 73 | 74 | 75 | void queue_clear_all(Queue * q) { 76 | q->head = 0; 77 | q->tail = 0; 78 | q->count = 0; 79 | q->max_count = q->sum_count = q->call_count = 0; 80 | } 81 | 82 | 83 | void queue_expand(Queue * q) { 84 | int i, pt; 85 | int * new_array, * old_array; 86 | 87 | if (q->count < q->size) return; 88 | 89 | new_array = (int *) malloc(sizeof(int) * 2 * q->size); 90 | if (new_array == NULL) { 91 | printf("out of memory\n"); 92 | exit(1); 93 | } 94 | 95 | old_array = q->array; 96 | 97 | // copy 98 | pt = q->head; 99 | for (i = 0; i < q->count; i ++) { 100 | new_array[i] = q->array[pt]; 101 | pt ++; 102 | if (pt == q->size) pt = 0; 103 | } 104 | 105 | q->array = new_array; 106 | q->size *= 2; 107 | q->head = 0; 108 | q->tail = i; 109 | 110 | free(old_array); 111 | 112 | //printf("expand queue size to %d: ", q->size); 113 | //queue_dump(q); printf("\n"); 114 | } 115 | 116 | 117 | /* 118 | * push at tail. 119 | */ 120 | void queue_push(Queue * q, int n) { 121 | if (q->count >= q->size) queue_expand(q); 122 | 123 | if (n == QUEUE_ERR_CODE) { 124 | printf("Queue error: push a number that equals QUEUE_ERR_CODE\n"); 125 | exit(1); 126 | } 127 | 128 | q->array[q->tail] = n; 129 | q->tail ++; 130 | q->count ++; 131 | 132 | // wrap around. 133 | if (q->tail == q->size) q->tail = 0; 134 | 135 | //printf("push %d (size=%d): ", n, q->count); 136 | //queue_dump(q); printf("\n"); 137 | 138 | #if DEBUG_QUEUE 139 | if (q->max_count < q->count) q->max_count = q->count; 140 | q->call_count ++; 141 | q->sum_count += q->count; 142 | #endif 143 | } 144 | 145 | 146 | /* 147 | * pop at front 148 | */ 149 | int queue_pop(Queue * q) { 150 | int item; 151 | if (q->count == 0) return QUEUE_ERR_CODE; 152 | 153 | item = q->array[q->head]; 154 | q->head ++; 155 | if (q->head == q->size) q->head = 0; 156 | 157 | q->count --; 158 | 159 | //printf("pop %d (size=%d): ", item, q->count); 160 | //queue_dump(q); printf("\n"); 161 | 162 | return item; 163 | } 164 | 165 | 166 | int queue_peek(Queue * q) { 167 | if (q->count == 0) return QUEUE_ERR_CODE; 168 | return q->array[q->head]; 169 | } 170 | 171 | 172 | int queue_count(Queue * q) { 173 | return q->count; 174 | } 175 | 176 | 177 | /* 178 | * Check if number n exists in the q. 179 | */ 180 | int queue_exist(Queue * q, int n) { 181 | int i; 182 | int pt = q->head; 183 | for (i = 0; i < q->count; i ++) { 184 | if (q->array[pt] == n) return 1; 185 | pt ++; 186 | if (pt == q->size) pt = 0; 187 | } 188 | return 0; 189 | } 190 | 191 | 192 | void queue_dump(Queue * q) { 193 | int i, pt; 194 | pt = q->head; 195 | for (i = 0; i < q->count; i ++) { 196 | printf("[%d] %d ", pt, q->array[pt]); 197 | pt ++; 198 | if (pt == q->size) pt = 0; 199 | } 200 | printf("\n"); 201 | } 202 | 203 | 204 | /* 205 | * Print the usage information of the queue. 206 | */ 207 | void queue_info(Queue * q) { 208 | #if DEBUG_QUEUE 209 | printf("queue_push is called %d times, ", q->call_count); 210 | printf("max count: %d, average count: %.2f\n", 211 | q->max_count, ((double )q->sum_count) / q->call_count); 212 | #endif 213 | } 214 | -------------------------------------------------------------------------------- /bld/hyacc/readme.txt: -------------------------------------------------------------------------------- 1 | hyacc, hyaccpar and hyaccmanpage are the three files 2 | needed to run Hyacc. To use Hyacc, put your grammar 3 | file in the same folder as these three files. 4 | 5 | "hyacc -h" will show help message. 6 | "hyacc -m" will show manual. 7 | 8 | One example calc.y (an infix notation calculator) is provided. 9 | "hyacc calc.y" will produce y.tab.c. 10 | "gcc y.tab.c -o calc" will produce the executable calc. 11 | 12 | -------------------------------------------------------------------------------- /bld/hyacc/stack_config.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Hyacc, a LR(0)/LALR(1)/LR(1) parser generator. 3 | Copyright (C) 2007 Xin Chen. chenx@hawaii.edu 4 | 5 | Hyacc is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Hyacc is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Hyacc; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /* 21 | * stack_config.c 22 | * 23 | * An expandable stack for Configuration pointer. 24 | * 25 | * @Author: Xin Chen 26 | * @Created on: 2/27/2006 27 | * @Last modified: 6/19/2007 28 | */ 29 | 30 | #include "stack_config.h" 31 | 32 | 33 | stack * stack_create() { 34 | return stack_create2(STACK_INIT_SIZE); 35 | } 36 | 37 | 38 | stack * stack_create2(int size) { 39 | stack * s = (stack *) malloc(sizeof(stack)); 40 | if (s == NULL) { 41 | puts("stack_create: out of memory"); 42 | return NULL; 43 | } 44 | s->pt = 0; 45 | s->capacity = size; 46 | s->array = (Configuration **) 47 | malloc(s->capacity * sizeof(Configuration *)); 48 | if (s->array == NULL) { 49 | puts("stack_create: out of memory"); 50 | return NULL; 51 | } 52 | return s; 53 | } 54 | 55 | 56 | void stack_push(stack * s, Configuration * n) { 57 | s->array[s->pt] = n; 58 | s->pt ++; 59 | #if DEBUG_STACK 60 | printf("stack_push: %d\n", s->array[s->pt - 1]); 61 | stack_dump(s); 62 | #endif 63 | 64 | if (s->pt == s->capacity) { 65 | s->array = (Configuration **) realloc( 66 | (void *) s->array, 2 * s->capacity * sizeof(Configuration *) ); 67 | if (s->array == NULL) { 68 | puts("stack_push: out of memory"); 69 | return; 70 | } 71 | s->capacity *= 2; 72 | #if DEBUG_STACK 73 | printf("stack_push: expand stack capacity to: %d\n", 74 | s->capacity); 75 | #endif 76 | } 77 | } 78 | 79 | 80 | Configuration * stack_pop(stack * s) { 81 | if (s->pt == 0) { 82 | if (USE_WARNING) 83 | puts("stack_pop warning: underflow, return NULL"); 84 | return NULL; 85 | } 86 | -- s->pt; 87 | #if DEBUG_STACK 88 | printf("stack_pop: %d\n", s->array[s->pt]); 89 | stack_dump(s); 90 | #endif 91 | return s->array[s->pt]; 92 | } 93 | 94 | 95 | Configuration * stack_top(stack * s) { 96 | if (s->pt == 0) { 97 | if (USE_WARNING) 98 | puts("stack_top warning: underflow, return NULL"); 99 | return NULL; 100 | } 101 | #if DEBUG_STACK 102 | printf("stack_top: %d. ct: %d\n", s->array[s->pt - 1], 103 | stack_count(s)); 104 | #endif 105 | return s->array[s->pt - 1]; 106 | } 107 | 108 | 109 | /* 110 | * @Return: number of elements in the stack. 111 | */ 112 | int stack_count(stack * s) { 113 | return s->pt; 114 | } 115 | 116 | 117 | void stack_destroy(stack * s) { 118 | free(s->array); 119 | free(s); 120 | } 121 | 122 | 123 | void stack_dump(stack * s) { 124 | int i; 125 | Configuration * c; 126 | printf("stack capacity: %d, count: %d\n", 127 | s->capacity, stack_count(s)); 128 | if (stack_count(s) == 0) return; 129 | 130 | for (i = 0; i < s->pt; i ++) { 131 | if ((i > 0) && (i % 10 == 0)) putchar('\n'); 132 | c = s->array[i]; 133 | printf("[%d] ", i); 134 | if (c == 0) { 135 | puts("0"); 136 | } else if (c == (Configuration *) -1) { 137 | puts("*"); 138 | } else { 139 | stdout_writeConfig(c); 140 | } 141 | } 142 | putchar('\n'); 143 | } 144 | 145 | -------------------------------------------------------------------------------- /bld/hyacc/stack_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Hyacc, a LR(0)/LALR(1)/LR(1) parser generator. 3 | Copyright (C) 2007, 2008, 2009 Xin Chen. chenx@hawaii.edu 4 | 5 | Hyacc is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Hyacc is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Hyacc; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef _STACK_CONFIG_H_ 21 | #define _STACK_CONFIG_H_ 22 | 23 | /* 24 | * stack_config.h 25 | * 26 | * An expandable integer stack, implemented as an array. 27 | * 28 | * @Author: Xin Chen 29 | * @Created on: 2/27/2006 30 | * @Last modified: 6/19/2007 31 | * @Copyright (C) 2007, 2008, 2009 32 | */ 33 | 34 | #include "y.h" 35 | 36 | #define DEBUG_STACK 0 37 | #define STACK_INIT_SIZE 256 38 | #define USE_WARNING 0 39 | 40 | typedef struct { 41 | Configuration ** array; 42 | int pt; 43 | int capacity; 44 | } stack; 45 | 46 | stack * stack_create(); 47 | stack * stack_create2(int init_capacity); 48 | void stack_push(stack * s, Configuration * n); 49 | Configuration * stack_pop(stack * s); 50 | Configuration * stack_top(stack * s); 51 | int stack_count(stack * s); /* number of elements in stack */ 52 | void stack_destroy(stack * s); 53 | void stack_dump(stack * s); 54 | 55 | #endif 56 | 57 | -------------------------------------------------------------------------------- /bld/hyacc/state_hash_table.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Hyacc, a LR(0)/LALR(1)/LR(1) parser generator. 3 | Copyright (C) 2007 Xin Chen. chenx@hawaii.edu 4 | 5 | Hyacc is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Hyacc is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Hyacc; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /* 21 | * state_hash_table.c 22 | * 23 | * This hash table stores state numbers. It hashes a state by 24 | * a function of the rule index and marker position of the 25 | * state's core configurations. 26 | * 27 | * This hash table is used to expidite the the process of fi- 28 | * nding a same or compatible state in the function addTrans- 29 | * itionStates2New(). 30 | * 31 | * This is an alternative of the function isExistingState(), 32 | * which uses linear search in all the states, and is slower. 33 | * 34 | * For example, for C.y, in -O0 (no optimization), there are 35 | * 1605 states in the parsing machine, so from the first to 36 | * the last state as they are added, in average there will be 37 | * sum_{k=1_to_n}(k/2) = n(n+1)/4 searches, where n = 1605. 38 | * This is 644,407. 39 | * 40 | * But using this state hash table, in average there are 5.02 41 | * states per list (from StateHashTbl_dump() output), so the 42 | * cost is (1 + 5.02) * 1605 = 9,662, where 1 is the cost of 43 | * getting the hash value for a state. 44 | * 45 | * This is 644,407/9,662 = 67 times faster. 46 | * 47 | * @Author: Xin Chen 48 | * @Created on: 3/3/2006 49 | * @Last modified: 3/21/2007 50 | * @Copyright (C) 2007 51 | */ 52 | 53 | #include "y.h" 54 | 55 | 56 | struct StateTableNode { 57 | State * state; 58 | struct StateTableNode * next; 59 | }; 60 | typedef struct StateTableNode StateNode; 61 | 62 | 63 | typedef struct { 64 | int count; 65 | StateNode * next; 66 | } StateHashTblNode; 67 | 68 | 69 | #define SHT_SIZE 997 /* State hash table size */ 70 | StateHashTblNode StateHashTbl[SHT_SIZE]; 71 | 72 | 73 | StateNode * createStateNode(State * s) { 74 | StateNode * n; 75 | HYY_NEW(n, StateNode, 1); 76 | n->state = s; 77 | n->next = NULL; 78 | return n; 79 | } 80 | 81 | 82 | void destroyStateNode(StateNode * n) { 83 | free(n); 84 | } 85 | 86 | 87 | void initStateHashTbl() { 88 | int i; 89 | for (i = 0; i < SHT_SIZE; i ++) { 90 | StateHashTbl[i].count = 0; 91 | StateHashTbl[i].next = NULL; 92 | } 93 | } 94 | 95 | 96 | static int getStateHashVal(State * s) { 97 | int i, sum = 0; 98 | for (i = 0; i < s->core_config_count; i ++) { 99 | sum = (sum + s->config[i]->ruleID * 97 + 100 | s->config[i]->marker * 7 + i) % SHT_SIZE; 101 | } 102 | return sum; 103 | } 104 | 105 | 106 | extern BOOL in_lanetracing; 107 | 108 | /* 109 | * Search the state hash table for state s. 110 | * If not found, insert it and return NULL. 111 | * else, return the found state. 112 | */ 113 | State * searchStateHashTbl(State * s, int * is_compatible) { 114 | int v = getStateHashVal(s); 115 | StateNode * n = StateHashTbl[v].next; 116 | StateNode * n_prev; 117 | 118 | (* is_compatible) = 0; // default to 0 - false. 119 | 120 | if (n == NULL) { 121 | StateHashTbl[v].next = createStateNode(s); 122 | StateHashTbl[v].count = 1; 123 | return NULL; 124 | } 125 | 126 | while (n != NULL) { 127 | n_prev = n; 128 | if (isSameState(n->state, s) == TRUE) { 129 | return n->state; 130 | } 131 | if (USE_COMBINE_COMPATIBLE_STATES) { 132 | if (isCompatibleStates(n->state, s) == TRUE) { 133 | combineCompatibleStates(n->state, s); 134 | (* is_compatible) = 1; 135 | return n->state; 136 | } 137 | } 138 | n = n->next; 139 | } 140 | // n == NULL, s does not exist. insert at end. 141 | n_prev->next = createStateNode(s); 142 | StateHashTbl[v].count ++; 143 | 144 | return NULL; 145 | } 146 | 147 | 148 | /* 149 | * Search the state hash table for state s. 150 | * If not found, insert it and return NULL. 151 | * else, return the found state. 152 | * 153 | * Is similar to searchStateHashTbl, but does not use 154 | * weak compatibility. 155 | */ 156 | State * searchSameStateHashTbl(State * s) { 157 | int v = getStateHashVal(s); 158 | StateNode * n = StateHashTbl[v].next; 159 | StateNode * n_prev; 160 | 161 | if (n == NULL) { 162 | StateHashTbl[v].next = createStateNode(s); 163 | StateHashTbl[v].count = 1; 164 | return NULL; 165 | } 166 | 167 | while (n != NULL) { 168 | n_prev = n; 169 | if (isSameState(n->state, s) == TRUE) { 170 | return n->state; 171 | } 172 | n = n->next; 173 | } 174 | // n == NULL, s does not exist. insert at end. 175 | n_prev->next = createStateNode(s); 176 | StateHashTbl[v].count ++; 177 | 178 | return NULL; 179 | } 180 | 181 | 182 | /* 183 | * load factor: number of entry / hash table size. 184 | * hash table cell usage: 185 | * number of used hash table cells / hash table size. 186 | */ 187 | void StateHashTbl_dump() { 188 | int i, states_count = 0, list_count = 0; 189 | StateNode * n; 190 | 191 | yyprintf("\n--state hash table--\n"); 192 | yyprintf("-----------------------\n"); 193 | yyprintf("cell | count | state\n"); 194 | yyprintf("-----------------------\n"); 195 | for (i = 0; i < SHT_SIZE; i ++) { 196 | if (StateHashTbl[i].count == 0) continue; 197 | 198 | list_count ++; 199 | states_count += StateHashTbl[i].count; 200 | 201 | yyprintf3("[%3d] (count=%d) : ", i, StateHashTbl[i].count); 202 | if ((n = StateHashTbl[i].next) != NULL) { 203 | yyprintf2("%d", n->state->state_no); 204 | 205 | n = n->next; 206 | while (n != NULL) { 207 | yyprintf2(", %d", n->state->state_no); 208 | n = n->next; 209 | } 210 | } 211 | yyprintf("\n"); 212 | } 213 | 214 | yyprintf4("%d states, %d lists, in average %.2f states/list.\n", 215 | states_count, list_count, 216 | ((double) states_count)/list_count); 217 | yyprintf3("load factor: %.2f, hash table cell usage: %.2f\n", 218 | ((double) states_count)/SHT_SIZE, 219 | ((double) list_count)/SHT_SIZE); 220 | 221 | } 222 | 223 | 224 | 225 | -------------------------------------------------------------------------------- /bld/hyacc/symbol_table.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Hyacc, a LR(0)/LALR(1)/LR(1) parser generator. 3 | Copyright (C) 2007 Xin Chen. chenx@hawaii.edu 4 | 5 | Hyacc is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Hyacc is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Hyacc; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /* 21 | * symbol_table.c 22 | * 23 | * Stores all symbols of the grammar and relevant information 24 | * of these symbols. 25 | * 26 | * @Author: Xin Chen 27 | * @Created on: 2/16/2007 28 | * @Last modified: 3/21/2007 29 | * @Copyright (C) 2007 30 | */ 31 | 32 | #include "y.h" 33 | 34 | #define DEBUG_HASHTBL 0 35 | 36 | 37 | /******************************************* 38 | * Functions for RuleIDNode. 39 | *******************************************/ 40 | 41 | 42 | RuleIDNode * createRuleIDNode(int ruleID) { 43 | RuleIDNode * r; 44 | r = (RuleIDNode *) malloc(sizeof(RuleIDNode)); 45 | if (r == NULL) 46 | YYERR_EXIT("createRuleIDNode: out of memory\n"); 47 | 48 | r->ruleID = ruleID; 49 | r->next = NULL; 50 | return r; 51 | } 52 | 53 | 54 | void writeRuleIDList(SymbolTblNode * n) { 55 | RuleIDNode * a; 56 | printf("%s: ", n->symbol); 57 | if ((a = n->ruleIDList) != NULL) { 58 | printf("%d", a->ruleID); 59 | 60 | for (a = a->next; a != NULL; a = a->next) { 61 | printf(", %d", a->ruleID); 62 | } 63 | } 64 | printf("\n"); 65 | } 66 | 67 | 68 | void writeNonTerminalRuleIDList() { 69 | SymbolNode * a; 70 | int count = 0; 71 | printf("--Nonterminal symbol rule index list--\n"); 72 | for (a = grammar.non_terminal_list; a != NULL; a = a->next) { 73 | printf("%d: ", count ++); 74 | writeRuleIDList(a->snode); 75 | } 76 | } 77 | 78 | 79 | void destroyRuleIDList(RuleIDNode * r) { 80 | RuleIDNode * a, * b; 81 | 82 | if (r == NULL) return; 83 | 84 | a = r; 85 | while (a != NULL) { 86 | b = a->next; 87 | free(a); 88 | a = b; 89 | } 90 | } 91 | 92 | 93 | /******************************************* 94 | * Functions for SymbolNode. 95 | *******************************************/ 96 | 97 | 98 | /* 99 | * Create a symbol node, used by Production, Context etc. 100 | */ 101 | SymbolNode * createSymbolNode(SymbolTblNode * sn) { 102 | SymbolNode * n; 103 | 104 | if (sn == NULL) 105 | YYERR_EXIT("createSymbolNode error: snode is NULL\n"); 106 | 107 | n = (SymbolNode *) malloc(sizeof(SymbolNode)); 108 | if (n == NULL) 109 | YYERR_EXIT("createSymbolNode error: out of memory\n"); 110 | n->snode = sn; 111 | n->next = NULL; 112 | return n; 113 | } 114 | 115 | 116 | void freeSymbolNode(SymbolNode * n) { 117 | if (n == NULL) return; 118 | free(n); 119 | } 120 | 121 | 122 | void freeSymbolNodeList(SymbolNode * a) { 123 | SymbolNode * b; 124 | if (a == NULL) return; 125 | 126 | while (a != NULL) { 127 | b = a->next; 128 | free(a); 129 | a = b; 130 | } 131 | } 132 | 133 | 134 | SymbolNode * findInSymbolList(SymbolList a, SymbolTblNode * s) { 135 | SymbolNode * b; 136 | 137 | for (b = a; b != NULL; b = b->next) { 138 | if (b->snode == s) return b; 139 | } 140 | 141 | return NULL; 142 | } 143 | 144 | 145 | int getSymbolListLen(SymbolList a) { 146 | int len; 147 | SymbolNode * b; 148 | 149 | len = 0; 150 | for (b = a; b != NULL; b = b->next) { len ++; } 151 | return len; 152 | } 153 | 154 | 155 | /* 156 | * Given a symbol list a, returns a clone of it. 157 | */ 158 | SymbolList cloneSymbolList(const SymbolList a) { 159 | SymbolNode * b, *c, * clone; 160 | if (NULL == a) return NULL; 161 | 162 | clone = c = createSymbolNode(a->snode); 163 | for (b = a->next; b != NULL; b = b->next) { 164 | c->next = createSymbolNode(b->snode); 165 | c = c->next; 166 | } 167 | 168 | return clone; 169 | } 170 | 171 | /* 172 | * Remove s from list a. 173 | * @return: the new list. 174 | */ 175 | SymbolList removeFromSymbolList( 176 | SymbolList a, SymbolTblNode * s, int * exist) { 177 | SymbolNode * b, * tmp; 178 | * exist = 1; 179 | 180 | if (a->snode == s) { // is the first node. 181 | b = a; 182 | a = a->next; 183 | freeSymbolNode(b); 184 | return a; 185 | } 186 | 187 | for (b = a; b->next != NULL; b = b->next) { 188 | if (b->next->snode == s) { 189 | tmp = b->next; 190 | b->next = tmp->next; 191 | freeSymbolNode(tmp); 192 | return a; 193 | } 194 | } 195 | 196 | // b->next is NULL. s is NOT in list a. 197 | * exist = 0; 198 | return a; 199 | } 200 | 201 | 202 | /* 203 | * Find in a sorted (INCREMENTAL) list. 204 | */ 205 | SymbolNode * findInIncSymbolList(SymbolList a, SymbolTblNode * s) { 206 | SymbolNode * b; 207 | 208 | for (b = a; b != NULL; b = b->next) { 209 | if (b->snode == s) return b; 210 | else if (strcmp(s->symbol, b->snode->symbol) > 0) { 211 | return NULL; 212 | } 213 | } 214 | 215 | return NULL; 216 | } 217 | 218 | 219 | /* 220 | * Insert symbol n into INC list a. 221 | * @Return: the result list. 222 | */ 223 | SymbolNode * insertIncSymbolList(SymbolList a, SymbolTblNode * n) { 224 | int cmp; 225 | SymbolNode * b, * b_prev; 226 | if (NULL == n) return a; 227 | if (NULL == a) return createSymbolNode(n); 228 | 229 | for (b_prev = NULL, b = a; b != NULL; b_prev = b, b = b->next) { 230 | cmp = strcmp(n->symbol, b->snode->symbol); 231 | if (cmp < 0) { // insert after b_prev, before b. 232 | if (b_prev == NULL) { // insert at the head. 233 | b_prev = createSymbolNode(n); 234 | b_prev->next = b; 235 | return b_prev; 236 | } else { // insert in the middle. 237 | b_prev->next = createSymbolNode(n); 238 | b_prev->next->next = b; 239 | return a; 240 | } 241 | } else if (cmp > 0) { // go on. 242 | continue; 243 | } else { // equals. already exists. 244 | return a; 245 | } 246 | } 247 | 248 | // b is NULL. insert at the end. 249 | b_prev->next = createSymbolNode(n); 250 | 251 | return a; 252 | } 253 | 254 | 255 | /* 256 | * Combine list b into a. Both lists are in INC order. 257 | * Returns the head of the combined list. 258 | * This can be used when combining contexts. 259 | */ 260 | SymbolNode * combineIncSymbolList(SymbolList a, SymbolList b) { 261 | SymbolNode * na, * nb, * na_prev; 262 | int cmp; 263 | if (a == NULL) return cloneSymbolList(b); 264 | if (b == NULL) return a; 265 | 266 | na_prev = NULL; 267 | na = a; 268 | nb = b; 269 | 270 | while (1) { 271 | cmp = strcmp(na->snode->symbol, nb->snode->symbol); 272 | //printf("strcmp(%s, %s) = %d\n", 273 | // na->snode->symbol, nb->snode->symbol, cmp); 274 | if (cmp == 0) { 275 | na_prev = na; 276 | na = na->next; 277 | nb = nb->next; 278 | } else if (cmp > 0) { // insert b before na. 279 | if (na_prev == NULL) { // insert at the head of a. 280 | na_prev = createSymbolNode(nb->snode); 281 | na_prev->next = a; 282 | a = na_prev; 283 | } else { // insert in the middle of list a before na. 284 | na_prev->next = createSymbolNode(nb->snode); 285 | na_prev->next->next = na; 286 | } 287 | nb = nb->next; 288 | } else { // cmp < 0. 289 | na_prev = na; 290 | na = na->next; 291 | } 292 | 293 | if (na == NULL) { 294 | na_prev->next = cloneSymbolList(nb); // attach the rest of nb. 295 | break; 296 | } else if (nb == NULL) { 297 | break; 298 | } 299 | //writeSymbolList(a, "a"); 300 | } 301 | 302 | return a; 303 | } 304 | 305 | 306 | void writeSymbolList(SymbolList a, char * name) { 307 | SymbolNode * b = a; 308 | if (name != NULL) printf("%s: ", name); 309 | if (b != NULL) { 310 | printf("%s", b->snode->symbol); 311 | for (b = b->next; b != NULL; b = b->next) { 312 | printf(", %s", b->snode->symbol); 313 | } 314 | printf("\n"); 315 | } 316 | } 317 | 318 | 319 | /******************************************* 320 | * Function for SymbolTblNode. 321 | *******************************************/ 322 | 323 | /* 324 | * create a symbol table node, used by hash table HashTbl. 325 | */ 326 | SymbolTblNode * createSymbolTblNode(char * symbol) { 327 | SymbolTblNode * n; 328 | 329 | if (symbol == NULL) 330 | YYERR_EXIT("createSymbolTblNode error: symbol is NULL\n"); 331 | 332 | n = (SymbolTblNode *) malloc(sizeof(SymbolTblNode)); 333 | if (n == NULL) 334 | YYERR_EXIT("createSymbolTblNode error: out of memory\n"); 335 | n->symbol = (char *) malloc(sizeof(char) * (strlen(symbol) + 1)); 336 | strcpy(n->symbol, symbol); 337 | n->next = NULL; 338 | n->type = _NEITHER; 339 | n->vanishable = 0; // default value: FALSE 340 | n->seq = -1; 341 | n->ruleIDList = NULL; 342 | n->TP = NULL; // terminal property. 343 | n->value = 0; 344 | return n; 345 | } 346 | 347 | 348 | /* 349 | * Empty string and EOF '$' are _NEITHER type. 350 | */ 351 | static char * getSymbolType(SymbolTblNode * n) { 352 | if (n->type == _TERMINAL) return "T"; 353 | if (n->type == _NONTERMINAL) return "NT"; 354 | return "-"; 355 | } 356 | 357 | 358 | static char * getAssocName(associativity a) { 359 | if (a == _LEFT) return "left"; 360 | if (a == _RIGHT) return "right"; 361 | if (a == _NONASSOC) return "none"; 362 | return "--unknonw--"; 363 | } 364 | 365 | 366 | /******************************************* 367 | * Hash table functions. 368 | *******************************************/ 369 | 370 | void testHashTbl() { 371 | hashTbl_insert("xin"); 372 | hashTbl_insert("abe"); 373 | hashTbl_insert("xin"); 374 | hashTbl_insert(""); 375 | hashTbl_insert(""); 376 | 377 | hashTbl_find(""); 378 | hashTbl_find("abe"); 379 | hashTbl_find("ooo"); 380 | 381 | hashTbl_dump(); 382 | hashTbl_destroy(); 383 | printf("---------------\n"); 384 | } 385 | 386 | 387 | void hashTbl_init() { 388 | int i; 389 | for (i = 0; i < HT_SIZE; i ++) { 390 | HashTbl[i].count = 0; 391 | HashTbl[i].next = NULL; 392 | } 393 | 394 | #if DEBUG_HASHTBL 395 | printf("size of hash table = %d\n", sizeof(HashTbl)); 396 | #endif 397 | //testHashTbl(); 398 | } 399 | 400 | 401 | /* 402 | * Assumption: symbol != NULL. 403 | * empty string is allowed. 404 | */ 405 | static int hash_value(char * symbol) { 406 | int i, sum; 407 | int len = strlen(symbol); 408 | 409 | sum = 0; 410 | for (i = 0; i < len; i ++) { 411 | sum = (sum + symbol[i]) % HT_SIZE; 412 | } 413 | 414 | #if DEBUG_HASHTBL 415 | printf("hash value for %s is %d\n", symbol, sum); 416 | #endif 417 | 418 | return sum; 419 | } 420 | 421 | 422 | /* 423 | * If the symbol exists, return the node, 424 | * otherwise create a node and return the node. 425 | * 426 | * So this contains the function of hashTbl_find(). 427 | * If it's unknown whether a symbol exists, use 428 | * this function to ensure getting a node contains 429 | * this symbol. 430 | */ 431 | SymbolTblNode * hashTbl_insert(char * symbol) { 432 | int v; 433 | SymbolTblNode * n; 434 | 435 | if (symbol == NULL) return NULL; 436 | v = hash_value(symbol); 437 | 438 | if (HashTbl[v].next == NULL) { 439 | HashTbl[v].next = createSymbolTblNode(symbol); 440 | HashTbl[v].count ++; 441 | return HashTbl[v].next; 442 | } else { 443 | for (n = HashTbl[v].next; n->next != NULL; n = n->next) { 444 | if (strcmp(n->symbol, symbol) == 0) { 445 | #if DEBUG_HASHTBL 446 | printf("node for string %s exists\n", symbol); 447 | #endif 448 | return n; 449 | } 450 | } 451 | // the last node on this linked list. 452 | if (strcmp(n->symbol, symbol) == 0) { 453 | #if DEBUG_HASHTBL 454 | printf("node for string %s exists\n", symbol); 455 | #endif 456 | return n; 457 | } 458 | n->next = createSymbolTblNode(symbol); 459 | HashTbl[v].count ++; 460 | return n->next; 461 | } 462 | } 463 | 464 | 465 | /* 466 | * Return the node for symbol. 467 | * If symbol does not exist, return NULL. 468 | */ 469 | SymbolTblNode * hashTbl_find(char * symbol) { 470 | int v; 471 | SymbolTblNode * n; 472 | 473 | if (symbol == NULL) return NULL; 474 | v = hash_value(symbol); 475 | 476 | for (n = HashTbl[v].next; n != NULL; n = n->next) { 477 | if (strcmp(n->symbol, symbol) == 0) { 478 | #if DEBUG_HASHTBL 479 | printf("node for %s is found\n"); 480 | #endif 481 | return n; 482 | } 483 | } 484 | 485 | #if DEBUG_HASHTBL 486 | printf("node for %s is NOT found\n", symbol); 487 | #endif 488 | 489 | return NULL; 490 | } 491 | 492 | 493 | void hashTbl_destroy() { 494 | int i; 495 | SymbolTblNode * n, * nnext; 496 | 497 | //printf("--destroy hash table--\n"); 498 | for (i = 0; i < HT_SIZE; i ++) { 499 | if (HashTbl[i].count > 0) { 500 | for (n = HashTbl[i].next; n != NULL; n = nnext) { 501 | nnext = n->next; 502 | //printf("freeing node for %s\n", n->symbol); 503 | free(n->symbol); 504 | destroyRuleIDList(n->ruleIDList); 505 | free(n); 506 | } 507 | } 508 | } 509 | } 510 | 511 | 512 | void SymbolTblNode_dump(SymbolTblNode * n) { 513 | yyprintf6("%s [type=%s,vanish=%s,seq=%d,val=%d", 514 | n->symbol, getSymbolType(n), 515 | (n->vanishable == 1) ? "T" : "F", 516 | n->seq, n->value); 517 | if (n->type == _TERMINAL && n->TP != NULL) { 518 | yyprintf3(",prec=%d,assoc=%s", n->TP->precedence, 519 | getAssocName(n->TP->assoc)); 520 | } 521 | yyprintf("]"); 522 | } 523 | 524 | 525 | void hashTbl_dump() { 526 | int i, count = 0, list_count = 0; 527 | SymbolTblNode * n; 528 | 529 | yyprintf("\n\n--Hash table--\n"); 530 | for (i = 0; i < HT_SIZE; i ++) { 531 | if (HashTbl[i].count > 0) { 532 | list_count ++; 533 | yyprintf3("HashTbl[%d] (count=%d): ", i, HashTbl[i].count); 534 | for (n = HashTbl[i].next; n->next != NULL; n = n->next) { 535 | SymbolTblNode_dump(n); 536 | yyprintf(", "); 537 | count ++; 538 | } 539 | SymbolTblNode_dump(n); 540 | yyprintf("\n"); 541 | count ++; 542 | } 543 | } 544 | yyprintf2("--hash table size: %d--\n", HT_SIZE); 545 | yyprintf5("--symbol count: %d, load factor lamda (%d/%d) = %.3f--\n", 546 | count, count, HT_SIZE, ((double) count) / HT_SIZE); 547 | yyprintf5("--list count: %d. Hash Table cell usage (%d/%d) = %.3f--\n", 548 | list_count, list_count, HT_SIZE, 549 | ((double) list_count) / HT_SIZE); 550 | yyprintf2("--symbols per list: %.3f--\n", 551 | ((double) count) / list_count); 552 | 553 | //hashTbl_destroy(); 554 | } 555 | 556 | 557 | -------------------------------------------------------------------------------- /bld/hyacc/version.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Hyacc, a LR(0)/LALR(1)/LR(1) parser generator. 3 | Copyright (C) 2007 Xin Chen. chenx@hawaii.edu 4 | 5 | Hyacc is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Hyacc is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Hyacc; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /* 21 | * version.c 22 | * 23 | * Gives version number of the hyacc release. 24 | * 25 | * @Author: Xin Chen 26 | * @Date started: February 8, 2007 27 | * @Last modified: October 27, 2007 28 | * @Copyright (C) 2007 29 | */ 30 | 31 | #include "y.h" 32 | 33 | char * HYACC_VERSION = "HYACC version 0.95 (2009)\n\ 34 | Copyright (C) 2007, 2008, 2009 Xin Chen\n\n\ 35 | Hyacc uses GNU GPL license. \n\ 36 | The parser engine hyaccpar uses BSD license. \n\ 37 | See the source for license information.\ 38 | "; 39 | 40 | void print_version() { 41 | printf("%s\n", HYACC_VERSION); 42 | } 43 | -------------------------------------------------------------------------------- /bld/hyaccMake.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### hyacc make invocation script 4 | 5 | cd $2 6 | $1 $3 -s 7 | exit 8 | -------------------------------------------------------------------------------- /bld/lexerStructGen.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/globalDefs.h" 2 | #include "../src/constantDefs.h" 3 | 4 | #include "../src/lexerNodeStruct.h" 5 | 6 | map tokenMap; 7 | 8 | int mapToken(string s) { 9 | map::iterator queryBuf = tokenMap.find(s); 10 | if (queryBuf != tokenMap.end()) { // query hit 11 | return queryBuf->second; 12 | } else { // query miss 13 | int newId = tokenMap.size(); 14 | tokenMap.insert( make_pair(s, newId) ); 15 | return newId; 16 | } 17 | } 18 | 19 | // parses the lexer table into an includable .h file with the appropriate struct representation 20 | int main() { 21 | // input file 22 | FILE *in; 23 | in = fopen("./src/lexerTable.txt","r"); 24 | if (in == NULL) { // if file open failed, return an error 25 | return -1; 26 | } 27 | // output files 28 | FILE *out; 29 | out = fopen("./tmp/lexerStruct.h","w"); 30 | if (out == NULL) { // if file open failed, return an error 31 | return -1; 32 | } 33 | FILE *out2; 34 | out2 = fopen("./tmp/lexerStruct.cpp","w"); 35 | if (out2 == NULL) { // if file open failed, return an error 36 | return -1; 37 | } 38 | FILE *lnr; 39 | lnr = fopen("./tmp/lexerNodeRaw.h","w"); 40 | if (lnr == NULL) { // if file open failed, return an error 41 | return -1; 42 | } 43 | 44 | // print the necessary prologue into the .cpp 45 | fprintf(out2, "#include \"lexerStruct.h\"\n\n"); 46 | 47 | // create the lexer node array 48 | LexerNode lexerNode[256][256]; 49 | for (int i = 0; i<256; i++) { 50 | for (int j = 0; j<256; j++) { 51 | lexerNode[i][j] = (LexerNode){ -1, 0 }; // -1 tokenType indicates an invalid node 52 | } 53 | } 54 | // now, process the input file 55 | // data buffers 56 | char lineBuf[MAX_STRING_LENGTH]; 57 | int fromState; 58 | unsigned char c; 59 | char tokenTypeCString[MAX_STRING_LENGTH]; 60 | int toState; 61 | // read the lexer data 62 | for(;;) { 63 | char *retVal = fgets(lineBuf, MAX_STRING_LENGTH, in); 64 | if (retVal == NULL) { // if we've reached the end of the file, break out of the loop 65 | break; 66 | } 67 | // the line was valid, so now try parsing the data out of it 68 | int retVal2 = sscanf(lineBuf, "%d %c %s %d", &fromState, &c, tokenTypeCString, &toState); 69 | string tokenTypeString(tokenTypeCString); // create a c++ string out of the c string 70 | if (retVal2 >= 0 && retVal2 <= 3) { // if it was a blank/incomplete line, skip it 71 | continue; 72 | } else if (retVal2 == 4) { // else if it was a valid data line, process it normally 73 | int tokenType = mapToken(tokenTypeString); // get the token mapping 74 | lexerNode[fromState][c] = (LexerNode){ tokenType, toState }; 75 | } 76 | } 77 | 78 | // print out the header notice to the .cpp 79 | fprintf(out2, "/* NOTE: This file was automatically generated by src/lexerStructGen.cpp -- do not modify it */\n\n"); 80 | // print out tokenType2String to the .cpp 81 | fprintf(out2, "const char *tokenType2String(int tokenType) {\n"); 82 | fprintf(out2, "\tswitch(tokenType) {\n"); 83 | for (map::iterator queryBuf = tokenMap.begin(); queryBuf != tokenMap.end(); queryBuf++) { 84 | fprintf(out2, "\t\tcase TOKEN_%s:\n", queryBuf->first.c_str()); 85 | fprintf(out2, "\t\t\treturn \"%s\";\n", queryBuf->first.c_str()); 86 | fprintf(out2, "\t\t\tbreak;\n"); 87 | } 88 | // print out additional $end token case 89 | fprintf(out2, "\t\tcase TOKEN_END:\n"); 90 | fprintf(out2, "\t\t\treturn \"END\";\n"); 91 | fprintf(out2, "\t\t\tbreak;\n"); 92 | // print out epilogue 93 | fprintf(out2, "\t}\n"); 94 | fprintf(out2, "\treturn NULL; // can't happen if the above covers all cases, which it should\n"); 95 | fprintf(out2, "}\n"); 96 | 97 | // print out string2TokenType to the .cpp 98 | fprintf(out2, "unsigned int string2TokenType(string s) {\n"); 99 | for (map::iterator queryBuf = tokenMap.begin(); queryBuf != tokenMap.end(); queryBuf++) { 100 | fprintf(out2, "\tif (s == \"TOKEN_%s\")\n", queryBuf->first.c_str()); 101 | fprintf(out2, "\t\treturn TOKEN_%s;\n", queryBuf->first.c_str()); 102 | } 103 | // print out additional $end token case 104 | fprintf(out2, "\tif (s == \"TOKEN_END\")\n"); 105 | fprintf(out2, "\t\treturn TOKEN_END;\n"); 106 | // print out epilogue 107 | fprintf(out2, "\treturn NUM_TOKENS; // can't happen if the above covers all cases, which it should\n"); 108 | fprintf(out2, "}\n"); 109 | 110 | // print out the header notice to the .h 111 | fprintf(out, "/* NOTE: This file was automatically generated by src/lexerStructGen.cpp -- do not modify it */\n\n"); 112 | // print the necessary prologue into the .h 113 | fprintf(out, "#ifndef _LEXER_STRUCT_H_\n"); 114 | fprintf(out, "#define _LEXER_STRUCT_H_\n\n"); 115 | fprintf(out, "#include \"../src/globalDefs.h\"\n\n"); 116 | fprintf(out, "#include \"../src/lexerNodeStruct.h\"\n\n"); 117 | // print out token definitions to the .h 118 | fprintf(out, "#define NUM_TOKENS %u\n\n", ((unsigned int)tokenMap.size() + 2)); // plus 2 due to TOKEN_END and TOKEN_STD 119 | for (map::iterator queryBuf = tokenMap.begin(); queryBuf != tokenMap.end(); queryBuf++) { 120 | fprintf(out, "#define TOKEN_%s %d\n", queryBuf->first.c_str(), queryBuf->second); 121 | } 122 | // print out additional $end token definition 123 | fprintf(out, "#define TOKEN_END %u\n", (unsigned int)tokenMap.size()); 124 | fprintf(out, "#define TOKEN_STD %u\n", (unsigned int)tokenMap.size() + 1); 125 | fprintf(out, "\n"); 126 | // print out the forward declarations to the .h 127 | fprintf(out, "const char *tokenType2String(int tokenType);\n"); 128 | fprintf(out, "unsigned int string2TokenType(string s);\n\n"); 129 | fprintf(out, "#endif\n"); 130 | 131 | // print out the lexer node struct array 132 | fprintf(lnr, "const LexerNode lexerNode[256][256] = {\n"); 133 | for (unsigned int i=0; i < 256; i++) { 134 | fprintf(lnr, "\t{\n"); 135 | for (unsigned int j=0; j < 256; j++) { 136 | fprintf(lnr, "\t\t{ %d, %d },\n", lexerNode[i][j].tokenType, lexerNode[i][j].toState); 137 | } 138 | fprintf(lnr, "\t},\n"); 139 | } 140 | fprintf(lnr, "};\n"); 141 | 142 | // finally, return normally 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /bld/parserStructGen.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/globalDefs.h" 2 | #include "../src/constantDefs.h" 3 | 4 | #include "../tmp/lexerStruct.h" 5 | #include "../src/parserNodeStruct.h" 6 | 7 | #define NUM_RULES 512 8 | 9 | // parses the generated parse table into an includable .h file with the appropriate struct representation 10 | int main() { 11 | // input file 12 | FILE *in; 13 | in = fopen("./tmp/parserTable.txt","r"); 14 | if (in == NULL) { // if file open failed, return an error 15 | return -1; 16 | } 17 | // output files 18 | FILE *header; 19 | header = fopen("./tmp/parserStruct.h","w"); 20 | if (header == NULL) { // if file open failed, return an error 21 | return -1; 22 | } 23 | FILE *pnr; 24 | pnr = fopen("./tmp/parserNodeRaw.h","w"); 25 | if (pnr == NULL) { // if file open failed, return an error 26 | return -1; 27 | } 28 | FILE *rltt; 29 | rltt = fopen("./tmp/ruleLhsTokenTypeRaw.h","w"); 30 | if (rltt == NULL) { // if file open failed, return an error 31 | return -1; 32 | } 33 | FILE *rlts; 34 | rlts = fopen("./tmp/ruleLhsTokenStringRaw.h","w"); 35 | if (rlts == NULL) { // if file open failed, return an error 36 | return -1; 37 | } 38 | FILE *rrl; 39 | rrl = fopen("./tmp/ruleRhsLengthRaw.h","w"); 40 | if (rrl == NULL) { // if file open failed, return an error 41 | return -1; 42 | } 43 | 44 | // print out the header notice to the .h 45 | fprintf(header, "/* NOTE: This file was automatically generated by src/parserStructGen.cpp -- do not modify it */\n\n"); 46 | // print the necessary prologue into the .h 47 | fprintf(header, "#ifndef _PARSER_STRUCT_H_\n"); 48 | fprintf(header, "#define _PARSER_STRUCT_H_\n\n"); 49 | fprintf(header, "#include \"../tmp/lexerStruct.h\"\n"); 50 | fprintf(header, "#include \"../src/parserNodeStruct.h\"\n\n"); 51 | fprintf(header, "#define NUM_RULES %d\n\n", NUM_RULES); 52 | 53 | // now, process the input file 54 | char lineBuf[MAX_STRING_LENGTH]; // line data buffer 55 | 56 | // first, scan ahead to the parser table 57 | bool tableFound = false; 58 | for(;;) { 59 | char *retVal = fgets(lineBuf, MAX_STRING_LENGTH, in); 60 | if (retVal == NULL) { // if we've reached the end of the file, break out of the loop 61 | break; 62 | } 63 | if (strcmp(lineBuf,"--Parsing Table--\n") == 0) { // if we've found the beginning of the parse table, break out of the loop 64 | tableFound = true; 65 | break; 66 | } 67 | } 68 | // if we couldn't find a parse table block, return with an error 69 | if (!tableFound) { 70 | return -1; 71 | } 72 | 73 | // now, extract the token ordering from the header row 74 | // read the header into the line buffer 75 | char *retVal = fgets(lineBuf, MAX_STRING_LENGTH, in); 76 | if (retVal == NULL) { // if we've reached the end of the file, return an error code 77 | return -1; 78 | } 79 | // discard the initial "State" 80 | char *lbCur = lineBuf; 81 | char junk[MAX_STRING_LENGTH]; 82 | sscanf(lbCur, "%s", junk); 83 | lbCur += strlen(junk)+1; // scan past the "State" 84 | // read in the token ordering itself 85 | bool parsingNonTerms = false; // whether we have reached the nonterminal part yet 86 | unsigned int nonTermCount = 0; 87 | string token; // temporary token string 88 | map tokenOrder; 89 | map tokenClassifier; 90 | for(;;) { 91 | if (sscanf(lbCur, "%s", junk) < 1) { 92 | break; 93 | } 94 | lbCur += strlen(junk)+1; 95 | // allocate a string with this token in it 96 | token = "TOKEN_"; 97 | // $end token special-casing 98 | if (strcmp(junk, "$end") == 0) { 99 | token += "END"; 100 | } else { 101 | token += junk; 102 | } 103 | if (token == "TOKEN_Program") { 104 | parsingNonTerms = true; 105 | } 106 | if (parsingNonTerms) { 107 | fprintf(header, "#define %s NUM_TOKENS + %d\n", token.c_str(), nonTermCount); 108 | nonTermCount++; 109 | } 110 | // push the string to the token ordering map 111 | tokenOrder.insert( make_pair(tokenOrder.size(), token) ); 112 | unsigned int mapping = string2TokenType(token); 113 | if (mapping != NUM_TOKENS) { // if it's a lexerStruct mapping 114 | tokenClassifier.insert( make_pair(token, mapping) ); 115 | } else { // otherwise, if it's a parserStruct mapping 116 | tokenClassifier.insert( make_pair(token, (NUM_TOKENS + (nonTermCount - 1))) ); 117 | } 118 | } 119 | // print out the definition of the number of nonterminals 120 | fprintf(header, "\n"); 121 | fprintf(header, "#define NUM_NONTERMS %d\n\n", nonTermCount); 122 | // print out the definition for the total label count 123 | fprintf(header, "#define NUM_LABELS NUM_TOKENS + NUM_NONTERMS\n\n"); 124 | // print out the epilogue into the .h 125 | fprintf(header, "#endif\n"); 126 | 127 | // now, back up in the file and scan ahead to the rule declarations 128 | fseek(in, 0, SEEK_SET); 129 | bool rulesFound = false; 130 | for(;;) { 131 | char *retVal = fgets(lineBuf, MAX_STRING_LENGTH, in); 132 | if (retVal == NULL) { // if we've reached the end of the file, break out of the loop 133 | break; 134 | } 135 | if (strcmp(lineBuf,"Rules: \n") == 0) { // if we've found the beginning of the rules, break out of the loop 136 | rulesFound = true; 137 | break; 138 | } 139 | } 140 | // if we couldn't find a rule block, return with an error 141 | if (!rulesFound) { 142 | return -1; 143 | } 144 | 145 | // print out the ruleLhsTokenType, ruleLshTokenString, and ruleRhsLength header notices 146 | fprintf(rltt, "/* NOTE: This file was automatically generated by src/parserStructGen.cpp -- do not modify it */\n\n"); 147 | fprintf(rlts, "/* NOTE: This file was automatically generated by src/parserStructGen.cpp -- do not modify it */\n\n"); 148 | fprintf(rrl, "/* NOTE: This file was automatically generated by src/parserStructGen.cpp -- do not modify it */\n\n"); 149 | // print out the ruleLhsTokenType, ruleLshTokenString, and ruleRhsLength array initializers 150 | fprintf(rltt, "const int ruleLhsTokenType[NUM_RULES] = {\n"); 151 | fprintf(rlts, "const char *ruleLhsTokenString[NUM_RULES] = {\n"); 152 | fprintf(rrl, "const unsigned int ruleRhsLength[NUM_RULES] = {\n"); 153 | // get rule lengths 154 | for (unsigned int i=0; true; i++) { // per-rule line loop 155 | // read in a line 156 | char *retVal = fgets(lineBuf, MAX_STRING_LENGTH, in); 157 | if (retVal == NULL) { // if we've reached the end of the file, break out of the loop 158 | return -1; 159 | } 160 | char *lbCur = lineBuf; 161 | // discard the junk before the rule's lhs 162 | char junk[MAX_STRING_LENGTH]; 163 | sscanf(lbCur, "%s", junk); // scan the first token of the line 164 | if (junk[0] == 'N') { // break if we've reached the end of the rule set 165 | break; 166 | } 167 | // scan over to the next token 168 | lbCur += strlen(junk); 169 | while (lbCur[0] == ' ' || lbCur[0] == 't') { 170 | lbCur++; 171 | } 172 | // scan in the lhs of the rule 173 | sscanf(lbCur, "%s", junk); 174 | string lhs(junk); // log the lhs in a string wrapper 175 | // scan over to the next token 176 | lbCur += strlen(junk); 177 | while (lbCur[0] == ' ' || lbCur[0] == 't') { 178 | lbCur++; 179 | } 180 | sscanf(lbCur, "%s", junk); // scan and throw away the next "->" token in the line 181 | // scan over to the next token 182 | lbCur += strlen(junk); 183 | while (lbCur[0] == ' ' || lbCur[0] == 't') { 184 | lbCur++; 185 | } 186 | // now, count the number of elements on the RHS 187 | int rhsElements = 0; 188 | for(;;) { 189 | if (sscanf(lbCur, "%s", junk) < 1 || junk[0] == '(') { // break wif we reach the end of the line 190 | break; 191 | } 192 | // scan over to the next token 193 | lbCur += strlen(junk); 194 | while (lbCur[0] == ' ' || lbCur[0] == 't') { 195 | lbCur++; 196 | } 197 | rhsElements++; 198 | } 199 | // then, log the lhs tokenType, lhs tokenString and rhs size of the rule in the corresponding arrays 200 | if (lhs != "$accept") { 201 | fprintf(rltt, "\tTOKEN_%s,\n", lhs.c_str()); 202 | fprintf(rlts, "\t\"%s\",\n", lhs.c_str()); 203 | } else { 204 | fprintf(rltt, "\t0,\n"); 205 | fprintf(rlts, "\t\"\",\n"); 206 | } 207 | fprintf(rrl, "\t%d,\n", rhsElements); 208 | } 209 | fprintf(rltt, "};\n"); 210 | fprintf(rlts, "};\n"); 211 | fprintf(rrl, "};\n"); 212 | 213 | // now, scan ahead to the parse table 214 | tableFound = false; 215 | for(;;) { 216 | char *retVal = fgets(lineBuf, MAX_STRING_LENGTH, in); 217 | if (retVal == NULL) { // if we've reached the end of the file, break out of the loop 218 | break; 219 | } 220 | if (strcmp(lineBuf,"--Parsing Table--\n") == 0) { // if we've found the beginning of the parse table, break out of the loop 221 | tableFound = true; 222 | break; 223 | } 224 | } 225 | if (!tableFound) { // if we couldn't find a parse table block, return with an error 226 | return -1; 227 | } else { // otherwise, eat the header line and return an error if this fails 228 | char *retVal = fgets(lineBuf, MAX_STRING_LENGTH, in); 229 | if (retVal == NULL) { // if we've reached the end of the file, break out of the loop 230 | return -1; 231 | } 232 | } 233 | 234 | // finally, process the raw parse table actions 235 | ParserNode parserNode[NUM_RULES][NUM_TOKENS + nonTermCount]; 236 | for (unsigned int i=0; i < NUM_RULES; i++) { 237 | for (unsigned int j=0; j < (NUM_TOKENS + nonTermCount); j++) { 238 | parserNode[i][j].action = ACTION_ERROR; 239 | parserNode[i][j].n = ACTION_ERROR; 240 | } 241 | } 242 | for(;;) { 243 | char *retVal = fgets(lineBuf, MAX_STRING_LENGTH, in); 244 | if (retVal == NULL || lineBuf[0] == 'N') { // if we've reached the end of the table, break out of the loop 245 | break; 246 | } 247 | // the line was valid, so now try parsing the data out of it 248 | int fromState; 249 | // first, read the state number 250 | char *lbCur = lineBuf; 251 | sscanf(lbCur, "%s", junk); 252 | // advance past the current token 253 | lbCur += strlen(junk); 254 | while(lbCur[0] == ' ' || lbCur[0] == '\t') { 255 | lbCur++; 256 | } 257 | // parse out the state number from the string 258 | fromState = atoi(junk); 259 | // now, read all of the transitions for this state 260 | for(unsigned int i=0; i var/testCertificate.dat 16 | else 17 | echo -------------------------------- 18 | echo Failed default test cases! 19 | echo "NOTE: This is the expected behaviour for now; there's still work to be done." 20 | rm -f var/testCertificate.dat 21 | fi 22 | exit 0 23 | -------------------------------------------------------------------------------- /bld/version.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../src/constantDefs.h" 7 | #include "../src/globalDefs.h" 8 | 9 | // prints the buildnumber to stdout 10 | int main(int argc, char **argv) { 11 | if (argc != 4) { 12 | printf("version controller: expects 3 arguments\n"); 13 | return 1; 14 | } 15 | 16 | unsigned long buildNumber; 17 | char *dateHash = argv[3]; 18 | 19 | char *versionString = argv[1]; 20 | FILE *f; 21 | if ((f = fopen("var/version.cfg","r")) == NULL) { // if no version file exists, create one 22 | f = fopen("var/version.cfg","w"); 23 | buildNumber = 1; 24 | fprintf(f,"%s %lu\n", versionString, buildNumber); 25 | fclose(f); 26 | } else { // a version file exists, so use it 27 | char version[MAX_STRING_LENGTH]; 28 | int retVal = fscanf(f, "%s %lu", version, &buildNumber); 29 | if (retVal != 2) { 30 | cerr << "Error reading var/version.cfg" << endl; 31 | exit(1); 32 | } 33 | fclose(f); 34 | f = fopen("var/version.cfg","w"); 35 | if (strcmp(version, versionString) == 0) { // if we're still on the same version 36 | buildNumber++; 37 | } else { // else if we've moved on to a new version 38 | buildNumber = 1; 39 | } 40 | fprintf(f,"%s %lu\n", versionString, buildNumber); 41 | fclose(f); 42 | } 43 | 44 | f = fopen("var/versionStamp.txt","w"); 45 | fprintf(f, "%lu.%s", buildNumber, dateHash); 46 | fclose(f); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /man/anic.1: -------------------------------------------------------------------------------- 1 | .TH ANIC "1" "January 2010" "ANI Toolchain" "ANI" 2 | .SH NAME 3 | \fBanic\fR \- ANI programming language compiler 4 | .SH SYNOPSIS 5 | .B anic 6 | \fIsourceFile\fR... [-] [-o \fIoutputFile\fR] [-p \fIoptimizationLevel\fR] [-v] [-s] [-t \fItabWidth\fR] [-e] [-h] 7 | .SH DESCRIPTION 8 | .PP 9 | Compile, assemble, and link ANI source code to produce program executables. 10 | .SH OPTIONS 11 | .PP 12 | .TP 13 | \fB\-\fR 14 | read standard input as if it were a source file 15 | .TP 16 | \fB\-o \fR\fIfilename\fR 17 | output the resulting binary to \fR\fIfilename\fR 18 | .IP 19 | If this option is not specified, the default is \fIa.out\fR. 20 | .TP 21 | \fB\-p \fR\fIn\fR 22 | use level \fR\fIn\fR code optimizations during compilation 23 | .IP 24 | The valid range is \fB0\fR to \fB3\fR inclusive, with larger values specifying increasingly more powerful (but also more time-consuming) optimizations. 25 | In general, a larger value means longer compilation times but faster resulting binaries. 26 | If this option is not specified, the default is \fI1\fR. 27 | .TP 28 | \fB\-v\fR 29 | verbose mode; print additional information about the compilation process on standard output 30 | .IP 31 | The additional information includes lexical tokens, parsing transitions, symbol trees, typing information, and resource allocation. 32 | .IP 33 | It is highly recommended to pipe the output of this option to a file or stream viewer, as it can be quite lengthy even for small source programs. 34 | .IP 35 | For example, 36 | .IP 37 | \fBanic \fR\fIprogram.ani\fR\fB \-v | less\fR 38 | .IP 39 | will make viewing the verbose ouput much more manageable. 40 | .IP 41 | Cannot be used with \fB\-s\fR. 42 | .TP 43 | \fB\-s\fR 44 | silent mode; print nothing, not even compilation errors, on any standard output 45 | .IP 46 | Cannot be used with \fB\-v\fR or \fB\-c\fR. 47 | .TP 48 | \fB\-c\fR 49 | color-coded output mode; print additional ANSI CSI control codes on standard and error outputs to make them more readable in a terminal 50 | .IP 51 | Most useful with \fB\-v\fR. Note that these control codes can cause readability problems outside of a terminal context, and that they will usually carry over unfiltered if the outputs are redirected (e.g. to a stream viewer or a file). 52 | .IP 53 | Cannot be used with \fB\-s\fR. 54 | .TP 55 | \fB\-t \fR\fIn\fR\fR 56 | use a tab modulus (width) of \fR\fIn\fR characters 57 | .IP 58 | The valid range is \fB1\fR to \fB80\fR inclusive. 59 | .IP 60 | This option does not affect the compilation process. It simply defines how the compiler reports the column numbers of tokens in the presence of tab characters. 61 | If this option is not specified, the default is \fI4\fR. 62 | .TP 63 | \fB\-e\fR 64 | pedantic error handling; do not to give up on compilation even when encountering confusing or large volumes of errors 65 | .IP 66 | Cannot be used with \fB\-s\fR. 67 | .TP 68 | \fB\-h\fR 69 | program help; display this man page 70 | .IP 71 | Must be the only argument. 72 | .SH EXAMPLES 73 | .TP 74 | \fBanic \fR\fIprogram.ani\fR 75 | Compile, assemble, and link the ANI program in source file 76 | .br 77 | \fIprogram.ani\fR and output the resulting binary to \fIa.out\fR. 78 | .TP 79 | \fBanic \fR\fIprogram.ani\fR\fB \-o \fR\fIprogram\fR 80 | Compile, assemble, and link the ANI program in source file 81 | .br 82 | \fIprogram.ani\fR and output the resulting binary to \fIprogram\fR. 83 | .TP 84 | \fBanic \- \-o \fR\fIprogram\fR 85 | Same as above, except read program source from standard input. 86 | .TP 87 | \fBanic \fR\fIprogram.ani\fR\fB \-v\fR 88 | Compile \fIprogram.ani\fR to \fIa.out\fR and additionally dump verbose compilation details to standard output. 89 | .TP 90 | \fBanic \fR\fIprogram.ani\fR\fB \-p \fR\fI3\fR\fB \-t \fR\fI8\fR\fB \-e \-o \fR\fIprogram\fR 91 | Compile \fIprogram.ani\fR to binary file \fIprogram\fR using level \fI3\fR optimizations, reporting column numbers assuming tabs are \fI8\fR characters wide, and with no limits on the amount of errors reported. 92 | .SH AUTHOR 93 | Written by Kajetan "Adrian" Biedrzycki. 94 | .SH "REPORTING BUGS" 95 | Report bugs to . 96 | .SH COPYRIGHT 97 | Copyright (c) 2010 Kajetan "Adrian" Biedrzycki. 98 | .PP 99 | Licensed under GPLv3+ (GNU GPL version 3 or later). See for details. 100 | .PP 101 | This is free software: you are free to change and redistribute it. 102 | There is NO WARRANTY, to the extent permitted by law. 103 | .SH "SEE ALSO" 104 | The full documentation for \fBanic\fR and the \fBANI\fR programming language is provided on the project home page at . 105 | -------------------------------------------------------------------------------- /src/constantDefs.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONSTANT_DEFS_H_ 2 | #define _CONSTANT_DEFS_H_ 3 | 4 | #define OUTPUT_FILE_DEFAULT "a.out" 5 | #define VERBOSE_OUTPUT_DEFAULT false 6 | #define SILENT_MODE_DEFAULT false 7 | #define CODED_OUTPUT_DEFAULT false 8 | #define EVENTUALLY_GIVE_UP_DEFAULT true 9 | 10 | #define MIN_OPTIMIZATION_LEVEL 0 11 | #define MAX_OPTIMIZATION_LEVEL 3 12 | #define DEFAULT_OPTIMIZATION_LEVEL 1 13 | 14 | #define MIN_TAB_MODULUS 1 15 | #define MAX_TAB_MODULUS 80 16 | #define TAB_MODULUS_DEFAULT 4 17 | 18 | #define TOLERABLE_ERROR_LIMIT 256 19 | 20 | #define MAX_STRING_LENGTH (sizeof(char)*4096) 21 | #define MAX_INT_STRING_LENGTH 21 22 | 23 | #define STD_IN_FILE_NAME "" 24 | 25 | #define MAX_TOKEN_LENGTH 1024*128 26 | #define ESCAPE_CHARACTER '\\' 27 | #define TOKEN_RAW_VECTOR INT_MAX 28 | 29 | #define STANDARD_LIBRARY_STRING "std" 30 | #define STANDARD_LIBRARY_FILE_INDEX UINT_MAX 31 | #define STANDARD_LIBRARY_FILE_NAME "" 32 | 33 | #define BLOCK_NODE_STRING "{}" 34 | #define FILTER_NODE_STRING "[Tx]" 35 | #define OBJECT_NODE_STRING "[]" 36 | #define INSTRUCTOR_NODE_STRING "=[]" 37 | #define OUTSTRUCTOR_NODE_STRING "=[-->]" 38 | #define INSTANTIATION_NODE_STRING "[T]" 39 | #define FAKE_RECALL_NODE_PREFIX ".." 40 | #define IMPORT_DECL_STRING "" 41 | #define STANDARD_IMPORT_DECL_STRING "" 42 | 43 | #define UNIQUE_ID_PREFIX "idLabel" 44 | 45 | #define VERBOSE(s) if (verboseOutput) {s} 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/driver.cpp: -------------------------------------------------------------------------------- 1 | #include "driver.h" 2 | 3 | #include "globalDefs.h" 4 | #include "constantDefs.h" 5 | 6 | #include "outputOperators.h" 7 | 8 | #include "lexer.h" 9 | #include "parser.h" 10 | #include "semmer.h" 11 | #include "genner.h" 12 | 13 | // global variables 14 | 15 | int driverErrorCode; 16 | 17 | int optimizationLevel = DEFAULT_OPTIMIZATION_LEVEL; 18 | bool verboseOutput = VERBOSE_OUTPUT_DEFAULT; 19 | bool silentMode = SILENT_MODE_DEFAULT; 20 | bool codedOutput = CODED_OUTPUT_DEFAULT; 21 | int tabModulus = TAB_MODULUS_DEFAULT; 22 | bool eventuallyGiveUp = EVENTUALLY_GIVE_UP_DEFAULT; 23 | 24 | vector inFileNames; // source file name vector 25 | 26 | // header print functions 27 | 28 | void printHeader(void) { 29 | cerr << HEADER_LITERAL; 30 | } 31 | void printUsage(void) { 32 | cerr << USAGE_LITERAL; 33 | } 34 | void printSeeAlso(void) { 35 | cerr << SEE_ALSO_LITERAL; 36 | } 37 | void printLink(void) { 38 | cerr << LINK_LITERAL; 39 | } 40 | void printHelp(void) { 41 | printHeader(); 42 | printUsage(); 43 | printSeeAlso(); 44 | printLink(); 45 | } 46 | 47 | // system termination functions 48 | 49 | void die(int errorCode) { 50 | if (errorCode) { 51 | printError(COLOREXP(SET_TERM(RED_CODE)) << "fatal error code " << errorCode << " -- stop" << COLOREXP(SET_TERM(RESET_CODE))); 52 | } 53 | exit(errorCode); 54 | } 55 | void die(void) { 56 | die(0); 57 | } 58 | 59 | // core helper functions 60 | 61 | unsigned int nextUniqueInt = 0; 62 | unsigned int getUniqueInt() { 63 | return (nextUniqueInt++); 64 | } 65 | string getUniqueId() { 66 | string acc(UNIQUE_ID_PREFIX); 67 | acc += getUniqueInt(); 68 | return acc; 69 | } 70 | 71 | int containsString(vector inFileNames, string &s) { 72 | for (unsigned int i=0; i < inFileNames.size(); i++) { // scan the vector for matches 73 | if (inFileNames[i] == s) { // if we have a match at this index, return true 74 | return 1; 75 | } 76 | } 77 | // else if we did not find any matches, return false 78 | return 0; 79 | } 80 | 81 | // main driver function 82 | 83 | int main(int argc, char **argv) { 84 | 85 | // initialize local error code 86 | driverErrorCode = 0; 87 | 88 | // verify arguments 89 | if (argc == 1) { 90 | codedOutput = true; // enable coded output for the help text 91 | printHelp(); 92 | die(); 93 | } 94 | 95 | // parse the command-line arguments 96 | vector inFiles; // source file vector 97 | string outFileName(OUTPUT_FILE_DEFAULT); // initialize the output file name 98 | // handled flags for each option 99 | bool oHandled = false; 100 | bool pHandled = false; 101 | bool vHandled = false; 102 | bool sHandled = false; 103 | bool cHandled = false; 104 | bool tHandled = false; 105 | bool eHandled = false; 106 | for (int i=1; i= argc) { // jump to the next argument, test if it doesn't exist 110 | printError("-o expected file name argument"); 111 | die(); 112 | } 113 | outFileName = argv[i]; 114 | // flag this option as handled 115 | oHandled = true; 116 | } else if (argv[i][1] == 'p' && argv[i][2] == '\0' && !pHandled) { // optimization level option 117 | if (++i >= argc) { // jump to the next argument, test if it doesn't exist 118 | printError("-p expected optimization level argument"); 119 | die(); 120 | } 121 | int n; 122 | if (sscanf(argv[i], "%d", &n) < 1) { // unsuccessful attempt to extract a number out of the argument 123 | printError("-p got illegal optimization level '" << argv[i] << "'"); 124 | die(); 125 | } else { // else attempt was successful 126 | if (n >= MIN_OPTIMIZATION_LEVEL && n <= MAX_OPTIMIZATION_LEVEL) { 127 | optimizationLevel = n; 128 | } else { 129 | printError("-p got out-of-bounds optimization level " << n); 130 | die(); 131 | } 132 | } 133 | // flag this option as handled 134 | pHandled = true; 135 | } else if (argv[i][1] == 'v' && argv[i][2] == '\0' && !vHandled && !sHandled) { // verbose output option 136 | verboseOutput = true; 137 | VERBOSE ( 138 | printNotice("verbose output enabled"); 139 | print(""); 140 | ) 141 | // flag this option as handled 142 | vHandled = true; 143 | } else if (argv[i][1] == 's' && argv[i][2] == '\0' && !vHandled && !sHandled && !cHandled) { // silent compilation option 144 | silentMode = true; 145 | // flag this option as handled 146 | sHandled = true; 147 | } else if (argv[i][1] == 'c' && argv[i][2] == '\0' && !cHandled && !sHandled) { // coded output option 148 | codedOutput = true; 149 | // flag this option as handled 150 | cHandled = true; 151 | } else if (argv[i][1] == 't' && argv[i][2] == '\0' && !tHandled) { 152 | if (++i >= argc) { // jump to the next argument, test if it doesn't exist 153 | printError("-t expected tab modulus argument"); 154 | die(); 155 | } 156 | int n; 157 | if (sscanf(argv[i], "%d", &n) < 1) { // unsuccessful attempt to extract a number out of the argument 158 | printError("-t got illegal tab modulus '" << argv[i] << "'"); 159 | die(); 160 | } else { // else attempt was successful 161 | if (n >= MIN_TAB_MODULUS && n <= MAX_TAB_MODULUS) { 162 | tabModulus = n; 163 | } else { 164 | printError("-t got out-of-bounds tab modulus " << n); 165 | die(); 166 | } 167 | } 168 | // flag this option as handled 169 | tHandled = true; 170 | } else if (argv[i][1] == 'e' && argv[i][2] == '\0' && !eHandled && !sHandled) { 171 | eventuallyGiveUp = false; 172 | // flag this option as handled 173 | eHandled = true; 174 | } else if (argv[i][1] == 'h' && argv[i][2] == '\0' && argc == 2) { 175 | // test to see if a command interpreter is available 176 | int systemRetVal = system(NULL); 177 | if (!systemRetVal) { 178 | printError("cannot display manual page: no command interpreter available"); 179 | die(1); 180 | } 181 | // invoke the program's man page 182 | systemRetVal = system("man anic 2> /dev/null"); 183 | // test if displaying the manual page failed 184 | if (systemRetVal) { 185 | printError("cannot display manual page: executing manual driver failed"); 186 | die(1); 187 | } 188 | die(0); 189 | } else { 190 | printWarning("confused by option '" << argv[i] << "', skipping"); 191 | } 192 | 193 | } else { // default case; assume regular file argument 194 | string fileName = (argv[i][0] != '-') ? argv[i] : STD_IN_FILE_NAME; 195 | if (containsString(inFileNames, fileName)) { 196 | printWarning("including file '" << fileName << "' multiple times"); 197 | continue; 198 | } 199 | ifstream *inFile = (fileName == STD_IN_FILE_NAME) ? NULL : new ifstream(fileName.c_str()); // create a stream for this file 200 | if (inFile != NULL && !inFile->good()) { // if file open failed 201 | printError("cannot open input file '" << fileName << "'"); 202 | } else { // else if file open succeeded, add the file and its name to the appropriate vectors 203 | inFiles.push_back(inFile); 204 | inFileNames.push_back(fileName); 205 | } 206 | } 207 | } 208 | 209 | // terminate if there was an error or if there are no input files 210 | if (driverErrorCode) { 211 | die(1); 212 | } else if (inFiles.empty()) { 213 | printError("no input files"); 214 | die(); 215 | } 216 | 217 | // lex files 218 | int lexerError = 0; // error flag 219 | vector *> lexemes; // per-file vector of the lexemes that the lexer is about to generate 220 | for (unsigned int i=0; i *lexeme = lex(inFiles[i], i); 232 | if (lexeme == NULL) { // if lexing failed with an error, log the error condition 233 | thisLexError = 1; 234 | } else { // else if lexing was successful, log the lexeme to the vector 235 | lexemes.push_back(lexeme); 236 | } 237 | // print out the tokens if we're in verbose mode 238 | VERBOSE( 239 | if (!thisLexError) { 240 | printNotice(COLOREXP(SET_TERM(GREEN_CODE)) << "successfully lexed file \'" << fileName << "\'" << COLOREXP(SET_TERM(RESET_CODE))); 241 | } else { 242 | printNotice(COLOREXP(SET_TERM(RED_CODE)) << "failed to lex file \'" << fileName << "\'" << COLOREXP(SET_TERM(RESET_CODE))); 243 | } 244 | print(""); // new line 245 | ) 246 | // log the highest error code that occured 247 | if (thisLexError > lexerError) { 248 | lexerError = thisLexError; 249 | } 250 | } 251 | // now, check if lexing failed and if so, kill the system as appropriate 252 | if (lexerError) { 253 | die(1); 254 | } 255 | 256 | // parse lexemes 257 | int parserError = 0; // error flag 258 | Tree *treeRoot = NULL; // the root parseme of the parse tree 259 | Tree *treeCur = NULL; // the tail of the linked list of parsemes 260 | unsigned int fileIndex = 0; // current lexeme's file name index 261 | for (vector *>::iterator lexemeIter = lexemes.begin(); lexemeIter != lexemes.end(); lexemeIter++) { 262 | VERBOSE(printNotice("parsing file \'" << inFileNames[fileIndex] << "\'...");) 263 | // do the actual parsing 264 | Tree *thisParseme; 265 | int thisParseError = parse(*lexemeIter, thisParseme, fileIndex); 266 | if (thisParseError) { // if parsing failed with an error, log the error condition 267 | VERBOSE( 268 | printNotice(COLOREXP(SET_TERM(RED_CODE)) << "failed to parse file \'" << inFileNames[fileIndex] << "\'" << COLOREXP(SET_TERM(RESET_CODE))); 269 | print(""); // new line 270 | ) 271 | } else { // else if parsing was successful, latch the parseme into the tree trunk 272 | if (treeRoot != NULL) { // if this is not the first parseme 273 | // link in this tree 274 | *treeCur += thisParseme; 275 | // to the right 276 | // to the left 277 | *thisParseme -= treeCur; 278 | // advance treeCur to the new tail 279 | treeCur = treeCur->next; 280 | } else { // else if this is the first parseme 281 | treeRoot = treeCur = thisParseme; 282 | } 283 | VERBOSE( 284 | printNotice(COLOREXP(SET_TERM(GREEN_CODE)) << "successfully parsed file \'" << inFileNames[fileIndex] << "\'" << COLOREXP(SET_TERM(RESET_CODE))); 285 | print(""); // new line 286 | ) 287 | } 288 | // log the highest error code that occured 289 | if (thisParseError > parserError) { 290 | parserError = thisParseError; 291 | } 292 | // advance the file index 293 | fileIndex++; 294 | } 295 | // now, check if parsing failed and if so, kill the system as appropriate 296 | if (parserError) { 297 | die(1); 298 | } 299 | 300 | // perform semantic analysis 301 | 302 | VERBOSE(printNotice("mapping semantics...");) 303 | 304 | // allocate symbol tree root (will be filled with user-level definitions during parsing) 305 | SymbolTree *stRoot; 306 | // allocate the intermediate representation tree root (will be bound at the end of parsing) 307 | SchedTree *codeRoot; 308 | 309 | int semmerErrorCode = sem(treeRoot, stRoot, codeRoot); 310 | // now, check if semming failed and kill the system as appropriate 311 | if (semmerErrorCode) { 312 | VERBOSE( 313 | printNotice(COLOREXP(SET_TERM(RED_CODE)) << "failed to map semantics" << COLOREXP(SET_TERM(RESET_CODE))); 314 | print(""); // new line 315 | ) 316 | } else { 317 | VERBOSE( 318 | printNotice(COLOREXP(SET_TERM(GREEN_CODE)) << "successfully mapped semantics" << COLOREXP(SET_TERM(RESET_CODE))); 319 | print(""); // new line 320 | ) 321 | } 322 | // now, check if semming failed and if so, kill the system as appropriate 323 | if (semmerErrorCode) { 324 | die(1); 325 | } 326 | 327 | // generate the intermediate code tree 328 | 329 | VERBOSE(printNotice("generating code dump...");) 330 | 331 | // allocate the string buffer into which we will dump the resulting assembly code 332 | string asmString; 333 | 334 | // generate the actual assembly code 335 | int gennerErrorCode = gen(codeRoot, asmString); 336 | // now, check if genning failed and kill the system as appropriate 337 | if (gennerErrorCode) { 338 | VERBOSE( 339 | printNotice(COLOREXP(SET_TERM(RED_CODE)) << "failed to generate code dump" << COLOREXP(SET_TERM(RESET_CODE))); 340 | print(""); // new line 341 | ) 342 | } else { 343 | VERBOSE( 344 | printNotice(COLOREXP(SET_TERM(GREEN_CODE)) << "successfully generated code dump" << COLOREXP(SET_TERM(RESET_CODE))); 345 | print(""); // new line 346 | ) 347 | } 348 | // now, check if genning failed and if so, kill the system as appropriate 349 | if (gennerErrorCode) { 350 | die(1); 351 | } 352 | 353 | // open output file for writing 354 | ofstream *outFile = new ofstream(outFileName.c_str()); 355 | if (!outFile->good()) { 356 | printError("cannot open output file '" << outFileName << "'"); 357 | die(); 358 | } 359 | 360 | // terminate the program successfully 361 | return 0; 362 | } 363 | -------------------------------------------------------------------------------- /src/driver.h: -------------------------------------------------------------------------------- 1 | #ifndef _DRIVER_H_ 2 | #define _DRIVER_H_ 3 | 4 | #include "globalDefs.h" 5 | #include "constantDefs.h" 6 | 7 | // terminal control codes 8 | 9 | #define COLOR(s) if (codedOutput) {s} 10 | #define COLOREXP(e) (codedOutput ? (e) : "") 11 | 12 | #define SET_TERM(mode) ("\x1b[" mode "m") 13 | #define AND ";" 14 | 15 | #define RESET_CODE "0" 16 | #define BRIGHT_CODE "1" 17 | 18 | #define BLACK_CODE "30" 19 | #define RED_CODE "31" 20 | #define GREEN_CODE "32" 21 | #define YELLOW_CODE "33" 22 | #define BLUE_CODE "34" 23 | #define MAGENTA_CODE "35" 24 | #define CYAN_CODE "36" 25 | #define WHITE_CODE "37" 26 | 27 | // standard program strings 28 | 29 | #define PROGRAM_STRING COLOREXP(SET_TERM(BRIGHT_CODE AND GREEN_CODE) )<<"anic"<= TOLERABLE_ERROR_LIMIT) { printError("too many errors, giving up"); return NULL; } 57 | 58 | #define parserError(fi,r,c,str) if (!silentMode) { silentMode = true; \ 59 | cerr << ERROR_STRING << ": "<< \ 60 | COLOREXP(SET_TERM(CYAN_CODE)) << "PARSER" << COLOREXP(SET_TERM(RESET_CODE)) << \ 61 | ": " << COLOREXP(SET_TERM(BRIGHT_CODE AND BLACK_CODE)) << GET_FILE_NAME(fi) << ":" << r << ":" << c << COLOREXP(SET_TERM(RESET_CODE)) << ": " << str << ".\n"; \ 62 | silentMode = false; } \ 63 | parserErrorCode++; 64 | 65 | #define semmerError(fi,r,c,str) if (!silentMode) { silentMode = true; \ 66 | cerr << ERROR_STRING << ": "<< \ 67 | COLOREXP(SET_TERM(CYAN_CODE)) << "SEMMER" << COLOREXP(SET_TERM(RESET_CODE)) << \ 68 | ": " << COLOREXP(SET_TERM(BRIGHT_CODE AND BLACK_CODE)) << GET_FILE_NAME(fi) << ":" << r << ":" << c << COLOREXP(SET_TERM(RESET_CODE)) << ": " << str << ".\n"; \ 69 | silentMode = false; } \ 70 | semmerErrorCode++; 71 | 72 | void printHeader(void); 73 | void printUsage(void); 74 | void printSeeAlso(void); 75 | void printHelp(void); 76 | void printLink(void); 77 | const string &getFileName(unsigned int fileIndex); 78 | void die(int errorCode); 79 | void die(void); 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /src/genner.h: -------------------------------------------------------------------------------- 1 | #ifndef _GENNER_H_ 2 | #define _GENNER_H_ 3 | 4 | #include "globalDefs.h" 5 | #include "constantDefs.h" 6 | #include "driver.h" 7 | 8 | #include "lexer.h" 9 | #include "parser.h" 10 | #include "types.h" 11 | #include "semmer.h" 12 | 13 | // CodeTree category specifiers 14 | #define CATEGORY_NOP 0 15 | #define CATEGORY_LABEL 1 16 | #define CATEGORY_SEQ 2 17 | #define CATEGORY_WORD8 3 18 | #define CATEGORY_WORD16 4 19 | #define CATEGORY_WORD32 5 20 | #define CATEGORY_WORD64 6 21 | #define CATEGORY_ARRAY 7 22 | #define CATEGORY_LIST 8 23 | #define CATEGORY_TEMP 9 24 | #define CATEGORY_READ 10 25 | #define CATEGORY_UNOP 11 26 | #define CATEGORY_BINOP 12 27 | #define CATEGORY_CONVOP 13 28 | #define CATEGORY_LOCK 14 29 | #define CATEGORY_UNLOCK 15 30 | #define CATEGORY_COND 16 31 | #define CATEGORY_JUMP 17 32 | #define CATEGORY_WRITE 18 33 | #define CATEGORY_COPY 19 34 | #define CATEGORY_SCHED 20 35 | 36 | // WordTree default size 37 | #define WordTree WordTree64 38 | 39 | // IRTree classes 40 | 41 | class IRTree { 42 | public: 43 | // data members 44 | int category; // the category that this IRTree belongs to 45 | // allocators/deallocators 46 | IRTree(int category); 47 | virtual ~IRTree(); 48 | // core methods 49 | string toString(unsigned int tabDepth = 1) const; 50 | void asmDump(string &asmString) const; 51 | }; 52 | 53 | // LabelTree classes 54 | 55 | // usage: identifier-labeled sequential code block; an atomic unit of execution 56 | class LabelTree : public IRTree { 57 | public: 58 | // data members 59 | string id; // string representation of this label 60 | SeqTree *code; // pointer to the tree node containing the sequence of code trees to run 61 | // allocators/deallocators 62 | LabelTree(SeqTree *code); 63 | ~LabelTree(); 64 | // core methods 65 | string toString(unsigned int tabDepth) const; 66 | void asmDump(string &asmString) const; 67 | }; 68 | 69 | // SeqTree classes 70 | 71 | // usage: a sequence of code to execute 72 | class SeqTree : public IRTree { 73 | public: 74 | // data members 75 | vector codeList; // vector representing the sequence of code trees to execute in order 76 | // allocators/deallocators 77 | SeqTree(const vector &seqList); 78 | ~SeqTree(); 79 | // core methods 80 | string toString(unsigned int tabDepth) const; 81 | void asmDump(string &asmString) const; 82 | }; 83 | 84 | // DataTree classes 85 | 86 | // usage: abstract class; never used directly 87 | class DataTree : public IRTree { 88 | public: 89 | // allocators/deallocators 90 | DataTree(int category); 91 | virtual ~DataTree(); 92 | // core methods 93 | string toString(unsigned int tabDepth) const; 94 | void asmDump(string &asmString) const; 95 | }; 96 | 97 | // usage: an in-place inclusion of an 8-bit data word 98 | class WordTree8 : public DataTree { 99 | public: 100 | // data members 101 | uint8_t data; // the raw data word contained in this node 102 | // allocators/deallocators 103 | WordTree8(uint8_t data); 104 | ~WordTree8(); 105 | // core methods 106 | string toString(unsigned int tabDepth) const; 107 | void asmDump(string &asmString) const; 108 | }; 109 | 110 | // usage: an in-place inclusion of a 16-bit data word 111 | class WordTree16 : public DataTree { 112 | public: 113 | // data members 114 | uint16_t data; // the raw data word contained in this node 115 | // allocators/deallocators 116 | WordTree16(uint16_t data); 117 | ~WordTree16(); 118 | // core methods 119 | string toString(unsigned int tabDepth) const; 120 | void asmDump(string &asmString) const; 121 | }; 122 | 123 | // usage: an in-place inclusion of a 32-bit data word 124 | class WordTree32 : public DataTree { 125 | public: 126 | // data members 127 | uint32_t data; // the raw data word contained in this node 128 | // allocators/deallocators 129 | WordTree32(uint32_t data); 130 | ~WordTree32(); 131 | // core methods 132 | string toString(unsigned int tabDepth) const; 133 | void asmDump(string &asmString) const; 134 | }; 135 | 136 | // usage: an in-place inclusion of a 64-bit data word 137 | class WordTree64 : public DataTree { 138 | public: 139 | // data members 140 | uint64_t data; // the raw data word contained in this node 141 | // allocators/deallocators 142 | WordTree64(uint64_t data); 143 | ~WordTree64(); 144 | // core methods 145 | string toString(unsigned int tabDepth) const; 146 | void asmDump(string &asmString) const; 147 | }; 148 | 149 | // usage: an in-place inclusion of a byte-array of data 150 | class ArrayTree : public DataTree { 151 | public: 152 | // data members 153 | vector data; // vector of the raw byte-array of data contained in this node 154 | // allocators/deallocators 155 | ArrayTree(const vector &data); 156 | ~ArrayTree(); 157 | // core methods 158 | string toString(unsigned int tabDepth) const; 159 | void asmDump(string &asmString) const; 160 | }; 161 | 162 | // usage: a compounding of several data trees to be computed separately but treated atomically 163 | class CompoundTree : public DataTree { 164 | public: 165 | // data members 166 | vector dataList; // vector of the data trees that make up this node 167 | // allocators/deallocators 168 | CompoundTree(const vector &dataList); 169 | ~CompoundTree(); 170 | // core methods 171 | string toString(unsigned int tabDepth) const; 172 | void asmDump(string &asmString) const; 173 | }; 174 | 175 | // usage: allocate temporary storage for the result of an operation 176 | class TempTree : public DataTree { 177 | public: 178 | // data members 179 | OpTree *opNode; // pointer to the operation that this temporary is holding the result of 180 | // allocators/deallocators 181 | TempTree(OpTree *opNode); 182 | ~TempTree(); 183 | // core methods 184 | string toString(unsigned int tabDepth) const; 185 | void asmDump(string &asmString) const; 186 | }; 187 | 188 | // usage: read memory from the specified memory address 189 | class ReadTree : public DataTree { 190 | public: 191 | // data members 192 | DataTree *address; // pointer to the data subnode specifying the memory address to read from 193 | // allocators/deallocators 194 | ReadTree(DataTree *address); 195 | ~ReadTree(); 196 | // core methods 197 | string toString(unsigned int tabDepth) const; 198 | void asmDump(string &asmString) const; 199 | }; 200 | 201 | // OpTree classes 202 | 203 | // usage: abstract class; never used directly 204 | class OpTree : public IRTree { 205 | public: 206 | // data members 207 | int kind; // the kind of operator to apply to the subnode(s); the valid values are defined above the subclass that they apply to 208 | // allocators/deallocators 209 | OpTree(int category, int kind); 210 | virtual ~OpTree(); 211 | // core methods 212 | string kindToString() const; 213 | string toString(unsigned int tabDepth) const; 214 | void asmDump(string &asmString) const; 215 | }; 216 | 217 | // definitions of arithmetic operator kinds 218 | #define UNOP_NOT_BOOL 0 219 | 220 | #define UNOP_COMPLEMENT_INT 1 221 | 222 | #define UNOP_DPLUS_INT 2 223 | #define UNOP_DMINUS_INT 3 224 | 225 | #define BINOP_DOR_BOOL 4 226 | #define BINOP_DAND_BOOL 5 227 | 228 | #define BINOP_OR_INT 6 229 | #define BINOP_XOR_INT 7 230 | #define BINOP_AND_INT 8 231 | 232 | #define BINOP_DEQUALS 9 233 | #define BINOP_NEQUALS 10 234 | #define BINOP_LT 11 235 | #define BINOP_GT 12 236 | #define BINOP_LE 13 237 | #define BINOP_GE 14 238 | 239 | #define BINOP_LS_INT 15 240 | #define BINOP_RS_INT 16 241 | 242 | #define BINOP_TIMES_INT 17 243 | #define BINOP_DIVIDE_INT 18 244 | #define BINOP_MOD_INT 19 245 | #define BINOP_TIMES_FLOAT 20 246 | #define BINOP_DIVIDE_FLOAT 21 247 | #define BINOP_MOD_FLOAT 22 248 | 249 | #define UNOP_MINUS_INT 23 250 | #define UNOP_MINUS_FLOAT 24 251 | 252 | #define BINOP_PLUS_INT 25 253 | #define BINOP_MINUS_INT 26 254 | #define BINOP_PLUS_FLOAT 27 255 | #define BINOP_MINUS_FLOAT 28 256 | #define BINOP_PLUS_STRING 29 257 | 258 | // usage: perform the given kind of unary operation on the subnode 259 | class UnOpTree : public OpTree { 260 | public: 261 | // data members 262 | DataTree *subNode; // pointer to the data subnode that we're applying the operator to 263 | // allocators/deallocators 264 | UnOpTree(int kind, DataTree *subNode); 265 | ~UnOpTree(); 266 | // core methods 267 | string toString(unsigned int tabDepth) const; 268 | void asmDump(string &asmString) const; 269 | }; 270 | 271 | // usage: perform the given kind of binary operation on subNodeLeft and subNodeRight 272 | class BinOpTree : public OpTree { 273 | public: 274 | // data members 275 | DataTree *subNodeLeft; // pointer to the data subnode representing the left operand 276 | DataTree *subNodeRight; // pointer to the data subnode representing the right operand 277 | // allocators/deallocators 278 | BinOpTree(int kind, DataTree *subNodeLeft, DataTree *subNodeRight); 279 | ~BinOpTree(); 280 | // core methods 281 | string toString(unsigned int tabDepth) const; 282 | void asmDump(string &asmString) const; 283 | }; 284 | 285 | // definitions of conversion operator kinds 286 | #define CONVOP_INT2FLOAT 30 287 | #define CONVOP_FLOAT2INT 31 288 | 289 | #define CONVOP_BOOL2STRING 32 290 | #define CONVOP_INT2STRING 33 291 | #define CONVOP_FLOAT2STRING 34 292 | #define CONVOP_CHAR2STRING 35 293 | 294 | // usage: perform the given kind of data representation conversion operation on the specified subNode 295 | class ConvOpTree : public OpTree { 296 | public: 297 | // data members 298 | DataTree *subNode; // pointer to the data subnode representing the source of the conversion 299 | // allocators/deallocators 300 | ConvOpTree(int kind, DataTree *subNode); 301 | ~ConvOpTree(); 302 | // core methods 303 | string toString(unsigned int tabDepth) const; 304 | void asmDump(string &asmString) const; 305 | }; 306 | 307 | // CodeTree classes 308 | 309 | // usage: abstract class; never used directly 310 | class CodeTree : public IRTree { 311 | public: 312 | // allocators/deallocators 313 | CodeTree(int category); 314 | virtual ~CodeTree(); 315 | // core methods 316 | string toString(unsigned int tabDepth) const; 317 | void asmDump(string &asmString) const; 318 | }; 319 | 320 | // usage: grab a lock on the specified memory address 321 | class LockTree : public CodeTree { 322 | public: 323 | // data members 324 | DataTree *address; // pointer to the data subnode specifying the memory address to lock 325 | // allocators/deallocators 326 | LockTree(DataTree *address); 327 | ~LockTree(); 328 | // core methods 329 | string toString(unsigned int tabDepth) const; 330 | void asmDump(string &asmString) const; 331 | }; 332 | 333 | // usage: release a lock on the specified memory address 334 | class UnlockTree : public CodeTree { 335 | public: 336 | // data members 337 | DataTree *address; // pointer to the data subnode specifying the memory address to unlock 338 | // allocators/deallocators 339 | UnlockTree(DataTree *address); 340 | ~UnlockTree(); 341 | // core methods 342 | string toString(unsigned int tabDepth) const; 343 | void asmDump(string &asmString) const; 344 | }; 345 | 346 | // usage: if the boolean data word test is true, run trueBranch; otherwise, run falseBranch 347 | class CondTree : public CodeTree { 348 | public: 349 | // data members 350 | DataTree *test; // pointer to the data subnode specifying the boolean value of the test condition 351 | CodeTree *trueBranch; // pointer to the code tree to jump to on a true test value 352 | CodeTree *falseBranch; // pointer to the code tree to jump to on a true test value 353 | // allocators/deallocators 354 | CondTree(DataTree *test, CodeTree *trueBranch, CodeTree *falseBranch); 355 | ~CondTree(); 356 | // core methods 357 | string toString(unsigned int tabDepth) const; 358 | void asmDump(string &asmString) const; 359 | }; 360 | 361 | // usage: use the value of a test word to index into the given jumpTable and jump to the code contained there; the test word is guaranteed to be a valid index into the jumpTable 362 | class JumpTree : public CodeTree { 363 | public: 364 | // data members 365 | DataTree *test; // pointer to the data subnode specifying the value of the test condition 366 | vector jumpTable; // vector of pointers to the sequential code trees to run for each index value 367 | // allocators/deallocators 368 | JumpTree(DataTree *test, const vector &jumpTable); 369 | ~JumpTree(); 370 | // core methods 371 | string toString(unsigned int tabDepth) const; 372 | void asmDump(string &asmString) const; 373 | }; 374 | 375 | // usage: write the source data to the specified destination memory address 376 | class WriteTree : public CodeTree { 377 | public: 378 | // data members 379 | DataTree *source; // pointer to the source data subnode 380 | DataTree *address; // pointer to the subnode specifying the destination memory address 381 | // allocators/deallocators 382 | WriteTree(DataTree *source, DataTree *address); 383 | ~WriteTree(); 384 | // core methods 385 | string toString(unsigned int tabDepth) const; 386 | void asmDump(string &asmString) const; 387 | }; 388 | 389 | // usage: copy a length of memory bytes from the specified sourceAddress to the specified destinationAddress 390 | class CopyTree : public CodeTree { 391 | public: 392 | // data members 393 | DataTree *sourceAddress; // pointer to the data subnode specifying the base address to start copying from 394 | DataTree *destinationAddress; // pointer to the data subnode specifying the destination address to copy into 395 | uint32_t length; 396 | // allocators/deallocators 397 | CopyTree(DataTree *sourceAddress, DataTree *destinationAddress, uint32_t length); 398 | ~CopyTree(); 399 | // core methods 400 | string toString(unsigned int tabDepth) const; 401 | void asmDump(string &asmString) const; 402 | }; 403 | 404 | // usage: schedule all of the label nodes in the labelList for execution 405 | class SchedTree : public CodeTree { 406 | public: 407 | // data members 408 | vector labelList; // vector of the label nodes to schedule 409 | // allocators/deallocators 410 | SchedTree(const vector &labelList); 411 | ~SchedTree(); 412 | // core methods 413 | string toString(unsigned int tabDepth) const; 414 | void asmDump(string &asmString) const; 415 | }; 416 | 417 | // main code generation function 418 | 419 | int gen(SchedTree *codeRoot, string &asmString); 420 | 421 | #endif 422 | -------------------------------------------------------------------------------- /src/globalDefs.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_DEFS_H_ 2 | #define _MAIN_DEFS_H_ 3 | 4 | // standard includes 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | using std::cin; 22 | using std::cout; 23 | using std::cerr; 24 | using std::endl; 25 | using std::flush; 26 | using std::ifstream; 27 | using std::ofstream; 28 | using std::ostream; 29 | using std::string; 30 | using std::vector; 31 | using std::deque; 32 | using std::map; 33 | using std::stack; 34 | using std::pair; 35 | using std::make_pair; 36 | 37 | // class forward declarations 38 | 39 | class Tree; 40 | class SymbolTree; 41 | class Type; 42 | class TypeList; 43 | class StdType; 44 | class FilterType; 45 | class StructorListResult; 46 | class StructorList; 47 | class MemberListResult; 48 | class MemberList; 49 | class ObjectType; 50 | class ErrorType; 51 | class TypeStatus; 52 | class IRTree; 53 | class LabelTree; 54 | class SeqTree; 55 | class DataTree; 56 | class WordTree8; 57 | class WordTree16; 58 | class WordTree32; 59 | class WordTree64; 60 | class ArrayTree; 61 | class CompoundTree; 62 | class TempTree; 63 | class ReadTree; 64 | class OpTree; 65 | class UnOpTree; 66 | class BinOpTree; 67 | class ConvTree; 68 | class CodeTree; 69 | class LockTree; 70 | class UnlockTree; 71 | class CondTree; 72 | class JumpTree; 73 | class WriteTree; 74 | class CopyTree; 75 | class SchedTree; 76 | 77 | // global variable linkage specifiers 78 | 79 | extern int optimizationLevel; 80 | extern bool verboseOutput; 81 | extern bool silentMode; 82 | extern bool codedOutput; 83 | extern int tabModulus; 84 | extern bool eventuallyGiveUp; 85 | 86 | extern vector inFileNames; 87 | 88 | extern int driverErrorCode; 89 | extern int lexerErrorCode; 90 | extern int parserErrorCode; 91 | extern int semmerErrorCode; 92 | extern int gennerErrorCode; 93 | 94 | extern Type *nullType; 95 | extern Type *errType; 96 | class StdType; 97 | extern StdType *stdBoolType; 98 | extern StdType *stdIntType; 99 | extern StdType *stdFloatType; 100 | extern StdType *stdCharType; 101 | extern StdType *stdStringType; 102 | extern StdType *stdBoolLitType; 103 | 104 | extern StdType *inIntType; 105 | extern StdType *inFloatType; 106 | extern StdType *inCharType; 107 | extern StdType *inStringType; 108 | extern ObjectType *stringerType; 109 | extern ObjectType *boolUnOpType; 110 | extern ObjectType *intUnOpType; 111 | extern ObjectType *boolBinOpType; 112 | extern ObjectType *intBinOpType; 113 | extern ObjectType *floatBinOpType; 114 | extern ObjectType *boolCompOpType; 115 | extern ObjectType *intCompOpType; 116 | extern ObjectType *floatCompOpType; 117 | extern ObjectType *charCompOpType; 118 | extern ObjectType *stringCompOpType; 119 | 120 | extern StdType *stdLibType; 121 | extern SymbolTree *stdLib; 122 | 123 | extern IRTree *nopCode; 124 | 125 | // global function forward declarations 126 | 127 | unsigned int getUniqueInt(); 128 | string getUniqueId(); 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /src/lexer.h: -------------------------------------------------------------------------------- 1 | #ifndef _LEXER_H_ 2 | #define _LEXER_H_ 3 | 4 | #include "globalDefs.h" 5 | #include "constantDefs.h" 6 | #include "driver.h" 7 | 8 | #include "../tmp/lexerStruct.h" 9 | 10 | class Token { 11 | public: 12 | // data members 13 | int tokenType; 14 | string s; 15 | unsigned int fileIndex; 16 | int row; 17 | int col; 18 | // allocators/deallocators 19 | Token(int tokenType = TOKEN_STD); 20 | Token(int tokenType, const string &s, unsigned int fileIndex, int row, int col); 21 | Token(const Token &otherToken); 22 | ~Token(); 23 | // operators 24 | Token &operator=(Token &otherToken); 25 | operator string() const; 26 | }; 27 | 28 | vector *lex(ifstream *in, unsigned int fileIndex); 29 | 30 | // post-includes 31 | 32 | #include "../tmp/lexerStruct.h" 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/lexerNodeStruct.h: -------------------------------------------------------------------------------- 1 | #ifndef LEXER_STRUCT_NODE_H 2 | #define LEXER_STRUCT_NODE_H 3 | 4 | struct lexerNodeStruct { 5 | int tokenType; 6 | int toState; 7 | }; 8 | typedef struct lexerNodeStruct LexerNode; 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/lexerTable.txt: -------------------------------------------------------------------------------- 1 | // state 0 (core) 2 | // lowercase letters 3 | 0 a ID 1 4 | 0 b ID 1 5 | 0 c ID 1 6 | 0 d ID 1 7 | 0 e ID 1 8 | 0 f ID 1 9 | 0 g ID 1 10 | 0 h ID 1 11 | 0 i ID 1 12 | 0 j ID 1 13 | 0 k ID 1 14 | 0 l ID 1 15 | 0 m ID 1 16 | 0 n ID 1 17 | 0 o ID 1 18 | 0 p ID 1 19 | 0 q ID 1 20 | 0 r ID 1 21 | 0 s ID 1 22 | 0 t ID 1 23 | 0 u ID 1 24 | 0 v ID 1 25 | 0 w ID 1 26 | 0 x ID 1 27 | 0 y ID 1 28 | 0 z ID 1 29 | // uppercase letters 30 | 0 A ID 1 31 | 0 B ID 1 32 | 0 C ID 1 33 | 0 D ID 1 34 | 0 E ID 1 35 | 0 F ID 1 36 | 0 G ID 1 37 | 0 H ID 1 38 | 0 I ID 1 39 | 0 J ID 1 40 | 0 K ID 1 41 | 0 L ID 1 42 | 0 M ID 1 43 | 0 N ID 1 44 | 0 O ID 1 45 | 0 P ID 1 46 | 0 Q ID 1 47 | 0 R ID 1 48 | 0 S ID 1 49 | 0 T ID 1 50 | 0 U ID 1 51 | 0 V ID 1 52 | 0 W ID 1 53 | 0 X ID 1 54 | 0 Y ID 1 55 | 0 Z ID 1 56 | // standard numbers 57 | 0 0 INUM 3 58 | 0 1 INUM 2 59 | 0 2 INUM 2 60 | 0 3 INUM 2 61 | 0 4 INUM 2 62 | 0 5 INUM 2 63 | 0 6 INUM 2 64 | 0 7 INUM 2 65 | 0 8 INUM 2 66 | 0 9 INUM 2 67 | // miscellaneous control characters 68 | 0 ( LBRACKET -1 69 | 0 ) RBRACKET -1 70 | 0 [ LSQUARE -1 71 | 0 ] RSQUARE -1 72 | 0 { LCURLY -1 73 | 0 } RCURLY -1 74 | 0 = EQUALS 10 75 | 0 . PERIOD 114 76 | 0 , COMMA -1 77 | 0 \ SLASH 102 78 | 0 ; SEMICOLON -1 79 | 0 ? QUESTION 112 80 | 0 : COLON 113 81 | // quote characters 82 | 0 ' CQUOTE -1 83 | 0 " SQUOTE -1 84 | // import operator 85 | 0 @ AT -1 86 | // arithmetic characters 87 | 0 + PLUS 103 88 | 0 - MINUS 104 89 | 0 * TIMES -1 90 | 0 / DIVIDE 105 91 | 0 % MOD -1 92 | // comparison characters 93 | 0 < LT 108 94 | 0 > GT 110 95 | // logical characters 96 | 0 ! NOT 11 97 | 0 ~ COMPLEMENT -1 98 | 0 & AND 106 99 | 0 | OR 107 100 | 0 ^ XOR -1 101 | 102 | // state 1 (continuing id) 103 | // lowercase letters 104 | 1 a ID 1 105 | 1 b ID 1 106 | 1 c ID 1 107 | 1 d ID 1 108 | 1 e ID 1 109 | 1 f ID 1 110 | 1 g ID 1 111 | 1 h ID 1 112 | 1 i ID 1 113 | 1 j ID 1 114 | 1 k ID 1 115 | 1 l ID 1 116 | 1 m ID 1 117 | 1 n ID 1 118 | 1 o ID 1 119 | 1 p ID 1 120 | 1 q ID 1 121 | 1 r ID 1 122 | 1 s ID 1 123 | 1 t ID 1 124 | 1 u ID 1 125 | 1 v ID 1 126 | 1 w ID 1 127 | 1 x ID 1 128 | 1 y ID 1 129 | 1 z ID 1 130 | // uppercase letters 131 | 1 A ID 1 132 | 1 B ID 1 133 | 1 C ID 1 134 | 1 D ID 1 135 | 1 E ID 1 136 | 1 F ID 1 137 | 1 G ID 1 138 | 1 H ID 1 139 | 1 I ID 1 140 | 1 J ID 1 141 | 1 K ID 1 142 | 1 L ID 1 143 | 1 M ID 1 144 | 1 N ID 1 145 | 1 O ID 1 146 | 1 P ID 1 147 | 1 Q ID 1 148 | 1 R ID 1 149 | 1 S ID 1 150 | 1 T ID 1 151 | 1 U ID 1 152 | 1 V ID 1 153 | 1 W ID 1 154 | 1 X ID 1 155 | 1 Y ID 1 156 | 1 Z ID 1 157 | // standard numbers 158 | 1 0 ID 1 159 | 1 1 ID 1 160 | 1 2 ID 1 161 | 1 3 ID 1 162 | 1 4 ID 1 163 | 1 5 ID 1 164 | 1 6 ID 1 165 | 1 7 ID 1 166 | 1 8 ID 1 167 | 1 9 ID 1 168 | // miscellaneous name chars 169 | 1 _ ID 1 170 | 171 | // state 2 (regular integer) 172 | // standard numbers 173 | 2 0 INUM 2 174 | 2 1 INUM 2 175 | 2 2 INUM 2 176 | 2 3 INUM 2 177 | 2 4 INUM 2 178 | 2 5 INUM 2 179 | 2 6 INUM 2 180 | 2 7 INUM 2 181 | 2 8 INUM 2 182 | 2 9 INUM 2 183 | // numeric modifiers 184 | 2 . ERROR 4 185 | 2 e ERROR 6 186 | 187 | // state 3 (saw an initial 0) 188 | // double zero (fail) 189 | 3 0 FAIL -1 190 | // standard octal numbers, lacking zero 191 | 3 1 INUM 8 192 | 3 2 INUM 8 193 | 3 3 INUM 8 194 | 3 4 INUM 8 195 | 3 5 INUM 8 196 | 3 6 INUM 8 197 | 3 7 INUM 8 198 | // hexadecimal modifier 199 | 3 x ERROR 9 200 | // numeric modifiers 201 | 3 . ERROR 4 202 | 203 | // state 4 (saw a decimal in a number) 204 | // standard numbers 205 | 4 0 FNUM 5 206 | 4 1 FNUM 5 207 | 4 2 FNUM 5 208 | 4 3 FNUM 5 209 | 4 4 FNUM 5 210 | 4 5 FNUM 5 211 | 4 6 FNUM 5 212 | 4 7 FNUM 5 213 | 4 8 FNUM 5 214 | 4 9 FNUM 5 215 | 216 | // state 5 (saw number decimal number) 217 | 5 0 FNUM 5 218 | 5 1 FNUM 5 219 | 5 2 FNUM 5 220 | 5 3 FNUM 5 221 | 5 4 FNUM 5 222 | 5 5 FNUM 5 223 | 5 6 FNUM 5 224 | 5 7 FNUM 5 225 | 5 8 FNUM 5 226 | 5 9 FNUM 5 227 | // numeric modifiers 228 | 5 e ERROR 6 229 | 230 | // state 6 (saw an e in a number, possible + or - upcoming) 231 | // standard numbers 232 | 6 0 FNUM 7 233 | 6 1 FNUM 7 234 | 6 2 FNUM 7 235 | 6 3 FNUM 7 236 | 6 4 FNUM 7 237 | 6 5 FNUM 7 238 | 6 6 FNUM 7 239 | 6 7 FNUM 7 240 | 6 8 FNUM 7 241 | 6 9 FNUM 7 242 | // signage specifiers 243 | 6 + ERROR 7 244 | 6 - ERROR 7 245 | 246 | // state 7 (e in a number, no more + or - allowed) 247 | // standard numbers 248 | 7 0 FNUM 7 249 | 7 1 FNUM 7 250 | 7 2 FNUM 7 251 | 7 3 FNUM 7 252 | 7 4 FNUM 7 253 | 7 5 FNUM 7 254 | 7 6 FNUM 7 255 | 7 7 FNUM 7 256 | 7 8 FNUM 7 257 | 7 9 FNUM 7 258 | 259 | // state 8 (continuation of an octal number) 260 | // standard octal numbers 261 | 8 0 INUM 8 262 | 8 1 INUM 8 263 | 8 2 INUM 8 264 | 8 3 INUM 8 265 | 8 4 INUM 8 266 | 8 5 INUM 8 267 | 8 6 INUM 8 268 | 8 7 INUM 8 269 | 270 | // state 9 (continuation of a hex number) 271 | // standard numbers 272 | 9 0 INUM 9 273 | 9 1 INUM 9 274 | 9 2 INUM 9 275 | 9 3 INUM 9 276 | 9 4 INUM 9 277 | 9 5 INUM 9 278 | 9 6 INUM 9 279 | 9 7 INUM 9 280 | 9 8 INUM 9 281 | 9 9 INUM 9 282 | // standard lowercase hex digits 283 | 9 a INUM 9 284 | 9 b INUM 9 285 | 9 c INUM 9 286 | 9 d INUM 9 287 | 9 e INUM 9 288 | 9 f INUM 9 289 | // standard uppercase hex digits 290 | 9 A INUM 9 291 | 9 B INUM 9 292 | 9 C INUM 9 293 | 9 D INUM 9 294 | 9 E INUM 9 295 | 9 F INUM 9 296 | 297 | // state 10 (= seen) 298 | 10 = DEQUALS -1 299 | 300 | // state 11 (! seen) 301 | 11 = NEQUALS -1 302 | 303 | // state 102 (\ seen) 304 | 102 \ DSLASH -1 305 | 306 | // state 103 (+ seen) 307 | 103 + DPLUS -1 308 | 309 | // state 104 (- seen) 310 | 104 - DMINUS 111 311 | 104 > RARROW -1 312 | 313 | // state 105 (/ seen) 314 | 105 / REGCOMMENT -1 315 | 105 * STARCOMMENT -1 316 | 317 | // state 106 (& seen) 318 | 106 & DAND -1 319 | 320 | // state 107 (| seen) 321 | 107 | DOR -1 322 | 107 > RFLAG -1 323 | 324 | // state 108 (< seen) 325 | 108 < LS -1 326 | 108 = LE -1 327 | 108 | LFLAG -1 328 | 108 - LARROW 109 329 | 330 | // state 109 (<- seen) 331 | 109 > LRARROW -1 332 | 333 | // state 110 (> seen) 334 | 110 > RS -1 335 | 110 = GE -1 336 | 337 | // state 111 (-- seen) 338 | 111 > DRARROW -1 339 | 340 | // state 112 (? seen) 341 | 112 ? DQUESTION -1 342 | 343 | // state 113 (: seen) 344 | 113 : DCOLON -1 345 | 346 | // state 114 (. seen) 347 | 114 . DPERIOD -1 348 | -------------------------------------------------------------------------------- /src/outputOperators.cpp: -------------------------------------------------------------------------------- 1 | #include "outputOperators.h" 2 | 3 | // operator definitions 4 | 5 | ostream &operator<< (ostream &os, Token &t) { 6 | os << ((string)(t)); 7 | return os; 8 | } 9 | 10 | ostream &operator<< (ostream &os, Tree *&tree) { 11 | os << ((string)(*tree)); 12 | return os; 13 | } 14 | 15 | ostream &operator<< (ostream &os, SymbolTree *st) { 16 | os << ((string)(*st)); 17 | return os; 18 | } 19 | 20 | ostream &operator<< (ostream &os, Type *type) { 21 | os << ((string)(*type)); 22 | return os; 23 | } 24 | 25 | ostream &operator<< (ostream &os, const TypeStatus &status) { 26 | os << ((string)(*(status.type))); 27 | return os; 28 | } 29 | -------------------------------------------------------------------------------- /src/outputOperators.h: -------------------------------------------------------------------------------- 1 | #ifndef _OUTPUT_OPERATORS_H_ 2 | #define _OUTPUT_OPERATORS_H_ 3 | 4 | #include "globalDefs.h" 5 | #include "constantDefs.h" 6 | 7 | #include "lexer.h" 8 | #include "parser.h" 9 | #include "semmer.h" 10 | 11 | // string vector streaming operator overloads 12 | ostream &operator<< (ostream &os, Token &t); 13 | ostream &operator<< (ostream &os, Tree *&tree); 14 | ostream &operator<< (ostream &os, SymbolTree *st); 15 | ostream &operator<< (ostream &os, Type *type); 16 | ostream &operator<< (ostream &os, const TypeStatus &status); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/parser.cpp: -------------------------------------------------------------------------------- 1 | #include "parser.h" 2 | 3 | #include "outputOperators.h" 4 | 5 | // parser-global variables 6 | 7 | int parserErrorCode; 8 | 9 | // Tree functions 10 | 11 | // constructors 12 | Tree::Tree(const Token &t) : t(t), next(NULL), back(NULL), child(NULL), parent(NULL), status(TypeStatus()) {} 13 | Tree::Tree(const Token &t, Tree *next, Tree *back, Tree *child, Tree *parent) : t(t), next(next), back(back), child(child), parent(parent), status(TypeStatus()) {} 14 | Tree::Tree(const TypeStatus &status) : next(NULL), back(NULL), child(NULL), parent(NULL), status(status) {} 15 | Tree::Tree(deque *depthList) : t(TOKEN_RAW_VECTOR), next((Tree *)depthList) {} 16 | 17 | // destructor 18 | Tree::~Tree() { 19 | delete next; 20 | delete child; 21 | } 22 | 23 | // core methods 24 | IRTree *Tree::code() const { 25 | return (status.code); 26 | } 27 | Type &Tree::typeRef() const { 28 | return (*(status.type)); 29 | } 30 | DataTree *Tree::castCode(const Type &destType) const { 31 | return (status.castCode(destType)); 32 | } 33 | DataTree *Tree::castCommonCode(const Type &otherType) const { 34 | return (status.castCommonCode(otherType)); 35 | } 36 | 37 | // comparison oparators 38 | bool Tree::operator==(int tokenType) const { 39 | return (t.tokenType == tokenType); 40 | } 41 | bool Tree::operator!=(int tokenType) const { 42 | return (t.tokenType != tokenType); 43 | } 44 | 45 | // traversal operators 46 | // binary traversers 47 | Tree *Tree::goNext(unsigned int n) const { 48 | const Tree *cur = this; 49 | for (unsigned int i=0; inext; 52 | } else { 53 | return NULL; 54 | } 55 | } 56 | return (Tree *)cur; 57 | } 58 | Tree *Tree::goBack(unsigned int n) const { 59 | const Tree *cur = this; 60 | for (unsigned int i=0; iback; 63 | } else { 64 | return NULL; 65 | } 66 | } 67 | return (Tree *)cur; 68 | } 69 | Tree *Tree::goChild(unsigned int n) const { 70 | const Tree *cur = this; 71 | for (unsigned int i=0; ichild; 74 | } else { 75 | return NULL; 76 | } 77 | } 78 | return (Tree *)cur; 79 | } 80 | Tree *Tree::goParent(unsigned int n) const { 81 | const Tree *cur = this; 82 | for (unsigned int i=0; iparent; 85 | } else { 86 | return NULL; 87 | } 88 | } 89 | return (Tree *)cur; 90 | } 91 | Tree *Tree::bottom() const { 92 | const Tree *cur = this; 93 | while (cur->child != NULL) { 94 | cur = cur->child; 95 | } 96 | return (Tree *)cur; 97 | } 98 | 99 | // binary attatchers 100 | void Tree::operator+=(Tree *next) { 101 | this->next = next; 102 | } 103 | void Tree::operator-=(Tree *back) { 104 | this->back = back; 105 | } 106 | void Tree::operator*=(Tree *child) { 107 | this->child = child; 108 | } 109 | void Tree::operator&=(Tree *parent) { 110 | this->parent = parent; 111 | } 112 | 113 | // converters 114 | Tree::operator string() const { 115 | if (*this == TOKEN_NonArrayedIdentifier || *this == TOKEN_ArrayedIdentifier || *this == TOKEN_OpenIdentifier) { // if this is an identifier-style Tree node, decode it 116 | string retVal(child->t.s); // ID or DPERIOD 117 | // invariant: cur is a non-NULL child of NonArrayedIdentifierSuffix, ArrayedIdentifierSuffix, or IdentifierSuffix 118 | for(const Tree *cur = child->next->child; cur != NULL; cur = (cur->next->next != NULL) ? cur->next->next->child : NULL) { 119 | // log the extension 120 | const Tree *curn = cur->next; // ID, ArrayAccess, or TIMES 121 | if (*curn == TOKEN_ID) { 122 | retVal += '.'; 123 | retVal += curn->t.s; 124 | } else if (*curn == TOKEN_ArrayAccess) { 125 | // check to make sure that the expressions are compatible with STD_INT 126 | if (curn->child->next->next->next == NULL) { // if there's only one subscript 127 | TypeStatus expStatus = getStatusExp(curn->child->next); 128 | if (!(*expStatus >> *stdIntType)) { // if the types are incompatible, flag an error 129 | Token curToken = curn->child->next->t; // Exp 130 | semmerError(curToken.fileIndex,curToken.row,curToken.col,"array subscript is invalid"); 131 | semmerError(curToken.fileIndex,curToken.row,curToken.col,"-- (subscript type is "<child->next); 136 | if (!(*leftExpStatus >> *stdIntType)) { // if the types are incompatible, flag an error 137 | Token curToken = curn->child->next->t; // Exp 138 | semmerError(curToken.fileIndex,curToken.row,curToken.col,"left extent subscript is invalid"); 139 | semmerError(curToken.fileIndex,curToken.row,curToken.col,"-- (subscript type is "<child->next); 142 | if (!(*rightExpStatus >> *stdIntType)) { // if the types are incompatible, flag an error 143 | Token curToken = curn->child->next->next->next->t; // Exp 144 | semmerError(curToken.fileIndex,curToken.row,curToken.col,"right extent subscript is invalid"); 145 | semmerError(curToken.fileIndex,curToken.row,curToken.col,"-- (subscript type is "<back : NULL, treeCur, (treeCur != NULL) ? treeCur->parent : NULL); 171 | // relatch on the left 172 | if (treeCur != NULL && treeCur->back != NULL) { 173 | *(treeCur->back) += treeToAdd; 174 | *treeCur -= NULL; 175 | } 176 | // link down from parent above 177 | if (treeCur != NULL && treeCur->parent != NULL) { 178 | *(treeCur->parent) *= treeToAdd; 179 | } 180 | // link up from the current node below 181 | if (treeCur != NULL) { 182 | *treeCur &= treeToAdd; 183 | } 184 | // set the newly promoted node as the current one 185 | treeCur = treeToAdd; 186 | } 187 | 188 | // treeCur is guaranteed not to be NULL in this case 189 | void shiftPromoteNullToken(Tree *&treeCur, Token &t) { 190 | Tree *treeToAdd = new Tree(t, NULL, treeCur, NULL, NULL); 191 | // link in the newly allocated node 192 | *treeCur += treeToAdd; 193 | // set treeCur to the newly allocated node 194 | treeCur = treeToAdd; 195 | } 196 | 197 | int parse(vector *lexeme, Tree *&parseme, unsigned int fileIndex) { 198 | 199 | // initialize local error code 200 | parserErrorCode = 0; 201 | 202 | // initialize parser structures 203 | #include "../tmp/ruleRhsLengthRaw.h" 204 | #include "../tmp/ruleLhsTokenTypeRaw.h" 205 | #include "../tmp/ruleLhsTokenStringRaw.h" 206 | #include "../tmp/parserNodeRaw.h" 207 | 208 | // iterate through the lexemes and do the actual parsing 209 | // initialize the current bit of tree that we're examining 210 | Tree *treeCur = NULL; 211 | // initialize the state stack and push the initial state onto it 212 | stack stateStack; 213 | stateStack.push(0); 214 | 215 | for(vector::iterator lexemeIter = lexeme->begin(); lexemeIter != lexeme->end(); lexemeIter++) { 216 | 217 | transitionParserState: ; 218 | 219 | // get the current state off the top of the stack 220 | unsigned int curState = stateStack.top(); 221 | // peek at the next token of input 222 | Token &t = *lexemeIter; 223 | // get the transition node for the current state 224 | ParserNode transition = parserNode[curState][t.tokenType]; 225 | 226 | // branch based on the type of action dictated by the transition 227 | if (transition.action == ACTION_SHIFT) { 228 | shiftToken(treeCur, t); 229 | stateStack.push(transition.n); 230 | 231 | VERBOSE( cout << "\t" << 232 | COLOREXP(SET_TERM(BRIGHT_CODE AND MAGENTA_CODE)) << "SHIFT" << COLOREXP(SET_TERM(RESET_CODE)) << 233 | "\t" << curState << "\t->\t" << transition.n << "\t[" << 234 | COLOREXP(SET_TERM(BRIGHT_CODE AND CYAN_CODE)) << tokenType2String(t.tokenType) << COLOREXP(SET_TERM(RESET_CODE)) << 235 | "]\n"; ) 236 | 237 | } else if (transition.action == ACTION_REDUCE) { 238 | unsigned int numRhs = ruleRhsLength[transition.n]; 239 | int tokenType = ruleLhsTokenType[transition.n]; 240 | if (numRhs > 1) { 241 | treeCur = treeCur->goBack(numRhs-1); 242 | } 243 | for (unsigned int i=0; it.row : 0; 251 | t.col = treeCur != NULL ? treeCur->t.col : 0; 252 | // promote the current token, as appropriate 253 | if (numRhs != 0 || treeCur == NULL) { // if it's not the NULL-shifting promotion case 254 | promoteToken(treeCur, t); 255 | } else { // else if it is the NULL-shifting promotion case 256 | shiftPromoteNullToken(treeCur, t); // note: the above case handles treeCur == NULL 257 | } 258 | // take the goto branch of the new transition 259 | int tempState = stateStack.top(); 260 | stateStack.push(parserNode[tempState][tokenType].n); 261 | 262 | VERBOSE( 263 | const char *tokenString = ruleLhsTokenString[transition.n]; 264 | cout << "\t" << 265 | COLOREXP(SET_TERM(BRIGHT_CODE AND GREEN_CODE)) << "REDUCE" << COLOREXP(SET_TERM(RESET_CODE)) << 266 | "\t" << curState << "\t->\t" << stateStack.top() << "\t<" << 267 | COLOREXP(SET_TERM(BRIGHT_CODE AND CYAN_CODE)) << tokenString << COLOREXP(SET_TERM(RESET_CODE)) << 268 | ">\n"; 269 | ) 270 | 271 | goto transitionParserState; 272 | } else if (transition.action == ACTION_ACCEPT) { 273 | 274 | VERBOSE( cout << "\t" << 275 | COLOREXP(SET_TERM(BRIGHT_CODE AND WHITE_CODE)) << "ACCEPT" << COLOREXP(SET_TERM(RESET_CODE)) << 276 | "\n"; ) 277 | 278 | break; 279 | } else if (transition.action == ACTION_ERROR) { 280 | string errorString = "syntax error at "; 281 | if (t.tokenType == TOKEN_CQUOTE || t.tokenType == TOKEN_SQUOTE) { 282 | errorString += "quoted literal"; 283 | } else { 284 | errorString += "\'" + t.s + "\'"; 285 | } 286 | parserError(fileIndex, t.row, t.col, errorString); 287 | break; 288 | } 289 | } 290 | 291 | if (parserErrorCode) { // if there was an error, clean up 292 | // deallocate the unfinished tree, since there was an error anyway 293 | delete treeCur; 294 | } else { // else if there were no errors, log the root parseme into the return slot 295 | parseme = treeCur; 296 | } 297 | // return to the caller 298 | return parserErrorCode; 299 | } 300 | -------------------------------------------------------------------------------- /src/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef _PARSER_H_ 2 | #define _PARSER_H_ 3 | 4 | #include "globalDefs.h" 5 | #include "constantDefs.h" 6 | #include "driver.h" 7 | 8 | #include "lexer.h" 9 | #include "../tmp/parserStruct.h" 10 | #include "types.h" 11 | 12 | // forward declarations 13 | class SymbolTree; 14 | class Type; 15 | class TypeStatus; 16 | class IRTree; 17 | class DataTree; 18 | 19 | class Tree { 20 | public: 21 | // data members 22 | Token t; 23 | Tree *next; 24 | Tree *back; 25 | Tree *child; 26 | Tree *parent; 27 | SymbolTree *env; // the symbol environment in which this node occurs 28 | TypeStatus status; // the status coming OUT of this node 29 | // allocators/deallocators 30 | Tree(const Token &t); 31 | Tree(const Token &t, Tree *next, Tree *back, Tree *child, Tree *parent); 32 | Tree(const TypeStatus &status); 33 | Tree(deque *depthList); 34 | ~Tree(); 35 | // core methods 36 | IRTree *code() const; 37 | Type &typeRef() const; 38 | DataTree *castCode(const Type &destType) const; 39 | DataTree *castCommonCode(const Type &otherType) const; 40 | // comparison operators 41 | bool operator==(int tokenType) const; 42 | bool operator!=(int tokenType) const; 43 | // traversal operators 44 | Tree *goNext(unsigned int n) const; 45 | Tree *goBack(unsigned int n) const; 46 | Tree *goChild(unsigned int n) const; 47 | Tree *goParent(unsigned int n) const; 48 | Tree *bottom() const; 49 | // binary attatchers 50 | void operator+=(Tree *next); 51 | void operator-=(Tree *back); 52 | void operator*=(Tree *child); 53 | void operator&=(Tree *parent); 54 | // converters 55 | operator string() const; // only for SuffixedIdentifier or NonArraySuffixedIdentifier kinds 56 | }; 57 | 58 | int parse(vector *lexeme, Tree *&parseme, unsigned int fileIndex); 59 | 60 | // post-includes 61 | #include "semmer.h" 62 | #include "genner.h" 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/parserGrammar.y: -------------------------------------------------------------------------------- 1 | /* core tokens */ 2 | %token ID 3 | %token INUM 4 | %token FNUM 5 | %token PERIOD 6 | %token DPERIOD 7 | %token LBRACKET 8 | %token RBRACKET 9 | %token COMMA 10 | %token EQUALS 11 | %token SEMICOLON 12 | %token QUESTION 13 | %token DQUESTION 14 | %token COLON 15 | %token DCOLON 16 | %token LCURLY 17 | %token RCURLY 18 | %token LSQUARE 19 | %token RSQUARE 20 | %token RFLAG 21 | %token LFLAG 22 | %token RARROW 23 | %token LARROW 24 | %token DRARROW 25 | %token LRARROW 26 | %token SLASH 27 | %token DSLASH 28 | %token CQUOTE 29 | %token SQUOTE 30 | %token AT 31 | 32 | /* arithmetic tokens */ 33 | %token DOR 34 | %token DAND 35 | %token OR 36 | %token XOR 37 | %token AND 38 | %token DEQUALS 39 | %token NEQUALS 40 | %token LT 41 | %token GT 42 | %token LE 43 | %token GE 44 | %token LS 45 | %token RS 46 | %token PLUS 47 | %token DPLUS 48 | %token MINUS 49 | %token DMINUS 50 | %token TIMES 51 | %token DIVIDE 52 | %token MOD 53 | %token NOT 54 | %token COMPLEMENT 55 | 56 | /* arithmetic precedence rules */ 57 | %left DOR 58 | %left DAND 59 | %left OR 60 | %left XOR 61 | %left AND 62 | %left DEQUALS NEQUALS 63 | %left LT GT LE GE 64 | %left LS RS 65 | %left PLUS MINUS 66 | %left TIMES DIVIDE MOD 67 | %left NOT COMPLEMENT 68 | %left RSQUARE 69 | %left LSQUARE 70 | %left LBRACKET RBRACKET LCURLY RCURLY 71 | 72 | %% 73 | Program : Pipes 74 | ; 75 | Pipes : 76 | | LastPipe 77 | | Pipe 78 | | Pipe NonEmptyPipes 79 | ; 80 | NonEmptyPipes : LastPipe 81 | | Pipe 82 | | Pipe NonEmptyPipes 83 | ; 84 | Pipe : Declaration 85 | | NonEmptyTerms SEMICOLON 86 | ; 87 | LastPipe : NonEmptyTerms 88 | ; 89 | Declaration : ID EQUALS TypedStaticTerm 90 | | ID EQUALS TypedStaticTerm SEMICOLON 91 | | ID EQUALS BlankInstantiation 92 | | ID EQUALS BlankInstantiation SEMICOLON 93 | | AT ImportIdentifier 94 | | AT ImportIdentifier SEMICOLON 95 | | AT LSQUARE ImportIdentifier RSQUARE 96 | | AT LSQUARE ImportIdentifier RSQUARE SEMICOLON 97 | ; 98 | ImportIdentifier : NonArrayedIdentifier 99 | | ArrayedIdentifier 100 | | OpenIdentifier 101 | ; 102 | NonEmptyTerms : Term Terms 103 | ; 104 | Terms : 105 | | Term Terms 106 | ; 107 | Term : ClosedTerm 108 | | OpenTerm 109 | | DynamicTerm 110 | ; 111 | ClosedTerm : SimpleTerm 112 | | ClosedCondTerm 113 | ; 114 | OpenTerm : SimpleCondTerm 115 | | OpenCondTerm 116 | ; 117 | SimpleCondTerm : QUESTION Term 118 | ; 119 | ClosedCondTerm : QUESTION ClosedTerm COLON ClosedTerm 120 | ; 121 | OpenCondTerm : QUESTION ClosedTerm COLON OpenTerm 122 | ; 123 | SimpleTerm : StaticTerm 124 | | SwitchTerm 125 | ; 126 | StaticTerm : TypedStaticTerm 127 | | SingleAccess 128 | | MultiAccess 129 | ; 130 | SingleStaticTerm : TypedStaticTerm 131 | | SingleAccess 132 | ; 133 | SwitchTerm : DQUESTION LCURLY LabeledTerms RCURLY 134 | ; 135 | LabeledTerms : LastLabeledTerm 136 | | LabeledTerm LabeledTerms 137 | ; 138 | LabeledTerm: TypedStaticTerm COLON SimpleTerm 139 | | TypedStaticTerm COLON SimpleTerm SEMICOLON 140 | ; 141 | LastLabeledTerm : COLON SimpleTerm 142 | | COLON SimpleTerm SEMICOLON 143 | ; 144 | DynamicTerm : Compound 145 | | Pack 146 | | Unpack 147 | | Link 148 | | Loopback 149 | | Send 150 | | Swap 151 | | Return 152 | ; 153 | TypedStaticTerm : Node 154 | | BracketedExp 155 | ; 156 | BracketedExp : LBRACKET RBRACKET 157 | | LBRACKET ExpList RBRACKET 158 | ; 159 | CurlyBracketedExpList : CurlyBracketedExp 160 | | CurlyBracketedExp COMMA CurlyBracketedExpList 161 | ; 162 | CurlyBracketedExp : LCURLY ExpList RCURLY 163 | | LCURLY CurlyBracketedExpList RCURLY 164 | ; 165 | ExpList : Exp 166 | | Exp COMMA ExpList 167 | ; 168 | Exp : Primary 169 | | Exp DOR Exp 170 | | Exp DAND Exp 171 | | Exp OR Exp 172 | | Exp XOR Exp 173 | | Exp AND Exp 174 | | Exp DEQUALS Exp 175 | | Exp NEQUALS Exp 176 | | Exp LT Exp 177 | | Exp GT Exp 178 | | Exp LE Exp 179 | | Exp GE Exp 180 | | Exp LS Exp 181 | | Exp RS Exp 182 | | Exp TIMES Exp 183 | | Exp DIVIDE Exp 184 | | Exp MOD Exp 185 | | Exp PLUS Exp 186 | | Exp MINUS Exp 187 | ; 188 | Primary : PrimaryBase 189 | | PrefixOrMultiOp Primary 190 | ; 191 | PrimaryBase : NonArrayedIdentifier 192 | | ArrayedIdentifier 193 | | SingleAccessor NonArrayedIdentifier 194 | | SingleAccessor ArrayedIdentifier 195 | | Instantiation 196 | | ExplicitFilter 197 | | Object 198 | | PrimLiteral 199 | | BracketedExp 200 | | PrimaryBase PostfixOp 201 | ; 202 | Node : NonArrayedIdentifier 203 | | ArrayedIdentifier 204 | | Instantiation 205 | | Filter 206 | | Object 207 | | PrimOpNode 208 | | PrimLiteral 209 | ; 210 | NonArrayedIdentifier : ID NonArrayedIdentifierSuffix 211 | | DPERIOD NonArrayedIdentifierSuffix 212 | ; 213 | ArrayedIdentifier : ID ArrayedIdentifierSuffix 214 | | DPERIOD ArrayedIdentifierSuffix 215 | ; 216 | OpenIdentifier : ID OpenIdentifierSuffix 217 | | DPERIOD OpenIdentifierSuffix 218 | ; 219 | NonArrayedIdentifierSuffix : 220 | | PERIOD ID NonArrayedIdentifierSuffix 221 | ; 222 | ArrayedIdentifierSuffix : PERIOD ID ArrayedIdentifierSuffix 223 | | PERIOD ArrayAccess IdentifierSuffix 224 | ; 225 | OpenIdentifierSuffix : PERIOD TIMES 226 | | PERIOD ID OpenIdentifierSuffix 227 | ; 228 | IdentifierSuffix : 229 | | PERIOD ID IdentifierSuffix 230 | | PERIOD ArrayAccess IdentifierSuffix 231 | ; 232 | BlankInstantiation : LSQUARE BlankInstantiationSource RSQUARE 233 | ; 234 | Instantiation : LSQUARE SingleInitInstantiationSource RSQUARE 235 | | LSQUARE SingleInitInstantiationSource RSQUARE BracketedExp 236 | | LSQUARE SingleInitInstantiationSource RSQUARE CurlyBracketedExp 237 | | LSQUARE MultiInitInstantiationSource RSQUARE 238 | | LSQUARE MultiInitInstantiationSource RSQUARE BracketedExp 239 | | LSQUARE SingleFlowInitInstantiationSource RSQUARE 240 | | LSQUARE MultiFlowInitInstantiationSource RSQUARE 241 | | LSQUARE CopyInstantiationSource RSQUARE 242 | | LSQUARE CloneInstantiationSource RSQUARE 243 | ; 244 | BlankInstantiationSource : NonArrayedIdentifier BlankInstantiationTypeSuffix 245 | ; 246 | SingleInitInstantiationSource : NonArrayedIdentifier 247 | ; 248 | MultiInitInstantiationSource : NonArrayedIdentifier MultiInitInstantiationTypeSuffix 249 | ; 250 | SingleFlowInitInstantiationSource : RARROW SingleInitInstantiationSource 251 | ; 252 | MultiFlowInitInstantiationSource : RARROW MultiInitInstantiationSource 253 | ; 254 | CopyInstantiationSource : SingleAccessor NonArrayedIdentifier 255 | | SingleAccessor ArrayedIdentifier 256 | ; 257 | CloneInstantiationSource : RARROW SingleAccessor 258 | ; 259 | ArrayAccess : LSQUARE Exp RSQUARE 260 | | LSQUARE Exp COLON Exp RSQUARE 261 | ; 262 | PrimOpNode : PrefixOp 263 | | InfixOp 264 | | MultiOp 265 | | PostfixOp 266 | ; 267 | PrefixOp : NOT 268 | | COMPLEMENT 269 | ; 270 | InfixOp : DOR 271 | | DAND 272 | | OR 273 | | XOR 274 | | AND 275 | | DEQUALS 276 | | NEQUALS 277 | | LT 278 | | GT 279 | | LE 280 | | GE 281 | | LS 282 | | RS 283 | | TIMES 284 | | DIVIDE 285 | | MOD 286 | ; 287 | MultiOp : PLUS 288 | | MINUS 289 | ; 290 | PostfixOp : DPLUS 291 | | DMINUS 292 | ; 293 | PrefixOrMultiOp : PrefixOp 294 | | MultiOp 295 | ; 296 | InfixOrMultiOp : InfixOp 297 | | MultiOp 298 | ; 299 | PrimLiteral : INUM 300 | | FNUM 301 | | CQUOTE 302 | | SQUOTE 303 | ; 304 | Filter : Block 305 | | FilterHeader Block 306 | ; 307 | ExplicitFilter : FilterHeader Block 308 | ; 309 | FilterHeader : LSQUARE ParamList RSQUARE 310 | | LSQUARE ParamList RetList RSQUARE 311 | | LSQUARE RetList RSQUARE 312 | ; 313 | NonRetFilterHeader : LSQUARE ParamList RSQUARE 314 | ; 315 | RetFilterHeader : LSQUARE RetList RSQUARE 316 | ; 317 | ParamList : Param 318 | | Param COMMA ParamList 319 | ; 320 | RetList : DRARROW TypeList 321 | | DRARROW QUESTION 322 | ; 323 | ExplicitRetList : DRARROW TypeList 324 | ; 325 | Param : Type ID 326 | | QUESTION ID 327 | ; 328 | Type : NonArrayedIdentifier 329 | | FilterType 330 | | ObjectType 331 | | NonArrayedIdentifier TypeSuffix 332 | | FilterType TypeSuffix 333 | | ObjectType TypeSuffix 334 | ; 335 | TypeSuffix : SLASH 336 | | ListTypeSuffix 337 | | StreamTypeSuffix 338 | | ArrayTypeSuffix 339 | | PoolTypeSuffix 340 | ; 341 | BlankInstantiationTypeSuffix : SLASH 342 | | StreamTypeSuffix 343 | | PoolTypeSuffix 344 | ; 345 | MultiInitInstantiationTypeSuffix : ArrayTypeSuffix 346 | ; 347 | ListTypeSuffix : LSQUARE RSQUARE 348 | | LSQUARE RSQUARE ListTypeSuffix 349 | ; 350 | StreamTypeSuffix : DSLASH 351 | | DSLASH StreamTypeSuffix 352 | ; 353 | ArrayTypeSuffix : LSQUARE Exp RSQUARE 354 | | LSQUARE Exp RSQUARE ArrayTypeSuffix 355 | ; 356 | PoolTypeSuffix : SLASH LSQUARE Exp RSQUARE 357 | | SLASH LSQUARE Exp RSQUARE ArrayTypeSuffix 358 | ; 359 | FilterType : LSQUARE TypeList RSQUARE 360 | | LSQUARE TypeList ExplicitRetList RSQUARE 361 | | LSQUARE ExplicitRetList RSQUARE 362 | ; 363 | ObjectType : LCURLY RCURLY 364 | | LCURLY ObjectTypeList RCURLY 365 | ; 366 | ObjectTypeList : InstructorType 367 | | InstructorType COMMA ObjectTypeList 368 | | OutstructorType 369 | | OutstructorType COMMA ObjectTypeList 370 | | MemberType 371 | | MemberType COMMA ObjectTypeList 372 | ; 373 | InstructorType : EQUALS 374 | | EQUALS LSQUARE TypeList RSQUARE 375 | ; 376 | OutstructorType : EQUALS LSQUARE DRARROW TypeList RSQUARE 377 | ; 378 | MemberType : ID EQUALS Type 379 | ; 380 | TypeList : Type 381 | | Type COMMA TypeList 382 | ; 383 | Block : LCURLY Pipes RCURLY 384 | ; 385 | Object : LSQUARE RSQUARE LCURLY ObjectPipes RCURLY 386 | ; 387 | ObjectPipes : LastInstructor 388 | | Instructor 389 | | Instructor ObjectPipes 390 | | Outstructor 391 | | Outstructor ObjectPipes 392 | | LastPipe 393 | | Pipe 394 | | Pipe ObjectPipes 395 | ; 396 | Instructor : EQUALS SEMICOLON 397 | | EQUALS Block SEMICOLON 398 | | EQUALS NonRetFilterHeader Block 399 | | EQUALS NonRetFilterHeader Block SEMICOLON 400 | ; 401 | LastInstructor : EQUALS 402 | | EQUALS Block 403 | ; 404 | Outstructor : EQUALS RetFilterHeader Block 405 | | EQUALS RetFilterHeader Block SEMICOLON 406 | ; 407 | SingleAccess : SingleAccessor Node 408 | ; 409 | MultiAccess : MultiAccessor Node 410 | ; 411 | SingleAccessor : SLASH 412 | ; 413 | MultiAccessor : DSLASH 414 | | LSQUARE RSQUARE 415 | ; 416 | Compound : COMMA SingleStaticTerm 417 | ; 418 | Pack : RFLAG 419 | ; 420 | Unpack : LFLAG 421 | ; 422 | Link : DCOLON StaticTerm 423 | ; 424 | Loopback : LARROW 425 | ; 426 | Send : RARROW Node 427 | ; 428 | Swap : LRARROW Node 429 | ; 430 | Return : DRARROW 431 | ; 432 | %% 433 | -------------------------------------------------------------------------------- /src/parserNodeStruct.h: -------------------------------------------------------------------------------- 1 | #ifndef PARSER_STRUCT_NODE_H 2 | #define PARSER_STRUCT_NODE_H 3 | 4 | // action definitions 5 | #define ACTION_SHIFT 1 6 | #define ACTION_REDUCE 2 7 | #define ACTION_ACCEPT 3 8 | #define ACTION_GOTO 4 9 | #define ACTION_ERROR 5 10 | 11 | struct parserNodeStruct { 12 | int action; // the action to take in this situation (ACTION_ defines above) 13 | unsigned int n; // either the state to go to (SHIFT/GOTO) or the rule to reduce by (REDUCE) 14 | }; 15 | typedef struct parserNodeStruct ParserNode; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/semmer.h: -------------------------------------------------------------------------------- 1 | #ifndef _SEMMER_H_ 2 | #define _SEMMER_H_ 3 | 4 | #include "globalDefs.h" 5 | #include "constantDefs.h" 6 | #include "driver.h" 7 | 8 | #include "lexer.h" 9 | #include "parser.h" 10 | #include "types.h" 11 | #include "genner.h" 12 | 13 | // SymbolTree node kinds 14 | #define KIND_STD 1 15 | #define KIND_CLOSED_IMPORT 2 16 | #define KIND_OPEN_IMPORT 3 17 | #define KIND_BLOCK 4 18 | #define KIND_DECLARATION 5 19 | #define KIND_PARAMETER 6 20 | #define KIND_INSTRUCTOR 7 21 | #define KIND_OUTSTRUCTOR 8 22 | #define KIND_FILTER 9 23 | #define KIND_OBJECT 10 24 | #define KIND_INSTANTIATION 11 25 | #define KIND_FAKE 12 26 | 27 | class SymbolTree { 28 | public: 29 | // data members 30 | int kind; // node kind 31 | string id; // string representation of this node used for binding 32 | Tree *defSite; // where the symbol is defined in the Tree (Declaration or Param) 33 | SymbolTree *copyImportSite; // if this node is a copy-import, the node from which we're importing; NULL otherwise 34 | SymbolTree *parent; // pointer ot the parent of this node; populated during SymbolTree status derivation 35 | map children; // list of this node's children 36 | int offsetKindInternal; // the kind of child this node apprears as to its lexical parent 37 | unsigned int offsetIndexInternal; // the offset of this child in the lexical parent's offset kind 38 | unsigned int numRaws; // the number of raw-represented children for this node 39 | unsigned int numBlocks; // the number of block-represented children for this node 40 | unsigned int numPartitions; // the number of partition-represented children for this node 41 | unsigned int numShares; // the number of share-represented children for this node 42 | // allocators/deallocators 43 | SymbolTree(int kind, const string &id, Tree *defSite = NULL, SymbolTree *copyImportSite = NULL); 44 | SymbolTree(int kind, const char *id, Tree *defSite = NULL, SymbolTree *copyImportSite = NULL); 45 | SymbolTree(int kind, const string &id, Type *defType, SymbolTree *copyImportSite = NULL); 46 | SymbolTree(int kind, const char *id, Type *defType, SymbolTree *copyImportSite = NULL); 47 | SymbolTree(const SymbolTree &st, SymbolTree *parent, SymbolTree *copyImportSite = NULL); 48 | ~SymbolTree(); 49 | // core methods 50 | unsigned int addRaw(); 51 | unsigned int addBlock(); 52 | unsigned int addPartition(); 53 | unsigned int addShare(); 54 | void getOffset(); 55 | int offsetKind(); 56 | Tree *offsetExp() const; 57 | unsigned int offsetIndex(); 58 | string toString(unsigned int tabDepth); 59 | // operators 60 | SymbolTree &operator=(const SymbolTree &st); 61 | SymbolTree &operator*=(SymbolTree *st); 62 | operator string(); 63 | }; 64 | 65 | // forward declarations of mutually recursive typing functions 66 | 67 | TypeStatus getStatusSymbolTree(SymbolTree *root, SymbolTree *parent, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 68 | TypeStatus getStatusIdentifier(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 69 | TypeStatus getStatusPrimaryBase(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 70 | TypeStatus getStatusPrimary(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 71 | TypeStatus getStatusBracketedExp(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 72 | TypeStatus getStatusExp(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 73 | TypeStatus getStatusPrimOpNode(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 74 | TypeStatus getStatusPrimLiteral(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 75 | TypeStatus getStatusBlock(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 76 | TypeStatus getStatusFilterHeader(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 77 | TypeStatus verifyStatusFilter(Tree *tree); 78 | TypeStatus getStatusFilter(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 79 | TypeStatus getStatusInstructor(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 80 | TypeStatus verifyStatusInstructor(Tree *tree); 81 | TypeStatus getStatusOutstructor(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 82 | TypeStatus verifyStatusOutstructor(Tree *tree); 83 | TypeStatus getStatusObject(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 84 | TypeStatus verifyStatusObject(Tree *tree); 85 | TypeStatus getStatusType(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 86 | TypeStatus getStatusTypeList(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 87 | TypeStatus getStatusParamList(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 88 | TypeStatus getStatusInstantiationSource(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 89 | TypeStatus getStatusInstantiation(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 90 | TypeStatus getStatusNode(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 91 | TypeStatus getStatusTypedStaticTerm(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 92 | TypeStatus getStatusAccess(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 93 | TypeStatus getStatusStaticTerm(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 94 | TypeStatus getStatusDynamicTerm(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 95 | TypeStatus getStatusSwitchTerm(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 96 | TypeStatus getStatusSimpleTerm(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 97 | TypeStatus getStatusSimpleCondTerm(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 98 | TypeStatus getStatusOpenOrClosedCondTerm(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 99 | TypeStatus getStatusTerm(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 100 | TypeStatus getStatusNonEmptyTerms(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 101 | TypeStatus getStatusDeclaration(Tree *tree); 102 | TypeStatus getStatusPipe(Tree *tree, const TypeStatus &inStatus = TypeStatus(nullType, errType)); 103 | 104 | // semantic analysis helper blocks 105 | 106 | #define GET_STATUS_HEADER \ 107 | /* if the type is memoized, short-circuit evaluate */\ 108 | if (tree->status.type != NULL) {\ 109 | return (tree->status);\ 110 | }\ 111 | /* otherwise, compute the type normally */ 112 | 113 | #define GET_STATUS_SYMBOL_TREE_HEADER \ 114 | /* if the type is memoized, skip over type derivation */\ 115 | Tree *tree = root->defSite;\ 116 | if (tree->status.type != NULL) {\ 117 | goto endTypeDerivation;\ 118 | }\ 119 | /* otherwise, compute the type normally */ 120 | 121 | #define returnType(x) \ 122 | /* memoize the return value and jump to the intermediate code generation point */\ 123 | tree->status = TypeStatus((x), inStatus.retType);\ 124 | goto endTypeDerivation 125 | 126 | #define returnTypeRet(x,y) \ 127 | /* memoize the return value and jump to the intermediate code generation point */\ 128 | tree->status = TypeStatus((x),(y));\ 129 | goto endTypeDerivation 130 | 131 | #define returnStatus(x) \ 132 | /* memoize the return value and jump to the intermediate code generation point */\ 133 | tree->status = (x);\ 134 | goto endTypeDerivation 135 | 136 | #define GET_STATUS_CODE \ 137 | /* if we failed to do a returnType, returnTypeRet, or returnStatus, memoize the error type and return from this function */\ 138 | tree->status = TypeStatus(errType, NULL);\ 139 | return (tree->status);\ 140 | /* label the exit point of type derivation (i.e. the entry point for code generation) */\ 141 | endTypeDerivation:\ 142 | /* if we derived a valid return status, proceed to build the intermediate code tree */\ 143 | if (tree->status.type->category != CATEGORY_ERRORTYPE) { 144 | 145 | #define returnCode(x) \ 146 | /* memoize the intermediate code tree and return from this function */\ 147 | tree->status.code = (x);\ 148 | return (tree->status) 149 | 150 | #define GET_STATUS_FOOTER \ 151 | /* close the if-statement */\ 152 | }\ 153 | /* if we failed to do a returnCode, returnKind, or returnKindIndex, simply return from this function */\ 154 | return (tree->status) 155 | 156 | #define GET_STATUS_NO_CODE_FOOTER \ 157 | /* if we failed to do a returnType, returnTypeRet, or returnStatus, memoize the error type and return from this function */\ 158 | tree->status = TypeStatus(errType, NULL);\ 159 | /* label the exit point for type derivation */\ 160 | endTypeDerivation:\ 161 | /* return from this function */\ 162 | return (tree->status) 163 | 164 | // main semantic analysis function 165 | 166 | int sem(Tree *treeRoot, SymbolTree *&stRoot, SchedTree *&codeRoot); 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /src/types.h: -------------------------------------------------------------------------------- 1 | #ifndef _TYPES_H_ 2 | #define _TYPES_H_ 3 | 4 | #include "globalDefs.h" 5 | #include "constantDefs.h" 6 | #include "driver.h" 7 | 8 | #include "../tmp/parserStruct.h" 9 | 10 | // Type category specifiers 11 | #define CATEGORY_STDTYPE 0 12 | #define CATEGORY_TYPELIST 1 13 | #define CATEGORY_FILTERTYPE 2 14 | #define CATEGORY_OBJECTTYPE 3 15 | #define CATEGORY_ERRORTYPE 4 16 | 17 | // Type suffix specifiers 18 | #define SUFFIX_CONSTANT 0 19 | #define SUFFIX_LATCH 1 20 | #define SUFFIX_LIST 2 21 | #define SUFFIX_STREAM 3 22 | #define SUFFIX_ARRAY 4 23 | #define SUFFIX_POOL 5 24 | 25 | // Type offset kinds 26 | #define OFFSET_NULL 0 27 | #define OFFSET_RAW 1 28 | #define OFFSET_BLOCK 2 29 | #define OFFSET_PARTITION 3 30 | #define OFFSET_SHARE 4 31 | #define OFFSET_FREE 5 32 | 33 | // core Type class 34 | 35 | class Type { 36 | public: 37 | // data members 38 | int category; // the category that this Type belongs to 39 | int suffix; // the type suffix (constant, latch, stream, or array) 40 | int depth; // stream depth of arrays and streams 41 | Tree *offsetExp; // the offset expression for this type (if it's a SUFFIX_POOL); RAW_VECTOR, LSQUARE, NonArrayedIdentifier, ArrayedIdentifier, or CloneInstantiationSource 42 | bool referensible; // whether a node of this type can be referenced on its own 43 | bool instantiable; // whether a node of this type can be instantiated 44 | bool toStringHandled; // used for recursion detection in operator string() 45 | // mutators 46 | void constantize(); // for when an identifier is present without an accessor or a sub-identifier's type is constrained by upstream identifiers 47 | void latchize(); // for when we're instantiating a node with a single initializer 48 | void poolize(Tree *offsetExp); // for when we're instantiating a node with a multi initializer 49 | void decreaseDepth(); 50 | bool delatch() const; 51 | bool delist(); 52 | bool destream(); 53 | void copyDelatch(Tree *offsetExp); 54 | bool pack(); 55 | bool unpack(); 56 | Type *link(Type &otherType); 57 | TypeList *wrapTypeList() const; 58 | Type *foldTypeList() const; 59 | // allocators/deallocators 60 | Type(int category, int suffix = SUFFIX_CONSTANT, int depth = 0, Tree *offsetExp = NULL); 61 | virtual ~Type() = 0; 62 | // core methods 63 | // virtual 64 | virtual bool isComparable(const Type &otherType) const = 0; 65 | virtual Type *copy() const = 0; 66 | virtual void erase() = 0; 67 | virtual void clear() = 0; 68 | virtual string toString(unsigned int tabDepth = 1) = 0; 69 | // non-virtual 70 | bool baseEquals(const Type &otherType) const; 71 | bool baseSendable(const Type &otherType) const; 72 | int offsetKind() const; 73 | string suffixString() const; 74 | // operators 75 | // virtual 76 | virtual bool operator==(Type &otherType) = 0; 77 | virtual bool operator==(int kind) const = 0; 78 | virtual Type *operator,(Type &otherType) = 0; 79 | virtual bool operator>>(Type &otherType) = 0; 80 | virtual operator string() = 0; 81 | // non-virtual 82 | operator bool() const; 83 | bool operator!() const; 84 | bool operator!=(Type &otherType); 85 | bool operator!=(int kind) const; 86 | }; 87 | 88 | // Type subclasses 89 | 90 | // StdType node kinds 91 | #define STD_NULL 0 92 | #define STD_STD 1 93 | 94 | #define STD_MIN_COMPARABLE 2 95 | 96 | #define STD_BOOL 2 97 | #define STD_INT 3 98 | #define STD_FLOAT 4 99 | #define STD_CHAR 5 100 | #define STD_STRING 6 101 | 102 | #define STD_MAX_COMPARABLE 6 103 | 104 | #define STD_NOT 7 105 | #define STD_COMPLEMENT 8 106 | #define STD_DPLUS 9 107 | #define STD_DMINUS 10 108 | 109 | #define STD_DOR 11 110 | #define STD_DAND 12 111 | #define STD_OR 13 112 | #define STD_XOR 14 113 | #define STD_AND 15 114 | #define STD_DEQUALS 16 115 | #define STD_NEQUALS 17 116 | #define STD_LT 18 117 | #define STD_GT 19 118 | #define STD_LE 20 119 | #define STD_GE 21 120 | #define STD_LS 22 121 | #define STD_RS 23 122 | #define STD_TIMES 24 123 | #define STD_DIVIDE 25 124 | #define STD_MOD 26 125 | 126 | #define STD_PLUS 27 127 | #define STD_MINUS 28 128 | 129 | class StdType : public Type { 130 | public: 131 | // data members 132 | int kind; // the kind of standard type that this is 133 | // allocators/deallocators 134 | StdType(int kind, int suffix = SUFFIX_CONSTANT, int depth = 0, Tree *offsetExp = NULL); 135 | ~StdType(); 136 | // core methods 137 | bool isComparable() const; 138 | bool isComparable(const Type &otherType) const; 139 | int kindCast(const StdType &otherType) const; // returns kind resulting from sending *this to otherType, STD_NULL if the comparison is invalid 140 | pair stdFlowDerivation(const TypeStatus &prevStatus, Tree *nextTerm) const; // bool is whether we consumed nextTerm in the derivation 141 | bool objectTypePromotion(Type &otherType) const; // returns whether we can specially promote this StdType to the given ObjectType 142 | Type *copy() const; 143 | void erase(); 144 | void clear(); 145 | string kindToString() const; 146 | string toString(unsigned int tabDepth); 147 | // operators 148 | bool operator==(Type &otherType); 149 | bool operator==(int kind) const; 150 | Type *operator,(Type &otherType); 151 | bool operator>>(Type &otherType); 152 | operator string(); 153 | }; 154 | 155 | class TypeList : public Type { 156 | public: 157 | // data members 158 | vector list; // pointers to the underlying list of types 159 | // allocators/deallocators 160 | TypeList(const vector &list); 161 | TypeList(Type *type); 162 | TypeList(); 163 | ~TypeList(); 164 | // core methods 165 | bool isComparable(const Type &otherType) const; 166 | Type *copy() const; 167 | void erase(); 168 | void clear(); 169 | string toString(unsigned int tabDepth); 170 | // operators 171 | bool operator==(Type &otherType); 172 | bool operator==(int kind) const; 173 | Type *operator,(Type &otherType); 174 | bool operator>>(Type &otherType); 175 | operator string(); 176 | }; 177 | 178 | class FilterType : public Type { 179 | public: 180 | // data members 181 | TypeList *fromInternal; // the source of this object type 182 | TypeList *toInternal; // the destination of this object type 183 | Tree *defSite; // the FilterHeader tree node that defines this FilterType 184 | Type *inType; // the incoming type at the definition site 185 | // allocators/deallocators 186 | FilterType(Type *fromInternal = nullType, Type *toInternal = nullType, int suffix = SUFFIX_CONSTANT, int depth = 0, Tree *offsetExp = NULL); 187 | FilterType(Tree *defSite, Type *inType = nullType, int suffix = SUFFIX_CONSTANT, int depth = 0, Tree *offsetExp = NULL); 188 | ~FilterType(); 189 | // core methods 190 | TypeList *from(); 191 | TypeList *to(); 192 | bool isComparable(const Type &otherType) const; 193 | Type *copy() const; 194 | void erase(); 195 | void clear(); 196 | string toString(unsigned int tabDepth); 197 | // operators 198 | bool operator==(Type &otherType); 199 | bool operator==(int kind) const; 200 | Type *operator,(Type &otherType); 201 | bool operator>>(Type &otherType); 202 | operator string(); 203 | }; 204 | 205 | class StructorListResult { 206 | public: 207 | // data members 208 | const pair &internalPair; 209 | // allocators/deallocators 210 | StructorListResult(const pair &internalPair); 211 | ~StructorListResult(); 212 | // converters 213 | operator Type *() const; 214 | // core methods 215 | Tree *defSite() const; 216 | // operators 217 | Type *operator->() const; 218 | bool operator==(const StructorListResult &otherResult) const; 219 | bool operator!=(const StructorListResult &otherResult) const; 220 | }; 221 | 222 | class StructorList { 223 | public: 224 | // data members 225 | vector > structors; 226 | // allocators/deallocators 227 | StructorList(); 228 | StructorList(const StructorList &otherStructorList); 229 | ~StructorList(); 230 | // core methods 231 | void add(TypeList *typeList); 232 | void add(Tree *tree); 233 | unsigned int size() const; 234 | bool reify(); 235 | void clear(); 236 | // iterator methods 237 | class iterator { 238 | public: 239 | // data members 240 | vector >::iterator internalIter; 241 | // allocators/deallocators 242 | iterator(); 243 | iterator(const iterator &otherIter); 244 | iterator(const vector >::iterator &internalIter); 245 | ~iterator(); 246 | // operators 247 | iterator &operator=(const iterator &otherIter); 248 | void operator++(int); 249 | bool operator==(const iterator &otherIter); 250 | bool operator!=(const iterator &otherIter); 251 | StructorListResult operator*(); 252 | }; 253 | iterator begin(); 254 | iterator end(); 255 | }; 256 | 257 | class MemberListResult { 258 | public: 259 | // data members 260 | const pair > &internalPair; 261 | // allocators/deallocators 262 | MemberListResult(const pair > &internalPair); 263 | ~MemberListResult(); 264 | // converters 265 | operator string() const; 266 | operator Type *() const; 267 | // core methods 268 | Tree *defSite() const; 269 | // operators 270 | Type *operator->() const; 271 | bool operator==(const MemberListResult &otherResult) const; 272 | bool operator!=(const MemberListResult &otherResult) const; 273 | }; 274 | 275 | class MemberList { 276 | public: 277 | // data members 278 | map > memberMap; 279 | // allocators/deallocators 280 | MemberList(); 281 | MemberList(const MemberList &otherMemberList); 282 | ~MemberList(); 283 | // core methods 284 | void add(string name, Type *type); 285 | void add(string name, Tree *tree); 286 | unsigned int size() const; 287 | void clear(); 288 | // iterator methods 289 | class iterator { 290 | public: 291 | // data members 292 | map >::iterator internalIter; 293 | // allocators/deallocators 294 | iterator(); 295 | iterator(const iterator &otherIter); 296 | iterator(const map >::iterator &internalIter); 297 | ~iterator(); 298 | // operators 299 | iterator &operator=(const iterator &otherIter); 300 | void operator++(int); 301 | bool operator==(const iterator &otherIter); 302 | bool operator!=(const iterator &otherIter); 303 | MemberListResult operator*(); 304 | }; 305 | iterator begin(); 306 | iterator end(); 307 | iterator find(const string &name); 308 | }; 309 | 310 | class ObjectType : public Type { 311 | public: 312 | // data members 313 | StructorList instructorList; // list of the types of this object's instructors (each one is a TypeList) 314 | StructorList outstructorList; // list of the types of this object's outstructors (each one is a TypeList) 315 | MemberList memberList; // smart map of the names of members to their types 316 | // allocators/deallocators 317 | ObjectType(int suffix = SUFFIX_CONSTANT, int depth = 0, Tree *offsetExp = NULL); 318 | ObjectType(const StructorList &instructorList, const StructorList &outstructorList, int suffix = SUFFIX_CONSTANT, int depth = 0, Tree *offsetExp = NULL); 319 | ObjectType(const StructorList &instructorList, const StructorList &outstructorList, const MemberList &memberList, int suffix = SUFFIX_CONSTANT, int depth = 0, Tree *offsetExp = NULL); 320 | ~ObjectType(); 321 | // core methods 322 | bool isNullInstantiable(); 323 | bool isComparable(const Type &otherType) const; 324 | Type *copy() const; 325 | void erase(); 326 | void clear(); 327 | string toString(unsigned int tabDepth); 328 | // operators 329 | bool operator==(Type &otherType); 330 | bool operator==(int kind) const; 331 | Type *operator,(Type &otherType); 332 | bool operator>>(Type &otherType); 333 | operator string(); 334 | }; 335 | 336 | class ErrorType : public Type { 337 | public: 338 | // allocators/deallocators 339 | ErrorType(); 340 | ~ErrorType(); 341 | // core methods 342 | bool isComparable(const Type &otherType) const; 343 | Type *copy() const; 344 | void erase(); 345 | void clear(); 346 | string toString(unsigned int tabDepth); 347 | // operators 348 | bool operator==(Type &otherType); 349 | bool operator==(int kind) const; 350 | Type *operator,(Type &otherType); 351 | bool operator>>(Type &otherType); 352 | operator string(); 353 | }; 354 | 355 | // typing status class 356 | 357 | class TypeStatus { 358 | public: 359 | // data members 360 | Type *type; // the type derived for this parse tree node 361 | Type *retType; // the carry-over return type derived for this parse tree node 362 | IRTree *code; // the intermediate representation code tree for this parse tree node 363 | // allocators/deallocators 364 | TypeStatus(Type *type = NULL, Type *retType = NULL); 365 | TypeStatus(Type *type, const TypeStatus &otherStatus); 366 | ~TypeStatus(); 367 | // converters 368 | operator Type *() const; 369 | operator uintptr_t() const; 370 | // core methods 371 | DataTree *castCode(const Type &destType) const; 372 | DataTree *castCommonCode(const Type &otherType) const; 373 | // operators 374 | TypeStatus &operator=(const TypeStatus &otherStatus); 375 | TypeStatus &operator=(Type *otherType); 376 | Type &operator*() const; 377 | Type *operator->() const; 378 | bool operator==(Type &otherType); 379 | bool operator!=(Type &otherType); 380 | }; 381 | 382 | // external linkage specifiers 383 | extern Type *nullType; 384 | extern Type *errType; 385 | 386 | // post-includes 387 | #include "parser.h" 388 | #include "genner.h" 389 | 390 | // Type to string helper blocks 391 | 392 | #define TYPE_TO_STRING_HEADER \ 393 | /* if we have reached a recursive loop, return this fact */\ 394 | if (toStringHandled) {\ 395 | string acc(COLOREXP( SET_TERM(BRIGHT_CODE AND YELLOW_CODE) ));\ 396 | acc += "";\ 397 | acc += COLOREXP( SET_TERM(RESET_CODE) );\ 398 | return acc;\ 399 | } else { /* otherwise, set the recursive printing flag */\ 400 | toStringHandled = true;\ 401 | }\ 402 | /* prepare to compute the string normally */\ 403 | string acc 404 | 405 | #define TYPE_TO_STRING_FOOTER \ 406 | /* unset the recursive printing flag */\ 407 | toStringHandled = false;\ 408 | /* return the completed accumulator */\ 409 | return acc 410 | 411 | #define TYPE_TO_STRING_INDENT \ 412 | acc += "\n\t| ";\ 413 | for (unsigned int i=0; i < tabDepth; i++)\ 414 | acc += " " 415 | 416 | #define TYPE_TO_STRING_INDENT_CLOSE \ 417 | acc += "\n\t| ";\ 418 | for (unsigned int i=0; i < tabDepth-1; i++)\ 419 | acc += " " 420 | 421 | #endif 422 | -------------------------------------------------------------------------------- /tst/debug.ani: -------------------------------------------------------------------------------- 1 | // debug.ani -- test file for anic debugging purposes 2 | 3 | // basic expression testing 4 | @std; 5 | exp1 = [float](5); 6 | exp2 = (-7+(-5--++-(-1))*2++-100.0e+10); 7 | exp3 = [int\]; 1 + 2 ++ -- ->exp3; 8 | exp4 = [float\]; 7e-1 - + ->exp4; 9 | exp5 = [string\]; 1.0 + " concatenated to a string" ->exp5; 10 | exp6 = [int\[1][2][3]]; 11 | exp7 = [float]{ 12 | {{1},{2}}, 13 | {{3.0},{4}}, 14 | {{5},{6}} 15 | }; 16 | 17 | // basic construct testing 18 | { 19 | someInt = [int]; 10 ->someInt; 20 | someIntLatch = [int](-5--); \someIntLatch [int x] {x {->std.out; ->std.out;}}; 21 | someFloat = [float](1); 22 | someString = [string](false); 23 | someChar = [char]('c'); 24 | someChar ?? { 25 | 'a': 1; 26 | 'b': 2 27 | 'c': 3; 28 | : 4 29 | } ->someIntLatch; 30 | someBool = [bool](); 31 | someFilter = [int x, string y --> bool\] { 32 | x + y != "Hi" ? (false) : (\boolSub) -->; 33 | boolSub = ((1 ^ 1) == 1); 34 | }; 35 | 5, (8 == 9 || (false || true)) someFilter ->std.out; 36 | 1, 2 + , 5 * , 5 % - ++ >> 2 << 1 ->someInt; 37 | { 8 [->float] [float\ f]{\f ->std.out} }; 38 | { 9 [->int[100]] [int\[100] intPool]{} }; 39 | { "hi" [int](7) ->std.out }; 40 | { someObj [->\] ->std.out }; 41 | someObj = []{ 42 | xStream = [int\\]; 43 | \\xStream ->std.out; 44 | =[--> ?] {someInt == someFloat ? "someObj's string representation" : "garbage string" -->}; 45 | =[int\ x] {\x ->xStream;} 46 | =[--> float] {2.0 -->}; 47 | }; 48 | someObj [{=[-->float]} someObjCompat --> float] {someObjCompat -->;}; 49 | \someObj ->std.out; 50 | ((1 < (2|1)) && (true || false)) ? (4+someInt) : (2-- * someInt++); 51 | true ? {"Hi" ->std.out}; 52 | false ? {"Bye" ->std.out}; 53 | 1 [int x] {x}; 54 | 1.0e+100 [float\ f --> string] {\f; "someString" + 'c' + true + " someOtherString" + (7++ - 8--) -->}; 55 | [float](-5.0) ([int x]{}); 56 | someObj /* expression injection */ ([]{=;=[--> string]{"lol"-->}}) ->out; 57 | @std.out; 58 | packStream = [float\\]; 59 | packStream2 = [float\\]; 60 | \packStream <| |> ->packStream; 61 | \packStream :: \packStream2 ->packStream; 62 | \\packStream ->std.out; 63 | 5 ->packStream; 6.0e-1 ->packStream; 8.1 |> ->packStream; 64 | 5 std.gen <| [float\ f --> ?]{\f -->} ->std.out; 65 | 8, 9.0e-5, "str", false [? intParam, ? floatParam, string\ stringParam, ? boolParam]{ 66 | \intParam <->floatParam [->int] ->intParam; 67 | \boolParam <->stringParam == "str" ->boolParam; 68 | }; 69 | "hello\t#1", (-8.0e-8) [? firstParam, ? secondParam --> ?] {[obj]() -->;} 70 | }; 71 | 72 | // standard object construction testing 73 | BinTree = []{ 74 | x = [int\]; 75 | leftTree = [BinTree](1); rightTree = [BinTree](2); 76 | =[int\ x] {\x ->BinTree.x}; 77 | =[BinTree\ leftTree, BinTree\ rightTree] {\leftTree <->BinTree.leftTree; \rightTree <->BinTree.rightTree;} 78 | } 79 | 80 | // standard upcast testing 81 | intBinOp = [int x, int y --> int\] {\std.randInt -->}; 82 | + <->intBinOp; 83 | stringCompOp = [string x, string y --> bool\] {false -->}; 84 | \stringCompOp; 85 | == ->stringCompOp; 86 | 87 | // array and pool testing 88 | intPool = [int[256]]; 89 | 7 ->intPool.[0]; 90 | 10 ->intPool.[7]; 91 | intPool.[0] ->std.out; 92 | \intPool.[intPool.[0]] ->intPool.[42]; 93 | 94 | intArray = intPool; 95 | 96 | floatPool = [float]{1,2,3,4,5,6,7,8,9,0.0}; 97 | 1.01e-8 ->floatPool.[intArray.[42 * 2 / 42]]; 98 | \floatPool.[intArray.[2]] ->std.out; 99 | 100 | boolPool = [bool[100]](); 101 | \boolPool.[0] ->std.out; 102 | false ->boolPool.[0]; 103 | 104 | // object sub-identifier testing 105 | obj = []{ 106 | ={"nothing"}; 107 | mem = 1; 108 | rec = obj; 109 | } 110 | \obj ->obj; 111 | constMemRef = obj.mem; 112 | latchMemRef = [int](\obj.mem); 113 | recObjRef = obj.rec; 114 | recMemRef = obj.rec.mem; 115 | objLatchRef = [obj](\obj); 116 | 117 | // self-constructing object testing 118 | selfConsObj = []{ 119 | =; 120 | =[selfConsObj\ self] {}; 121 | } 122 | selfConsObjIns = [selfConsObj\]; 123 | 124 | // basic import testing 125 | impObj = []{ 126 | =; 127 | mem1 = []{ 128 | =[--> ?] { [int](10) -->; } 129 | }; 130 | mem2 = "Hi"; 131 | } 132 | useObj = []{ 133 | =[int x] {}; 134 | @impObj.mem1; 135 | mem = [int](mem1); 136 | } 137 | 138 | // basic inheritance testing 139 | inhObj = []{ 140 | =[int\ initX] {\initX;}; 141 | inhMem = [int\]; 142 | } 143 | subObj = []{ 144 | =; 145 | @[inhObj.*]; 146 | subMem = [float\]; 147 | } 148 | 149 | // real-time parallel clock + calculator hybrid program 150 | { 151 | @std.*; 152 | a=[int](0); op=[char](' '); b=[int](0); r=[int](0); 153 | 0 [int ms] { 154 | ("\r" + ms/1000.0 + ":" + a + op + b + "=" + r) ->out; 155 | 1 delay (ms+1) <- 156 | }; 157 | {\inInt->a \inChar->op \inInt->b <-}; 158 | {\op ?? {'+': (\a+\b) '-': (\a-\b) '*': (\a*\b) '/': (\a/\b) : 0} ->r <-}; 159 | }; 160 | 161 | // dining philosophers problem 162 | philosopher = []{ 163 | id = [int\]; 164 | chopstick = [int\]; 165 | nextPhil = [philosopher\]; 166 | =; 167 | =[int newId] { [\newId] <->id; } 168 | 169 | getChopsticks = [--> ?] { \chopstick, \nextPhil.chopstick --> }; 170 | returnChopsticks = [int\ cs1, int\ cs2] { \cs1 ->chopstick; \cs2 ->nextPhil.chopstick; }; 171 | eat = [int\ cs1, int\ cs2 --> ?] { 172 | "Philosopher " + id + " eating...\n" ->std.out; 173 | \cs1, \cs2 -->; 174 | }; 175 | { std.randInt std.delay getChopsticks eat returnChopsticks <- }; 176 | }; 177 | 178 | numPhils = 5; 179 | 180 | philPool = [philosopher[numPhils]]; 181 | numPhils std.gen <| [int curId] { 182 | curId ->philPool.[curId]; 183 | \philPool.[(curId + 1) % numPhils] ->philPool.[curId].nextPhil; 184 | }; 185 | 186 | // program termination testing 187 | 0 -->; // terminate the program and return status 0 188 | --------------------------------------------------------------------------------