File: input_parser.cpp

package info (click to toggle)
open-amulet 4.3.1-7.1
  • links: PTS
  • area: main
  • in suites: woody
  • size: 7,804 kB
  • ctags: 9,779
  • sloc: cpp: 97,058; sh: 7,698; ansic: 1,881; makefile: 756; lisp: 153; exp: 15
file content (168 lines) | stat: -rw-r--r-- 5,147 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/* ************************************************************************
 *         The Amulet User Interface Development Environment              *
 * ************************************************************************
 * This code was written as part of the Amulet project at                 *
 * Carnegie Mellon University, and has been placed in the public          *
 * domain.  If you are using this code or any part of Amulet,             *
 * please contact amulet@cs.cmu.edu to be put on the mailing list.        *
 * ************************************************************************/

/* This file contains a procedure to parse strings into Amulet types.
   It is used by the inspector and also by scripting.

   Designed and implemented by Brad Myers
*/

#include <am_inc.h>

#include WIDGETS_ADVANCED__H
#include REGISTRY__H


//returns true if input can be parsed as a wanted_type.
//If returns true, then output_value is set with the actual value.
bool Am_Parse_Input_As_Type(Am_String input, Am_Value_Type wanted_type,
			    Am_Value &output_value) {
  Am_ID_Tag type_class = Am_Type_Class (wanted_type);
  switch (type_class) {
  case Am_SIMPLE_TYPE:
    switch(wanted_type) {
    case Am_BOOL: 
      if (input == "true") {
	output_value = true;
	return true;
      }
      else if (input == "false") {
	output_value = false;
	return true;
      }
      //else fall through to the INT case
    case Am_INT:
    case Am_LONG:
    case Am_FLOAT:
    case Am_DOUBLE:  {
      //Am_String_To_Long_Or_Float is defined in widgets_advanced.h
      bool ok = Am_String_To_Long_Or_Float(input, output_value);
      if (ok) {
	if (output_value.type != wanted_type) {
	  if (output_value.type == Am_FLOAT) {
	    if (wanted_type == Am_DOUBLE) {
	      output_value = (double)output_value;
	      return true;
	    }
	    return false; //want int, got float
	  }
	  else if (output_value.type == Am_LONG) { //user provided a long
	    if (wanted_type == Am_BOOL) 
	      output_value = output_value.Valid();
	    else if (wanted_type == Am_INT)
	      output_value = (int)output_value;
	    else if (wanted_type == Am_FLOAT)
	      output_value = (float)output_value;
	    else if (wanted_type == Am_DOUBLE)
	      output_value = (double)output_value;
	    else Am_ERROR("Unknown wanted type " << wanted_type);
	  }
	  else Am_ERROR("Unexpected return type " << output_value.type
			<< " on " << output_value);
	}
	return true;
      }
      else return false;
    }
    case Am_STRING:
      output_value = input;
      return true;
    case Am_CHAR: {
      char* s = input;
      if (strlen(s) == 1) {
	char c = s[0];
	output_value = c;
	return true;
      }
      else return false;
    }
    default:
      return false; //Unsupported simple type (Am_VOIDPTR, Am_PROC, etc.)
    }
    break;
  case Am_METHOD: 
  case Am_WRAPPER:
    if (wanted_type == Am_Value_List::Type_ID()) {
     std::cout << "** Can't edit value lists yet.  Sorry.\n";
      return false;
    }
    else {
      char* s = input;
      if (!strcmp(s, "(0L)") || !strcmp(s, "(NULL)") || !strcmp(s, "0") ||
	  !strncmp(s, "Am_No_", 6)) {
	output_value.type = wanted_type;
	output_value.value.wrapper_value = 0;
	return true;
      }
      if (wanted_type == Am_OBJECT) {
	if (s[0] == '<') { //remove the <> around the name
	  unsigned int i;
	  for (i = 1; i < (strlen(s)-1); i++)
	    s[i-1] = s[i];
	  s[i] = 0;
	}
      }
      const Am_Registered_Type* the_item =
	Am_Get_Named_Item((const char *)input);
      if (the_item != (0L) && the_item->ID() == wanted_type) {
	if (type_class == Am_METHOD)
	  output_value = (Am_Method_Wrapper*)the_item;
	else {
	  Am_Wrapper* wrap = (Am_Wrapper*)the_item;
	  wrap->Note_Reference ();
	  output_value = wrap;
	}
	return true;
      }
      return false;
    }
  case Am_ENUM: {
    Am_Type_Support* ws = Am_Find_Support (wanted_type);
    if (ws) {
      output_value = ws->From_String(input);
      if (output_value.Exists())
	return true;
    }
    return false;
  }
  default:
   std::cerr << "** Unknown type class " << type_class
	 << " on type " << wanted_type <<std::endl <<std::flush;
    return false;
  } //end switch
}
  
bool Am_Parse_Input_As_List_Of_Type(Am_String input, Am_Value_Type wanted_type,
				    Am_Value &output_value) {
  char *s = input;
  if (strncmp(s, "LIST(", 5)) return false; //not a list
  char* real_part = strchr(s, '[');
  real_part++;
 std::cout << "parse " << input << " found real part '" << real_part
       << "'\n" <<std::flush;
  char* token = strtok(real_part, ",]");
 std::cout << "first token `" << token << "'\n" <<std::flush;
  Am_String token_str;
  Am_Value_List return_values;
  bool ok;
  Am_Value sub_value;
  while (token) {
    if (token[0] == ' ') token++;
    token_str = token;
    ok = Am_Parse_Input_As_Type(token_str, wanted_type, sub_value);
   std::cout << "parsing " << token_str << " ok " << ok
	 << " value " << sub_value;
    if (!ok) return false;
    return_values.Add(sub_value);
    token = strtok((0L), ",]");
   std::cout << "next token is `" << token << "'\n" <<std::flush; 
  }
  output_value = return_values;
  return true;
}