├── .gitignore ├── test └── main.c ├── LICENSE ├── IOSMakeFile ├── TimeParser.h ├── Makefile ├── README.md ├── TimeParser.c ├── tokeIt.l └── parseIt.y /.gitignore: -------------------------------------------------------------------------------- 1 | # LexYacc Compiled Files 2 | y.output 3 | y.tab.c 4 | y.tab.h 5 | lex.yy.c 6 | 7 | # Object files 8 | *.o 9 | *.ko 10 | *.obj 11 | *.elf 12 | 13 | # Precompiled Headers 14 | *.gch 15 | *.pch 16 | 17 | # Libraries 18 | *.lib 19 | *.a 20 | *.la 21 | *.lo 22 | 23 | # Shared objects (inc. Windows DLLs) 24 | *.dll 25 | *.so 26 | *.so.* 27 | *.dylib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | *.i*86 34 | *.x86_64 35 | *.hex 36 | 37 | # Debug files 38 | *.dSYM/ 39 | -------------------------------------------------------------------------------- /test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../TimeParser.h" 4 | 5 | #ifndef MAX_INPUT 6 | #define MAX_INPUT 100 7 | #endif 8 | 9 | int main(int argc, char **argv) 10 | { 11 | char input[MAX_INPUT]; 12 | double t; 13 | struct tm *str_time; 14 | 15 | while(1){ 16 | printf("Give me a date in natural language ==> "); 17 | if (!fgets(input, MAX_INPUT, stdin)) { 18 | perror("an error occurred.\n"); 19 | } 20 | 21 | t = parseDateTimeString(input); 22 | time_t finaltime = t; 23 | str_time= localtime(&finaltime); 24 | printf("The time = %s\n", asctime(str_time)); 25 | } 26 | return 0; 27 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 momentlib 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /IOSMakeFile: -------------------------------------------------------------------------------- 1 | PROJ=moment 2 | LEX = lex 3 | YACC = yacc -d 4 | # LEX = flex 5 | # YACC = bison -d 6 | ifeq ($(IOS), 1) 7 | ARCH=armv7 8 | DEVICE=OS 9 | CC_FLAGS=-arch $(ARCH) 10 | CFLAGS_FLAGS=-mcpu=cortex-a8 -marm 11 | else ifeq ($(IOS), 2) 12 | ARCH=arm64 13 | DEVICE=OS 14 | CC_FLAGS=-arch $(ARCH) 15 | # CFLAGS_FLAGS=-mcpu=cortex-a8 -marm 16 | else 17 | ARCH=x86_64 18 | CC_FLAGS=-arch $(ARCH) 19 | DEVICE=Simulator 20 | endif 21 | 22 | DEVROOT=/Applications/Xcode.app/Contents/Developer 23 | SDKROOT=${DEVROOT}/Platforms/iPhone$(DEVICE).platform/Developer/SDKs/iPhone$(DEVICE)9.2.sdk 24 | CC=$(DEVROOT)/usr/bin/gcc $(CC_FLAGS) 25 | LD=$(CC) 26 | CFLAGS=-isysroot ${SDKROOT} -Iheaders $(CFLAGS_FLAGS) 27 | LDFLAGS=-isysroot ${SDKROOT} -Wl, -syslibroot ${SDKROOT} 28 | 29 | SRC=$(wildcard *.c) 30 | OBJS=$(patsubst %.c,%.o,$(SRC)) 31 | DEPS= 32 | 33 | LIBDIR=$(shell pwd)/libs 34 | LDLIBS=$(patsubst %, $(DIR)/lib%.a, $(DEPS)) 35 | 36 | all:$(ARCH)-$(PROJ).a 37 | 38 | 39 | $(ARCH)-$(PROJ).a: $(OBJS) 40 | @echo $(LDLIBS) $(OBJS) 41 | ar rcs $@ $(OBJS) 42 | ranlib $@ 43 | 44 | .PHONY: lipo 45 | lipo: 46 | lipo -create armv7-$(PROJ).a arm64-$(PROJ).a x86_64-$(PROJ).a -output libs/$(PROJ).a 47 | # lipo -create -arch armv7 armv7-$(PROJ).a -arch x86_64 x86_64-$(PROJ).a -output libs/$(PROJ).a 48 | 49 | clean: 50 | rm -f $(OBJS) 51 | 52 | 53 | .PHONY: realclean 54 | realclean: clean 55 | rm *.a libs/*.a lex.yy.c *.tab.* *.output *.gch *.exe -------------------------------------------------------------------------------- /TimeParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // TimeParser.h 3 | // NLDP 4 | // 5 | // Created by Kevin Musselman on 6/28/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define DIGILEN (int)(log10 (INT_MAX) +3) 17 | 18 | 19 | extern int yyparse(); 20 | extern char * yytext; 21 | typedef struct yy_buffer_state *YY_BUFFER_STATE; 22 | void yy_switch_to_buffer(YY_BUFFER_STATE); 23 | YY_BUFFER_STATE yy_scan_string (const char *); 24 | 25 | struct modifier 26 | { 27 | int amount[9]; 28 | int specAmount[3]; 29 | int specValue[3]; 30 | 31 | }; 32 | 33 | struct modifier mymodifier; 34 | struct modifier fromModifier; 35 | 36 | struct tm currentTime; 37 | 38 | struct tm *str_time; 39 | int *timePointer[7]; 40 | 41 | struct tm temp_time; 42 | struct tm set_time; 43 | 44 | time_t curtime; 45 | time_t initialTime; 46 | 47 | 48 | int changeAmount[9]; 49 | int fromChangeAmount[9]; 50 | 51 | int specAmount[3]; 52 | int finalSpecAmount[3]; 53 | 54 | char * unusedText; 55 | 56 | 57 | void setCurrentTime(void); 58 | void setTime(int hr, int min, int sec); 59 | void setDate(int day, int month, int year, int wday); 60 | 61 | void setBoth(int sec, int min, int hr, int day, int month, int year, int wday); 62 | char* join_strings(int* strings, char* seperator, int count); 63 | void setDayOfWeek(int weekday, int *amount); 64 | void setFinalTime(struct tm *temp, int amount[], int *change); 65 | void itoa(int n, char s[]); 66 | 67 | double parseDateTimeString(const char *str); 68 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # # A Makefile for simple lex and yacc examples 2 | 3 | # # Comment out the proper lines below according to the scanner and 4 | # # parser generators available in your system 5 | 6 | LEX = lex 7 | YACC = yacc -d 8 | # LEX = flex 9 | # YACC = bison -d 10 | 11 | # # We assume that your C-compiler is called gcc 12 | 13 | CC = gcc 14 | 15 | 16 | # testParser is the final object that we will generate, it used to test that the static library was created correctly 17 | 18 | testParser: ./test/main.c momentLib 19 | $(CC) -o testParser.exe test/main.c libMoment.a 20 | 21 | # momentLib: this is static library that is created from the y.tab.o lex.yy.o and TimeParser.o 22 | momentLib: y.tab.o lex.yy.o TimeParser.o 23 | ar -cvq libMoment.a *.o 24 | 25 | #TimeParser.o 26 | TimeParser.o: TimeParser.c TimeParser.h 27 | $(CC) -c TimeParser.c 28 | 29 | ## This rule will use yacc to generate the files y.tab.c and y.tab.h 30 | ## from our file parseIt.y 31 | 32 | y.tab.c y.tab.h: parseIt.y 33 | $(YACC) -v parseIt.y 34 | 35 | y.tab.o: y.tab.c TimeParser.h 36 | $(CC) -c y.tab.c 37 | 38 | # These dependency rules indicate that (1) lex.yy.o depends on 39 | # lex.yy.c and y.tab.h and (2) lex.yy.o and y.tab.o depend on TimeParser.h. 40 | # Make uses the dependencies to figure out what rules must be run when 41 | # a file has changed. 42 | 43 | lex.yy.o: y.tab.h lex.yy.c 44 | $(CC) -c lex.yy.c TimeParser.h 45 | 46 | ## this is the make rule to use lex to generate the file lex.yy.c from 47 | ## our file tokeIt.l 48 | 49 | lex.yy.c: tokeIt.l TimeParser.h 50 | $(LEX) tokeIt.l 51 | 52 | 53 | ## Make clean will delete all of the generated files so we can start 54 | ## from scratch 55 | 56 | clean: 57 | -rm -f *.o lex.yy.c *.tab.* *.output *.gch *.exe libMoment.a 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # core 2 | Natural Language Date/Time parser written in Lex, Yacc and C. 3 | 4 | ###Build It: 5 | 1. clone repo 6 | 2. run command "make" 7 | 3. make creates a static library called libMoment.a and an executable testParser.exe that links to the static library. 8 | 9 | Run ./testParser.exe to try it out. 10 | 11 | 12 | If you want to use the library in XCode you can run the script buildFatLibIOS.sh 13 | This will build a fat library containing the library for ISO and for Simulator. Currently only set for 9.2 sdk. 14 | 15 |
16 | To use it:
17 | Add the library and TimeParser.h to your project
18 | Include "TimeParser.h" 
19 | Then call the method parseDateTimeString(StringToParse), which returns a double type (unix time).
20 | You can then turn it into struct tm * with the localtime function but first would need to cast it to a time_t type.
21 | 
22 | 23 | 24 |

Example Expressions:

25 | 26 |

Simple

27 |
    28 | 29 | 30 |
  • thursday
  • 31 |
  • november
  • 32 |
  • friday 13:00
  • 33 |
  • mon 2:35
  • 34 |
  • 4pm
  • 35 |
  • 6 in the morning
  • 36 |
  • friday 1pm
  • 37 |
  • sat 7 in the evening
  • 38 |
  • yesterday
  • 39 |
  • today
  • 40 |
  • tomorrow
  • 41 |
  • this tuesday
  • 42 |
  • next month
  • 43 |
  • this morning
  • 44 |
  • last night
  • 45 |
  • this second
  • 46 |
  • yesterday at 4:00
  • 47 |
  • last friday at 20:00
  • 48 |
  • last week tuesday
  • 49 |
  • tomorrow at 6:45pm
  • 50 |
  • afternoon yesterday
  • 51 |
  • thursday last week
  • 52 | 53 |
54 |

Complex

55 |
    56 |
  • 3 years ago
  • 57 |
  • 5 months before now
  • 58 |
  • 7 hours ago
  • 59 |
  • 7 days from now
  • 60 |
  • 1 week hence
  • 61 |
  • in 3 hours
  • 62 |
  • 1 year ago tomorrow
  • 63 |
  • 3 months ago saturday at 5:00 pm
  • 64 |
  • 7 hours before tomorrow at noon
  • 65 |
  • 3rd wednesday in november
  • 66 |
  • 3rd month next year
  • 67 |
  • 3rd thursday this september
  • 68 |
  • 4th day last week
  • 69 |
70 | 71 |

Specific Dates

72 |
    73 |
  • January 5
  • 74 |
  • dec 25
  • 75 |
  • may 27th
  • 76 |
  • October 2006
  • 77 |
  • jan 3 2010
  • 78 |
  • March 14, 2004
  • 79 |
  • March 14th, 2004
  • 80 |
  • 3 jan 2000
  • 81 |
  • 17 april 85
  • 82 |
  • 5/27/1979
  • 83 |
  • 27/5/1979
  • 84 |
  • 1979-05-27
  • 85 |
  • Friday
  • 86 |
  • 5
  • 87 |
  • 4:00
  • 88 |
  • 17:00
  • 89 |
  • 0800
  • 90 |
91 | 92 | -------------------------------------------------------------------------------- /TimeParser.c: -------------------------------------------------------------------------------- 1 | // 2 | // TimeParser.c 3 | // NLDP 4 | // 5 | // Created by Kevin Musselman on 6/28/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #include "TimeParser.h" 10 | 11 | 12 | void setCurrentTime() 13 | { 14 | 15 | curtime = time(NULL); 16 | str_time= localtime(&curtime); 17 | 18 | timePointer[0] = &(str_time->tm_sec); 19 | timePointer[1] = &(str_time->tm_min); 20 | timePointer[2] = &(str_time->tm_hour); 21 | timePointer[3] = &(str_time->tm_mday); 22 | timePointer[4] = &(str_time->tm_wday); 23 | timePointer[5] = &(str_time->tm_mon); 24 | timePointer[6] = &(str_time->tm_year); 25 | 26 | initialTime = time(NULL); 27 | temp_time = *(localtime(&initialTime)); 28 | temp_time.tm_sec = -1; 29 | temp_time.tm_min = -1; 30 | temp_time.tm_hour = -1; 31 | temp_time.tm_mday = -1; 32 | temp_time.tm_wday = -1; 33 | temp_time.tm_mon = -1; 34 | temp_time.tm_year = -1; 35 | 36 | set_time.tm_sec = -1; 37 | set_time.tm_min = -1; 38 | set_time.tm_hour = -1; 39 | set_time.tm_mday = -1; 40 | set_time.tm_wday = -1; 41 | set_time.tm_mon = -1; 42 | set_time.tm_year = -1; 43 | 44 | fromModifier.specAmount[0] = mymodifier.specAmount[0] = finalSpecAmount[0] = specAmount[0] = 0; 45 | fromModifier.specAmount[1] = mymodifier.specAmount[1] = finalSpecAmount[1] = specAmount[1] = 0; 46 | fromModifier.specAmount[2] = mymodifier.specAmount[2] = finalSpecAmount[2] = specAmount[2] = 0; 47 | mymodifier.specValue[0] = -1; 48 | mymodifier.specValue[1] = -1; 49 | mymodifier.specValue[2] = -1; 50 | fromModifier.specValue[0] = -1; 51 | fromModifier.specValue[1] = -1; 52 | fromModifier.specValue[2] = -1; 53 | int len=sizeof(changeAmount)/sizeof(int); 54 | for(int i=0; i< len; i++) 55 | { 56 | changeAmount[i] = 0; 57 | fromChangeAmount[i] = 0; 58 | mymodifier.amount[i] = 0; 59 | fromModifier.amount[i] = 0; 60 | } 61 | 62 | unusedText = NULL; 63 | 64 | // str_time->tm_year = 139; 65 | // time_t finalTime = mktime(str_time); 66 | // str_time= localtime(&finalTime); 67 | // printf("after year change = %s\n", asctime(str_time)); 68 | 69 | } 70 | 71 | void setTime(int sec, int min, int hr) 72 | { 73 | str_time->tm_hour = hr; 74 | str_time->tm_min = min; 75 | str_time->tm_sec = sec; 76 | } 77 | void setDate(int day, int month, int year, int wday) 78 | { 79 | str_time->tm_mday = day; 80 | str_time->tm_wday = wday; 81 | str_time->tm_mon = month; 82 | str_time->tm_year = year; 83 | } 84 | 85 | void setBoth(int sec, int min, int hr, int day, int month, int year, int wday) 86 | { 87 | setDate(day, month, year, wday); 88 | setTime(sec, min, hr); 89 | 90 | } 91 | 92 | char* join_strings(int* strings, char* seperator, int count) { 93 | char* str = NULL; /* Pointer to the joined strings */ 94 | char intstr[DIGILEN]; 95 | size_t total_length = 0; /* Total length of joined strings */ 96 | int i = 0; /* Loop counter */ 97 | 98 | /* Find total length of joined strings */ 99 | 100 | 101 | for (i = 0; i < count; i++) 102 | { 103 | sprintf(intstr, "%d", strings[i]); 104 | total_length += strlen(intstr); 105 | } 106 | total_length++; /* For joined string terminator */ 107 | total_length += strlen(seperator) * (count - 1); // for seperators 108 | 109 | str = (char*) malloc(total_length); /* Allocate memory for joined strings */ 110 | str[0] = '\0'; /* Empty string we can append to */ 111 | 112 | /* Append all the strings */ 113 | for (i = 0; i < count; i++) { 114 | sprintf(intstr, "%d", strings[i]); 115 | strcat(str, intstr); 116 | if (i < (count - 1)) strcat(str, seperator); 117 | } 118 | 119 | return str; 120 | } 121 | 122 | 123 | void setFinalTime(struct tm *temp, int amount[], int *change) 124 | { 125 | 126 | // printf("set final time BEFORE= temp time= %s\n", asctime(str_time)); 127 | time_t tempTime = mktime(str_time); 128 | 129 | str_time= localtime(&tempTime); 130 | 131 | if(temp->tm_year >= 0) 132 | { 133 | str_time->tm_year = temp->tm_year; 134 | amount[2] = 0; 135 | } 136 | *timePointer[6] += change[6]; 137 | 138 | tempTime = mktime(str_time); 139 | 140 | str_time= localtime(&tempTime); 141 | 142 | 143 | int mon = str_time->tm_mon; 144 | if(temp->tm_mon >= 0) 145 | { 146 | amount[2] = 0; 147 | if(temp->tm_mon >=12) 148 | { 149 | str_time->tm_mon = mon = temp->tm_mon-12; 150 | str_time->tm_year +=1; 151 | 152 | } 153 | else 154 | { 155 | if(str_time->tm_mon > temp->tm_mon && (temp->tm_year < 0 && change[6]==0)) 156 | { 157 | if(amount[0] <= 0) 158 | str_time->tm_year += (amount[0]+1); 159 | else 160 | str_time->tm_year += amount[0]; 161 | } 162 | else if(str_time->tm_mon < temp->tm_mon) 163 | { 164 | if(amount[0] <= 0) 165 | str_time->tm_year += (amount[0]); 166 | else 167 | str_time->tm_year += (amount[0]-1); 168 | } 169 | else if(str_time->tm_mon == temp->tm_mon) 170 | { 171 | str_time->tm_year += amount[0]; 172 | } 173 | str_time->tm_mon = mon = temp->tm_mon; 174 | } 175 | 176 | } 177 | // printf("set final time after= temp time= %s\n", asctime(str_time)); 178 | 179 | *timePointer[5] += change[5]; 180 | 181 | 182 | tempTime = mktime(str_time); 183 | str_time= localtime(&tempTime); 184 | 185 | if(str_time->tm_mon != (mon+change[5])) 186 | str_time->tm_mon = (mon+change[5]); 187 | 188 | 189 | /******* change[7] is the number of weeks ******/ 190 | if(change[7]) 191 | { 192 | 193 | str_time->tm_mday += 7*change[7]; 194 | str_time->tm_mday -= str_time->tm_wday; 195 | tempTime = mktime(str_time); 196 | str_time= localtime(&tempTime); 197 | // printf("main time after month/year change = %s\n", asctime(str_time)); 198 | } 199 | 200 | if(temp->tm_mday >=0) 201 | { 202 | if(change[7]) 203 | { 204 | str_time->tm_mday += temp->tm_mday; 205 | } 206 | else 207 | str_time->tm_mday = temp->tm_mday; 208 | 209 | tempTime = mktime(str_time); 210 | str_time= localtime(&tempTime); 211 | // printf("the set day %d and is %s \n", temp->tm_mday, asctime(str_time)); 212 | } 213 | if(amount[1]>0 && temp->tm_mday >=0 && temp->tm_wday <0) temp->tm_wday = 0;//str_time->tm_wday; 214 | setDayOfWeek(temp->tm_wday, amount); 215 | 216 | // printf("amount2 = %d and change3 = %d", amount[2], change[3]); 217 | if(amount[2]!= 0 && change[3]==0) 218 | { 219 | switch(change[8]) 220 | { 221 | case 'm': 222 | { 223 | // printf("in the morning"); 224 | if(temp->tm_hour >= 0) 225 | { 226 | if((temp->tm_hour < str_time->tm_hour || (temp->tm_hour == str_time->tm_hour && temp->tm_min < str_time->tm_min))) 227 | str_time->tm_mday += 1; 228 | 229 | } 230 | else if(str_time->tm_hour > 12) 231 | str_time->tm_mday += 1; 232 | } 233 | break; 234 | case 'a': 235 | { 236 | // printf("in the afternoon"); 237 | if(temp->tm_hour >= 0) 238 | { 239 | if((temp->tm_hour < str_time->tm_hour || (temp->tm_hour == str_time->tm_hour && temp->tm_min < str_time->tm_min))) 240 | str_time->tm_mday += 1; 241 | 242 | } 243 | else if(str_time->tm_hour > 17) 244 | str_time->tm_mday += 1; 245 | } 246 | break; 247 | case 'e': 248 | { 249 | // printf("in the evening %d", temp->tm_hour); 250 | if(temp->tm_hour >= 0) 251 | { 252 | if((temp->tm_hour < str_time->tm_hour || (temp->tm_hour == str_time->tm_hour && temp->tm_min < str_time->tm_min))) 253 | str_time->tm_mday += 1; 254 | 255 | } 256 | else if(str_time->tm_hour > 20) 257 | str_time->tm_mday += 1; 258 | } 259 | break; 260 | case 'n': 261 | { 262 | } 263 | break; 264 | default: 265 | break; 266 | } 267 | } 268 | 269 | if(temp->tm_hour >= 0) 270 | str_time->tm_hour = temp->tm_hour; 271 | if(temp->tm_min >= 0) 272 | str_time->tm_min = temp->tm_min; 273 | if(temp->tm_sec >= 0) 274 | str_time->tm_sec = temp->tm_sec; 275 | 276 | 277 | change[6] = 0; 278 | change[5] = 0; 279 | 280 | for(int i=0; i<7; i++){ 281 | *timePointer[i] += change[i]; 282 | } 283 | tempTime = mktime(str_time); 284 | str_time= localtime(&tempTime); 285 | 286 | temp->tm_sec = -1; 287 | temp->tm_min = -1; 288 | temp->tm_hour = -1; 289 | temp->tm_mday = -1; 290 | temp->tm_wday = -1; 291 | temp->tm_mon = -1; 292 | temp->tm_year = -1; 293 | amount[0] = 0; 294 | amount[1] = 0; 295 | amount[2] = 0; 296 | 297 | 298 | for(int i=0; i< 9; i++) 299 | { 300 | change[i] = 0; 301 | } 302 | 303 | time_t finalTime = mktime(str_time); 304 | str_time= localtime(&finalTime); 305 | } 306 | 307 | 308 | void setDayOfWeek(int weekday, int *amount) 309 | { 310 | 311 | if(weekday >= 0) 312 | { 313 | // printf("weekday = %d and amount = %d", weekday, amount[1]); 314 | amount[2] = 0; 315 | if(str_time->tm_wday > weekday) 316 | { 317 | int dif = str_time->tm_wday - weekday; 318 | if (amount[1]==0) { 319 | str_time->tm_mday += (7-dif); 320 | } 321 | else if(amount[1]>0) 322 | { 323 | str_time->tm_mday += (7-dif)+(amount[1]-1)*7; 324 | } 325 | else if(amount[1] < 0) 326 | { 327 | str_time->tm_mday += ((amount[1]+1)*7)-dif; 328 | } 329 | 330 | } 331 | else if(str_time->tm_wday < weekday) 332 | { 333 | int dif = weekday - str_time->tm_wday; 334 | if (amount[1]==0) { 335 | str_time->tm_mday += dif; 336 | } 337 | else if(amount[1]>0) 338 | { 339 | str_time->tm_mday += (dif+(amount[1]-1)*7); 340 | } 341 | else if(amount[1] < 0) 342 | { 343 | str_time->tm_mday += (dif-7)+((amount[1]+1)*7); 344 | } 345 | } 346 | else if(str_time->tm_wday == weekday) 347 | { 348 | str_time->tm_mday += (amount[1]*7); 349 | } 350 | 351 | str_time->tm_wday = weekday; 352 | time_t tempTime = mktime(str_time); 353 | str_time= localtime(&tempTime); 354 | 355 | // printf("the string after wday = %s \n ", asctime(str_time)); 356 | 357 | } 358 | 359 | } 360 | 361 | /* reverse: reverse string s in place */ 362 | static void reverse(char s[]) 363 | { 364 | int i, j; 365 | char c; 366 | 367 | for (i = 0, j = strlen(s)-1; i 0); /* delete it */ 384 | if (sign < 0) 385 | s[i++] = '-'; 386 | s[i] = '\0'; 387 | reverse(s); 388 | } 389 | 390 | 391 | double parseDateTimeString(const char *str) 392 | { 393 | yy_switch_to_buffer(yy_scan_string(str)); 394 | yyparse(); 395 | time_t tempTime = mktime(str_time); 396 | str_time= localtime(&tempTime); 397 | 398 | 399 | setFinalTime(&set_time, finalSpecAmount, fromChangeAmount); 400 | 401 | tempTime = mktime(str_time); 402 | str_time= localtime(&tempTime); 403 | if(fromModifier.specValue[1]) 404 | { 405 | setDayOfWeek(fromModifier.specValue[1], fromModifier.specAmount); 406 | } 407 | 408 | return difftime(mktime(str_time), 0); 409 | 410 | } 411 | -------------------------------------------------------------------------------- /tokeIt.l: -------------------------------------------------------------------------------- 1 | /* date convert #1 */ 2 | 3 | 4 | %{ 5 | 6 | 7 | #include 8 | #include "y.tab.h" 9 | 10 | #define YY_NO_INPUT 11 | 12 | extern time_t curtime; 13 | extern struct tm temp_time; 14 | 15 | extern struct tm *str_time; 16 | extern char * unusedText; 17 | 18 | void yyerror(char *); 19 | 20 | void concatUnusedString(char *newstr); 21 | void parseMonthDayStr(char *text, char *tok); 22 | void parseDayMonthStr(char *text, char *tok); 23 | void parseYearMonthDayStr(char *text, char *tok); 24 | 25 | %} 26 | 27 | %option nounput 28 | 29 | %x error 30 | 31 | dateTimeTerms (sec(ond)?|min(ute)?|hour|hr|day|week|month|year)s? 32 | 33 | regularTime ((0?[1-9])|(1[0|1|2]))((:[0-5][0-9](" "?(a|p)\.?m\.?)?)|(" "?(a|p)\.?m\.?)) 34 | militaryTime (([0-1][0-9])|([2][0-3])):?([0-5][0-9]) 35 | specificTimes noon|midnight 36 | generalTime (morning|afternoon|evening|night|tonight|tonite)s? 37 | 38 | 39 | 40 | months (jan(uary|uaries)?|feb(ruary|ruaries)?|mar(ch|ches)?|apr(il)?|may|june?|jul(y|ies)?|aug(ust)?|sep(t)?(ember)?|oct(ober)?|nov(ember)?|dec(ember)?)(s?)\.? 41 | days sun|mon|tues|wed(nes)?|thurs|fri|sat(ur)? 42 | 43 | 44 | genericNum (([0][1-9])|([1][0-2])|([1-9])) 45 | daydate (([1][3-9])|([2][0-9])|(3[01])) 46 | yeardate ([12]([0-9]{3})) 47 | 48 | setModifier on 49 | 50 | 51 | 52 | times {regularTime}|{militaryTime} 53 | onDay (on)" "{days}(day)? 54 | 55 | 56 | 57 | %% 58 | 59 | in" "the { return INTHE; } 60 | now { return NOW; }; 61 | 62 | tomorrow { yylval.number = 8; return DAYOFWEEK; } 63 | yesterday { yylval.number = -1; return DAYOFWEEK; } 64 | today { yylval.number = 0; return DAYOFWEEK; } 65 | from { yylval.number = 1; return FROM; } 66 | last { yylval.number = -1; return LASTNEXT; } 67 | next { yylval.number = 1; return LASTNEXT; } 68 | ago|past { yylval.number = -1; return HENCEAGO; } 69 | hence { yylval.number = 1; return HENCEAGO; } 70 | before { yylval.number = -1; return BEFOREAFTER; } 71 | after { yylval.number = 1; return BEFOREAFTER; } 72 | in { yylval.number = 1; return IN; } 73 | this { yylval.number = 0; return THIS; } 74 | 75 | 76 | 77 | {dateTimeTerms} { 78 | switch(yytext[0]) 79 | { 80 | case 's': 81 | { 82 | yylval.number=0; 83 | } 84 | break; 85 | case 'm': 86 | { 87 | if(yytext[1]=='i') 88 | yylval.number=1; 89 | else 90 | yylval.number = 5; 91 | } 92 | break; 93 | case 'h': 94 | { 95 | yylval.number=2; 96 | } 97 | break; 98 | case 'd': 99 | { 100 | yylval.number=3; 101 | } 102 | break; 103 | case 'w': 104 | { 105 | yylval.number=4; 106 | } 107 | break; 108 | case 'y': 109 | { 110 | yylval.number=6; 111 | } 112 | break; 113 | } 114 | return TYPENAMES; 115 | 116 | } 117 | 118 | 119 | {generalTime} { 120 | 121 | yylval.number = yytext[0]; 122 | return GENERALTIME; 123 | 124 | } 125 | {specificTimes} { 126 | if(yytext[0]=='m') 127 | { 128 | yylval.string= strdup("00:00"); 129 | } 130 | else 131 | { 132 | yylval.string = strdup("12:00"); 133 | } 134 | return WHENTIME; 135 | 136 | } 137 | 138 | {regularTime} { 139 | 140 | int i, j= (int)strlen(yytext); 141 | 142 | char apm[3] = ":am"; 143 | for(i = 1; yytext[i] != '\0'; i++){ 144 | if(yytext[i] == 'a'){ 145 | j = i; 146 | break; 147 | } 148 | else if(yytext[i]== 'p') 149 | { 150 | apm[1] = 'p'; 151 | j=i; 152 | break; 153 | 154 | } 155 | } 156 | 157 | 158 | char hr[j+4]; 159 | 160 | strncpy(hr, yytext, j); 161 | hr[j] = '\0'; 162 | strcat(hr, apm); 163 | 164 | yylval.string=strdup(hr); 165 | return WHENTIME; 166 | } 167 | 168 | {militaryTime} { 169 | 170 | char *new = strdup(yytext); 171 | 172 | char hr[7] = ""; 173 | strncat(hr, new, 2); 174 | hr[2] = ':'; 175 | strncat(hr, &new[strlen(new)-2], 2); 176 | 177 | hr[5] = '\0'; 178 | 179 | yylval.string = strdup(hr); 180 | return MILITARYTIME; 181 | } 182 | 183 | {months} { 184 | switch(yytext[0]) 185 | { 186 | case 'j': 187 | { 188 | if(yytext[1]=='a') 189 | { 190 | yylval.number=0; 191 | } 192 | else if(yytext[2]=='n') 193 | { 194 | yylval.number=5; 195 | } 196 | else 197 | { 198 | yylval.number = 6; 199 | } 200 | } 201 | break; 202 | case 'f': 203 | yylval.number=1; 204 | break; 205 | case 'm': 206 | { 207 | if(yytext[2]=='r') 208 | { 209 | yylval.number=2; 210 | } 211 | else 212 | { 213 | yylval.number=4; 214 | } 215 | } 216 | break; 217 | case 'a': 218 | { 219 | if(yytext[1]=='p') 220 | { 221 | yylval.number=3; 222 | } 223 | else 224 | { 225 | yylval.number=7; 226 | } 227 | } 228 | break; 229 | case 's': 230 | { 231 | yylval.number=8; 232 | } 233 | break; 234 | case 'o': 235 | { 236 | yylval.number=9; 237 | } 238 | break; 239 | case 'n': 240 | { 241 | yylval.number=10; 242 | } 243 | break; 244 | case 'd': 245 | { 246 | yylval.number=11; 247 | } 248 | break; 249 | } 250 | return MONTHNUM; 251 | } 252 | 253 | {days}(\.|days?)? { 254 | 255 | switch(yytext[0]) 256 | { 257 | case 's': 258 | { 259 | if(yytext[1]=='a') 260 | { 261 | yylval.number=7; 262 | } 263 | else 264 | { 265 | yylval.number=1; 266 | } 267 | } 268 | break; 269 | case 'm': 270 | yylval.number=2; 271 | break; 272 | case 't': 273 | { 274 | if(yytext[1]=='h') 275 | { 276 | yylval.number=5; 277 | } 278 | else 279 | { 280 | yylval.number=3; 281 | } 282 | } 283 | break; 284 | case 'w': 285 | { 286 | yylval.number=4; 287 | } 288 | break; 289 | case 'f': 290 | { 291 | yylval.number=6; 292 | } 293 | break; 294 | } 295 | return DAYOFWEEK; 296 | } 297 | 298 | {daydate}"/"{genericNum}"/"{yeardate} { /***** ex. 23/05/2012 *****/ 299 | parseDayMonthStr(yytext, "/"); 300 | return SETDATE; 301 | } 302 | 303 | {genericNum}"/"{daydate}"/"{yeardate} { /***** ex. 11/23/2011 *****/ 304 | parseMonthDayStr(yytext, "/"); 305 | return SETDATE; 306 | } 307 | 308 | {genericNum}"/"{genericNum}"/"{yeardate} { /***** ex. 11/11/2012 *****/ 309 | parseMonthDayStr(yytext, "/"); 310 | return SETDATE; 311 | } 312 | {daydate}"-"{genericNum}"-"{yeardate} { /***** ex. 23-05-2012 *****/ 313 | parseDayMonthStr(yytext, "-"); 314 | return SETDATE; 315 | } 316 | 317 | {genericNum}"-"{daydate}"-"{yeardate} { /***** ex. 11-23-2011 *****/ 318 | parseMonthDayStr(yytext, "-"); 319 | return SETDATE; 320 | } 321 | 322 | {genericNum}"-"{genericNum}"-"{yeardate} { /***** ex. 11-11-2012 *****/ 323 | parseMonthDayStr(yytext, "-"); 324 | return SETDATE; 325 | } 326 | 327 | {yeardate}"/"{genericNum}"/"({genericNum}|{daydate}) { /***** ex. 2012/11/11 *****/ 328 | parseYearMonthDayStr(yytext, "/"); 329 | return SETDATE; 330 | } 331 | 332 | {yeardate}"-"{genericNum}"-"({genericNum}|{daydate}) { /***** ex. 2012-11-11 *****/ 333 | parseYearMonthDayStr(yytext, "-"); 334 | return SETDATE; 335 | } 336 | 337 | [0-9]+(st|nd|rd|th) { 338 | size_t thesize = strlen(yytext)-2; 339 | char *to = (char*) malloc(thesize); 340 | strncpy(to, yytext, thesize); 341 | yylval.number=atoi(to); 342 | 343 | return DTPOSITION; 344 | } 345 | 346 | [0-9]+ { 347 | 348 | yylval.number= atoi(yytext); 349 | return INTEGER; 350 | } 351 | 352 | 353 | 354 | 355 | at|@ {yylval.string = yytext; return ARTICLEPREP; } 356 | the ; 357 | [ \t,] { concatUnusedString(strdup(yytext)); BEGIN(INITIAL); } /* skip whitespace */ 358 | [ \t,] { concatUnusedString(strdup(yytext)); BEGIN(INITIAL); } /* skip whitespace in error state */ 359 | \+|plus { yylval.number = 1; return PLUS;} 360 | 361 | 362 | . { 363 | 364 | BEGIN(error); 365 | concatUnusedString(strdup(yytext)); 366 | // yyerror("Unknown character"); 367 | } 368 | 369 | . { 370 | concatUnusedString(strdup(yytext)); 371 | // printf("error character is = %s\n", yytext); 372 | } 373 | 374 | %% 375 | 376 | void parseMonthDayStr(char *text, char *tok) 377 | { 378 | 379 | char *parts = strtok(yytext, tok); 380 | temp_time.tm_mon= atoi(parts)-1; 381 | parts = strtok (NULL, tok); 382 | if(parts != NULL) 383 | { 384 | temp_time.tm_mday = atoi(parts); 385 | parts = strtok (NULL, tok); 386 | if(parts != NULL) 387 | temp_time.tm_year = atoi(parts)-1900; 388 | } 389 | } 390 | void parseDayMonthStr(char *text, char *tok) 391 | { 392 | 393 | char *parts = strtok(yytext, tok); 394 | temp_time.tm_mday= atoi(parts); 395 | parts = strtok (NULL, tok); 396 | if(parts != NULL) 397 | { 398 | temp_time.tm_mon = atoi(parts)-1; 399 | parts = strtok (NULL, tok); 400 | if(parts != NULL) 401 | temp_time.tm_year = atoi(parts)-1900; 402 | } 403 | } 404 | 405 | void parseYearMonthDayStr(char *text, char *tok) 406 | { 407 | 408 | char *parts = strtok(yytext, tok); 409 | temp_time.tm_year= atoi(parts)-1900; 410 | parts = strtok (NULL, tok); 411 | if(parts != NULL) 412 | { 413 | temp_time.tm_mon = atoi(parts)-1; 414 | parts = strtok (NULL, tok); 415 | if(parts != NULL) 416 | temp_time.tm_mday = atoi(parts); 417 | } 418 | } 419 | 420 | void concatUnusedString(char *strnew) 421 | { 422 | 423 | size_t len = 0; 424 | char *str = ""; 425 | if(unusedText!=NULL) 426 | { 427 | 428 | len = strlen(unusedText); /* could use 'sizeof' instead of strlen in this example */ 429 | str = unusedText; 430 | } 431 | 432 | char *str2 = malloc(len + strlen(strnew) + 1 ); 433 | strcpy(str2, str); 434 | strcat (str2, strnew); 435 | 436 | free(unusedText); 437 | unusedText = str2; 438 | 439 | } 440 | 441 | int yywrap(void) { 442 | return 1; 443 | } 444 | -------------------------------------------------------------------------------- /parseIt.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include "TimeParser.h" 4 | 5 | int yylex(void); 6 | void yyerror(char *); 7 | 8 | %} 9 | 10 | 11 | 12 | %union 13 | { 14 | int number; 15 | char *string; 16 | } 17 | 18 | %token INTEGER DTPOSITION DAYOFWEEK MONTHNUM GENERALTIME MODIFIERS FROM LASTNEXT BEFOREAFTER HENCEAGO IN THIS NOW INTHE PLUS SETDATE 19 | %token MONTH PASTMODIFIER WHENTIME TYPENAMES DTMODIFIERS ARTICLEPREP MILITARYTIME 20 | 21 | %% 22 | 23 | 24 | program: { setCurrentTime(); 25 | //NSLog(@"Parsing Started"); 26 | } 27 | | 28 | program expr { 29 | 30 | 31 | 32 | time_t curtime2 = mktime(str_time); 33 | 34 | // NSLog(@"UNIXTIMESTAMP = %d \n", curtime2); 35 | // NSLog(@"perty time = %s\n", asctime(str_time)); 36 | // NSLog(@"modifier num = %d", *mymodifier.changePointer); 37 | 38 | $$ = curtime2; 39 | 40 | for(int i=0; i<9; i++){ 41 | fromChangeAmount[i] += changeAmount[i]; 42 | changeAmount[i] = 0; 43 | } 44 | 45 | set_time.tm_sec = temp_time.tm_sec >=0 ? temp_time.tm_sec : set_time.tm_sec; 46 | set_time.tm_min = temp_time.tm_min >=0 ? temp_time.tm_min : set_time.tm_min; 47 | set_time.tm_hour = temp_time.tm_hour >=0 ? temp_time.tm_hour : set_time.tm_hour; 48 | set_time.tm_mday = temp_time.tm_mday >=0 ? temp_time.tm_mday : set_time.tm_mday; 49 | set_time.tm_wday = temp_time.tm_wday >= 0 ? temp_time.tm_wday : set_time.tm_wday; 50 | set_time.tm_mon = temp_time.tm_mon >= 0 ? temp_time.tm_mon : set_time.tm_mon; 51 | set_time.tm_year = temp_time.tm_year >= 0 ? temp_time.tm_year : set_time.tm_year; 52 | 53 | 54 | // printf("temp time = %s", asctime(&temp_time)); 55 | 56 | temp_time.tm_sec = -1; 57 | temp_time.tm_min = -1; 58 | temp_time.tm_hour = -1; 59 | temp_time.tm_mday = -1; 60 | temp_time.tm_wday = -1; 61 | temp_time.tm_mon = -1; 62 | temp_time.tm_year = -1; 63 | 64 | finalSpecAmount[0] = specAmount[0] != 0 ? specAmount[0] : finalSpecAmount[0]; 65 | finalSpecAmount[1] = specAmount[1] != 0 ? specAmount[1] : finalSpecAmount[1]; 66 | finalSpecAmount[2] = specAmount[2] != 0 ? specAmount[2] : finalSpecAmount[2]; 67 | 68 | 69 | // NSLog(@"topLevel change amount = %s\n", join_strings(fromChangeAmount, ",", 9)); 70 | // NSLog(@"topLevel spec amount = %s\n", join_strings(fromModifier.specAmount, ",", 3)); 71 | // NSLog(@"topLevel spec value = %s\n", join_strings(fromModifier.specValue, ",", 3)); 72 | } 73 | 74 | ; 75 | 76 | expr: 77 | 78 | expr BEFOREAFTER 79 | { 80 | 81 | // NSLog(@"inside before = %s\n", join_strings(fromModifier.amount, ",", 9)); 82 | 83 | if($2 == -1) 84 | { 85 | int i=0; 86 | for(i=0; i < 8; i++) 87 | { 88 | mymodifier.amount[i] = mymodifier.amount[i]>0 ? -mymodifier.amount[i] : mymodifier.amount[i]; 89 | } 90 | for(int j=0; j<3; j++) 91 | { 92 | if(mymodifier.specValue[j] >=0) 93 | mymodifier.specAmount[j] *= -1; 94 | } 95 | } 96 | int j=0; 97 | for(j=0; j<3; j++) 98 | { 99 | if(mymodifier.specValue[j] >= 0) 100 | { 101 | fromModifier.specAmount[j] = mymodifier.specAmount[j]; 102 | fromModifier.specValue[j] = mymodifier.specValue[j]; 103 | mymodifier.specValue[j] = -1; 104 | mymodifier.specAmount[j] = 0; 105 | } 106 | } 107 | int i = 0; 108 | for(i=0; i < 8; i++) 109 | { 110 | fromChangeAmount[i] += mymodifier.amount[i]; 111 | mymodifier.amount[i] = 0; 112 | } 113 | } 114 | | 115 | FROM expr { 116 | 117 | setFinalTime(&temp_time, specAmount, changeAmount); 118 | time_t tempTime = mktime(str_time); 119 | 120 | str_time= localtime(&tempTime); 121 | 122 | for(int i=0; i<7; i++){ 123 | *timePointer[i] += mymodifier.amount[i]; 124 | mymodifier.amount[i] = 0; 125 | } 126 | 127 | if(mymodifier.specValue[1]) 128 | { 129 | // NSLog(@"spec amount in from= %d", mymodifier.specAmount[1]); 130 | setDayOfWeek(mymodifier.specValue[1], mymodifier.specAmount); 131 | mymodifier.specValue[1] = -1; 132 | mymodifier.specAmount[1] = 0; 133 | } 134 | 135 | } 136 | | 137 | SETDATE { } 138 | | 139 | ARTICLEPREP {} 140 | | 141 | IN { } 142 | | 143 | THIS { } 144 | | 145 | NOW { } 146 | | 147 | INTEGER { /******** ex. 6 (means the time if only a number) ******/ 148 | 149 | if(fromChangeAmount[8] && fromChangeAmount[8] != 'm') 150 | { 151 | if($1 < 12) $1 += 12; 152 | else if($1 == 12) $1 = 0; 153 | } 154 | temp_time.tm_hour = $1; 155 | temp_time.tm_min = 0; 156 | temp_time.tm_sec = 0; 157 | } 158 | 159 | | 160 | MONTHNUM 161 | { /***** ex. "June" ******/ 162 | temp_time.tm_mon = $1; 163 | temp_time.tm_mday = 1; 164 | } 165 | | 166 | DAYOFWEEK /***** ex. "Friday" *****/ 167 | { 168 | if($1==-1) changeAmount[3] = -1; 169 | else if($1 == 8) changeAmount[3] = 1; 170 | else if($1 == 0) changeAmount[3] = 0; 171 | else 172 | temp_time.tm_wday = $1-1; 173 | } 174 | | 175 | IN INTEGER 176 | { 177 | if($2 > 1000) 178 | temp_time.tm_year = $2-1900; 179 | $$ = 6; 180 | } 181 | | 182 | 183 | IN MILITARYTIME 184 | { 185 | char *timeparts = strtok($2, ":"); 186 | char thedate[5] = ""; 187 | int actualdate= 0; 188 | strncat(thedate, timeparts, 2); 189 | timeparts = strtok (NULL, ":"); 190 | strncat(thedate, timeparts, 2); 191 | thedate[4] = '\0'; 192 | actualdate= atoi(thedate); 193 | 194 | temp_time.tm_year = actualdate-1900; 195 | $$ = 6; 196 | } 197 | | 198 | IN INTEGER TYPENAMES { /******** ex. "in 3 days" or "in 5 weeks" or "in 8 hours" ******/ 199 | if($3 == 4){ 200 | $3 = 3; 201 | $2 *= 7; 202 | } 203 | changeAmount[$3] = $2; 204 | } 205 | | 206 | TYPENAMES { 207 | if ($1 == 3) 208 | { 209 | mymodifier.amount[$1] += 1; 210 | } 211 | } 212 | | 213 | 214 | INTEGER TYPENAMES { /******** ex. "3 days" mostly used with "before" or "after" as in "3 days before yesterday" ****/ 215 | if($2 == 4) 216 | { 217 | $1 *= 7; 218 | $2 = 3; 219 | } 220 | // changeAmount[$2] = $1; 221 | mymodifier.amount[$2] += $1; 222 | 223 | } 224 | 225 | | 226 | 227 | INTEGER TYPENAMES HENCEAGO { /******* ex. "3 days ago" or "5 years hence" ******/ 228 | if($2 == 4){ 229 | $1 *= 7; 230 | $2 = 3; 231 | } 232 | changeAmount[$2] = $1*$3; 233 | } 234 | 235 | | 236 | INTEGER generalTimes /******* ex. "3 mornings" mainly used with "before" or "after" *****/ 237 | { 238 | mymodifier.amount[3] += $1; 239 | } 240 | | 241 | INTEGER generalTimes HENCEAGO /**** ex. "3 mornings ago" or "5 afternoons hence" *****/ 242 | { 243 | changeAmount[3] = $1*$3; 244 | } 245 | 246 | | 247 | LASTNEXT TYPENAMES { /********** ex. "Last Month" or "Next Year" *******/ 248 | $$ = 0; 249 | if($2 == 4){ 250 | $2 = 7; 251 | $$ = 4; 252 | } 253 | changeAmount[$2] = $1; 254 | } 255 | | 256 | LASTNEXT DAYOFWEEK { /******** ex. "last friday" or "next friday" ******/ 257 | if($2 > 0 && $2 < 8) 258 | temp_time.tm_wday = $2-1; 259 | specAmount[1] = $1; 260 | if($1 >0) 261 | changeAmount[7] = $1; 262 | } 263 | 264 | | 265 | LASTNEXT MONTHNUM /******** ex. "last May" or "next May" ******/ 266 | { 267 | if($1 >0) $2 += 12; 268 | temp_time.tm_mon = $2; 269 | specAmount[0] = $1; 270 | } 271 | 272 | | 273 | INTEGER INTHE generalTimes { /******** ex. " 6 in the morning" ******/ 274 | 275 | if($3 > 0) 276 | { 277 | if($1 < 12) 278 | temp_time.tm_hour = $1+12; 279 | 280 | else if($1 == 12) 281 | temp_time.tm_hour = 0; 282 | } 283 | else 284 | { 285 | temp_time.tm_hour = $1; 286 | } 287 | 288 | 289 | specAmount[2] = 1; 290 | } 291 | | 292 | INTEGER THIS generalTimes { /******** ex. " 6 this morning" ******/ 293 | 294 | if($3 > 0) 295 | { 296 | if($1 < 12) 297 | temp_time.tm_hour = $1+12; 298 | else if($1 == 12) 299 | temp_time.tm_hour = 0; 300 | } 301 | else 302 | { 303 | temp_time.tm_hour = $1; 304 | } 305 | specAmount[2] = 0; 306 | } 307 | | 308 | 309 | INTHE generalTimes { /******** ex. "in the morning" ******/ 310 | // NSLog(@"just in the morning"); 311 | specAmount[2] = 1; 312 | } 313 | | 314 | whenTime { } 315 | 316 | | 317 | 318 | whenTime INTHE generalTimes /******* 4:30 in the afternoon *******/ 319 | { 320 | if($3 > 0) 321 | { 322 | if(temp_time.tm_hour < 12) 323 | temp_time.tm_hour += 12; 324 | 325 | else if(temp_time.tm_hour == 12) 326 | temp_time.tm_hour = 0; 327 | } 328 | specAmount[2] = 1; 329 | } 330 | | 331 | generalTimes {} /****** ex. "morning" *******/ 332 | | 333 | 334 | LASTNEXT generalTimes /******* ex. "last night" **********/ 335 | { 336 | changeAmount[3] = $1; 337 | } 338 | | 339 | 340 | whenTime LASTNEXT generalTimes /****** ex. "7:30 last night" ********/ 341 | { 342 | changeAmount[3] = $2; 343 | specAmount[2] = 0; 344 | } 345 | | 346 | whenTime LASTNEXT DAYOFWEEK /****** ex. "7:30pm last Tuesday" ********/ 347 | { 348 | if($3 > 0 && $3 < 8) 349 | temp_time.tm_wday = $3-1; 350 | specAmount[1] = $2; 351 | 352 | } 353 | | 354 | whenTime THIS generalTimes /********* 3:30 this morning *********/ 355 | { 356 | if($3 > 0) 357 | { 358 | if(temp_time.tm_hour < 12) 359 | temp_time.tm_hour += 12; 360 | 361 | else if(temp_time.tm_hour == 12) 362 | temp_time.tm_hour = 0; 363 | } 364 | specAmount[2] = 0; 365 | } 366 | 367 | | 368 | DTPOSITION TYPENAMES expr /******* ex. "4th day last week", "3rd month next year" *******/ 369 | { 370 | switch($2) 371 | { 372 | case 3: 373 | { 374 | if($3 == 4) $1 -=1; 375 | else if($3 == 6) temp_time.tm_mon = 0; 376 | temp_time.tm_mday = $1; 377 | } 378 | break; 379 | case 4: 380 | { 381 | temp_time.tm_mday = 1; 382 | specAmount[1] = $1-1; 383 | } 384 | break; 385 | case 5: 386 | temp_time.tm_mon = $1-1; 387 | break; 388 | } 389 | } 390 | | 391 | DTPOSITION DAYOFWEEK expr /******* ex. "4th saturday next month", "3rd wed. in November" *******/ 392 | { 393 | if($2>0 && $2 < 8) 394 | { 395 | temp_time.tm_mday = 0; 396 | temp_time.tm_wday = $2-1; 397 | specAmount[1] = $1; 398 | } 399 | } 400 | 401 | 402 | | 403 | 404 | specAmountDayOrMonth { //NSLog(@"spec amount"); 405 | } 406 | 407 | 408 | ; 409 | 410 | 411 | 412 | 413 | specAmountDayOrMonth : 414 | INTEGER DAYOFWEEK /**** ex. "3 Fridays" used with "before or after" "2 tues after next thurs" ****/ 415 | { 416 | if($2 > 0 && $2 < 8) 417 | { 418 | mymodifier.specAmount[1] = $1; 419 | mymodifier.specValue[1] = $2-1; 420 | } 421 | } 422 | | 423 | INTEGER DAYOFWEEK HENCEAGO { /***** ex. "3 fridays hence" ****/ 424 | if($2 > 0 && $2 < 8) 425 | temp_time.tm_wday = $2-1; 426 | specAmount[1] = $1*$3; 427 | } 428 | | 429 | INTEGER MONTHNUM HENCEAGO { /***** ex. "3 Junes ago" ******/ 430 | temp_time.tm_mon = $2; 431 | specAmount[0] = $1*$3; 432 | } 433 | | 434 | INTEGER MONTHNUM INTEGER /**** ex. "3 june 1997" ******/ 435 | { 436 | temp_time.tm_mon = $2; 437 | temp_time.tm_mday = $1; 438 | if($3 < 1000) 439 | { 440 | if($3 < 15) 441 | $3 += (2000-1900); 442 | } 443 | temp_time.tm_year = $3; 444 | } 445 | | 446 | INTEGER MONTHNUM MILITARYTIME /**** ex. "3 june 2011" (had to do another to differentiate between military time and Year) ******/ 447 | { 448 | char *timeparts = strtok($3, ":"); 449 | char thedate[5] = ""; 450 | int actualdate= 0; 451 | strncat(thedate, timeparts, 2); 452 | timeparts = strtok (NULL, ":"); 453 | strncat(thedate, timeparts, 2); 454 | thedate[4] = '\0'; 455 | actualdate= atoi(thedate); 456 | 457 | temp_time.tm_mon = $2; 458 | temp_time.tm_mday = $1; 459 | temp_time.tm_year = actualdate-1900; 460 | } 461 | | 462 | MONTHNUM INTEGER /**** ex. "june 3" ******/ 463 | { 464 | temp_time.tm_mon = $1; 465 | if($2 >1900) 466 | temp_time.tm_year = $2-1900; 467 | else 468 | temp_time.tm_mday = $2; 469 | 470 | } 471 | | 472 | MONTHNUM MILITARYTIME /**** ex. "june 2008" ******/ 473 | { 474 | char *timeparts = strtok($2, ":"); 475 | char thedate[5] = ""; 476 | int actualdate= 0; 477 | strncat(thedate, timeparts, 2); 478 | timeparts = strtok (NULL, ":"); 479 | strncat(thedate, timeparts, 2); 480 | thedate[4] = '\0'; 481 | actualdate= atoi(thedate); 482 | 483 | temp_time.tm_mon = $1; 484 | temp_time.tm_year = actualdate-1900; 485 | } 486 | | 487 | MONTHNUM DTPOSITION /**** ex. "june 3rd" ******/ 488 | { 489 | temp_time.tm_mon = $1; 490 | temp_time.tm_mday = $2; 491 | } 492 | | 493 | MONTHNUM DTPOSITION INTEGER /***** ex. "june 3rd 1997" *****/ 494 | { 495 | if($3 < 1000) 496 | { 497 | if($3 < 15) 498 | $3 += (2000-1900); 499 | } 500 | temp_time.tm_mon = $1; 501 | temp_time.tm_mday = $2; 502 | temp_time.tm_year = $3; 503 | } 504 | | 505 | MONTHNUM INTEGER INTEGER /**** ex. "june 3 1997" ******/ 506 | { 507 | // NSLog(@"date = %d", $3); 508 | if($3 < 1000) 509 | { 510 | if($3 < 15) 511 | $3 += (2000-1900); 512 | } 513 | temp_time.tm_mon = $1; 514 | temp_time.tm_mday = $2; 515 | temp_time.tm_year = $3; 516 | } 517 | | 518 | MONTHNUM DTPOSITION MILITARYTIME 519 | { 520 | char *timeparts = strtok($3, ":"); 521 | char thedate[5] = ""; 522 | int actualdate= 0; 523 | strncat(thedate, timeparts, 2); 524 | timeparts = strtok (NULL, ":"); 525 | strncat(thedate, timeparts, 2); 526 | thedate[4] = '\0'; 527 | actualdate= atoi(thedate); 528 | 529 | 530 | temp_time.tm_mon = $1; 531 | temp_time.tm_mday = $2; 532 | temp_time.tm_year = actualdate-1900; 533 | } 534 | | 535 | MONTHNUM INTEGER MILITARYTIME 536 | { 537 | char *timeparts = strtok($3, ":"); 538 | char thedate[5] = ""; 539 | int actualdate= 0; 540 | strncat(thedate, timeparts, 2); 541 | timeparts = strtok (NULL, ":"); 542 | strncat(thedate, timeparts, 2); 543 | thedate[4] = '\0'; 544 | actualdate= atoi(thedate); 545 | 546 | temp_time.tm_mon = $1; 547 | temp_time.tm_mday = $2; 548 | temp_time.tm_year = actualdate-1900; 549 | } 550 | ; 551 | 552 | 553 | generalTimes: /****** ex. "morning", "afternoon" ********/ 554 | GENERALTIME { 555 | $$ = 1; 556 | if(temp_time.tm_hour < 0) 557 | { 558 | switch($1) 559 | { 560 | case 'm': 561 | { 562 | temp_time.tm_hour = 7; 563 | $$ = 0; 564 | } 565 | break; 566 | case 'a': 567 | { 568 | temp_time.tm_hour = 15; 569 | } 570 | break; 571 | case 'e': 572 | { 573 | temp_time.tm_hour = 18; 574 | } 575 | break; 576 | case 'n': 577 | { 578 | temp_time.tm_hour = 21; 579 | } 580 | break; 581 | // addition for tonight 582 | case 't': 583 | { 584 | temp_time.tm_hour = 21; 585 | } 586 | break; 587 | } 588 | } 589 | else if($1== 'm') $$ = 0; 590 | 591 | temp_time.tm_min = temp_time.tm_min >=0 ? temp_time.tm_min : 0; 592 | temp_time.tm_sec = temp_time.tm_sec >=0 ? temp_time.tm_sec : 0; 593 | changeAmount[8] = $1; 594 | } 595 | 596 | ; 597 | 598 | whenTime : /****** ex. "3:00" or "3pm" or "1830" ****/ 599 | MILITARYTIME 600 | { 601 | char *timeparts = strtok($1, ":"); 602 | temp_time.tm_hour= atoi(timeparts); 603 | timeparts = strtok (NULL, ":"); 604 | temp_time.tm_min= atoi(timeparts); 605 | temp_time.tm_sec = 0; 606 | } 607 | | 608 | WHENTIME { 609 | 610 | char *timeparts = strtok($1, ":"); 611 | temp_time.tm_hour= atoi(timeparts); 612 | temp_time.tm_min = 0; 613 | temp_time.tm_sec = 0; 614 | timeparts = strtok (NULL, ":"); 615 | while (timeparts != NULL) 616 | { 617 | if(timeparts[0]=='a') 618 | { 619 | if(temp_time.tm_hour == 12) 620 | temp_time.tm_hour = 0; 621 | } 622 | else if(timeparts[0]=='p') 623 | { 624 | if(temp_time.tm_hour < 12) 625 | temp_time.tm_hour += 12; 626 | } 627 | else 628 | { 629 | temp_time.tm_min = atoi(timeparts); 630 | } 631 | timeparts = strtok (NULL, ":"); 632 | } 633 | } 634 | 635 | ; 636 | 637 | %% 638 | 639 | void yyerror(char *s) { 640 | // NSLog(@"error"); 641 | fprintf(stderr, "%s\n", s); 642 | } 643 | --------------------------------------------------------------------------------