1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ******************************************************************************
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Copyright (C) 2005-2007, International Business Machines Corporation and   *
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * others. All Rights Reserved.                                               *
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ******************************************************************************
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdio.h>
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <string.h>
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdlib.h>
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <time.h>
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "wbnf.h"
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Most of this code is meant to test the test code. It's a self test.
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Normally this isn't run.
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define TEST_WBNF_TEST 0
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru///////////////////////////////////////////////////////////
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Constants and the most basic helper classes
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char DIGIT_CHAR[] = "0123456789";
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char WHITE_SPACE[] = {'\t', ' ', '\r', '\n', 0};
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char ALPHABET[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char SPECIAL[] = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic inline UBool isInList(const char c /*in*/, const char list[] /*in*/){
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char * p = list;
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (;*p != 0 && *p != c; p++);
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return *p?TRUE:FALSE;
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic inline UBool isDigit(char c) {return isInList(c, DIGIT_CHAR);}
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic inline UBool isWhiteSpace(char c) {return isInList(c, WHITE_SPACE);}
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic inline UBool isAlphabet(char c) {return isInList(c, ALPHABET);}
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic inline UBool isSpecialAsciiChar(char c) {return isInList(c,SPECIAL);}
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru///////////////////////////////////////////////////////////
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Helper classes
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass Buffer_byte{
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Utility class, can be treated as an auto expanded array. no boundary check.
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    typedef char byte;
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    byte * start;
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    byte * current;
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int buffer_size; // size unit is byte
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inline int content_size(){return current - start;} // size unit is byte
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inline void expand(int add_size = 100){ // size unit is byte
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int new_size = buffer_size + add_size;
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int cs_snap = content_size();
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        start = (byte *) realloc(start, new_size);   // may change the value of start
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        current = start + cs_snap;
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        memset(current, 0, add_size);
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        buffer_size = new_size;
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inline void expand_to(int size){
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int r = size - buffer_size;
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (r > 0) {
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            expand(r);  // simply expand, no block alignment
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_byte(const Buffer_byte &);
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_byte & operator = (const Buffer_byte &);
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_byte():start(NULL),current(start),buffer_size(0){
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        expand();
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ~Buffer_byte(){
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        free(start);
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inline void reset(){
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        start != NULL ? memset(start, 0, buffer_size) : 0;
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        current = start;
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Using memory copy method to append a C array to buffer,
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inline void append(const void * c, int size){ // size unit is byte
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        expand_to(content_size() + size) ;
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        memcpy(current, c, size);
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        current = current + size;
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    byte * buffer(){
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return start;
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  The class(es) try to work as bulid-in array, so it overloads these two operators
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    operator type *();
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    type & operator[];
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  The first is used to auto type convert, the latter is used to select member.
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  A small trick is the class does not overload the address-of operator. This
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  behavior is different from bulid-in array, but it give us the opportunity
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  to get the address of the class itself.
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//template<typename type>
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    class BUFFER{
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//       typedef BUFFER name;
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define BUFFER(type, name)\
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    class name {\
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    private:\
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru       Buffer_byte buf;\
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    public:\
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        name & reset() {buf.reset(); return *this;}\
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        name & append(type c) {buf.append(&c, sizeof(type)); return *this;}\
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        name & append_array(const type * p, int size) {buf.append(p, sizeof(type)*size); return *this;}\
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        type & operator [] (int i) { return ((type *) buf.buffer())[i];}\
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        operator type *(){return (type *) buf.buffer();} \
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int content_size(){return buf.content_size() / sizeof(type);}\
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass Pick{
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* The Pick is the basic language generator element*/
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // generate a string accroding the syntax
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Return a null-terminated c-string. The buffer is owned by callee.
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const char* next() = 0;
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual ~Pick(){};
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//typedef BUFFER<char> Buffer_char;
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//typedef BUFFER<int> Buffer_int;
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//typedef BUFFER<Pick *> Buffer_pPick;
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruBUFFER(char, Buffer_char);
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruBUFFER(int, Buffer_int);
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruBUFFER(Pick *, Buffer_pPick);
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass SymbolTable{
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Helper class.
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* It's a mapping table between 'variable name' and its 'active Pick object'
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_char  name_buffer;   // var names storage space
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_int   names;         // points to name (offset in name_buffer)
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_pPick refs;          // points to Pick
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int get_index(const char *const var_name){
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int len = names.content_size();
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (int i=0; i< len; i++){
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (strcmp(var_name, name_buffer + names[i]) == 0){
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return i;
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return -1;
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    enum RESULT {EMPTY, NO_VAR, NO_REF, HAS_REF};
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    RESULT find(const char *const var_name /*[in] c-string*/, Pick * * ref = NULL /*[out] Pick* */){
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!var_name) return EMPTY; // NULL name
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int i = get_index(var_name);
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (i == -1){
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NO_VAR;   // new name
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!refs[i]){  // exist name, no ref
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NO_REF;
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (ref) {
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *ref = refs[i];
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return HAS_REF;   // exist name, has ref
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void put(const char *const var_name, Pick *const var_ref = NULL){
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int i = get_index(var_name);
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        switch(find(var_name)){
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case EMPTY:    // NULL name
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case NO_VAR:    // new name
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int offset;
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset = name_buffer.content_size();
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                name_buffer.append_array(var_name, strlen(var_name) + 1);
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                names.append(offset);
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                refs.append(var_ref);
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case NO_REF:    // exist name, no ref
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                refs[i] = var_ref;    // link definition with variable
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case HAS_REF:    // exist name, has ref
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (var_ref){
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    refs[i] = var_ref;
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            default:
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ; // ASSERT(FALSE);
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool is_complete(){
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int n = names.content_size();
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (int i=0; i<n; ++i){
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (refs[i] == NULL){
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return FALSE;
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return TRUE;
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void reset(){
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        names.reset();
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        name_buffer.reset();
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // release memory here
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int s = refs.content_size();
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (int i=0; i < s; i++){
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete refs[i]; // TOFIX: point alias/recursion problem
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        refs.reset();
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ~SymbolTable(){
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        reset();
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Document of class Escaper
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ATTENTION:
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// From http://icu-project.org/userguide/Collate_Customization.html.
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// We get the precedence of escape/quote operations
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//     (highest) 1. backslash               \
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//               2. two single quotes       ''
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//               3. quoting                 ' '
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ICU Collation should accept following as the same string.
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 1)  'ab'c        _
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 2)  a\bc          \
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 3)  a'b'\c        |- They are equal.
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 4)  abc          _/
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// From "two single quotes", we have following deductions
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    D1. empty quoting is illgal. (obviously)
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    D2. no contact operation between two quotings
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//              '.''.'      is not ..   it is .'.
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    D3. "two single quotes" cannot contact two quoting simultaneously
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//              '..''''.'   is not ..'. it is ..''.
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//       NOTICE:
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//        "two single quotes" can contact before one quoting
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//              '''.'       is '.
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//        "two single quotes" can literally contact after one quoting
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//        But, from syntax, it's one quoting including a "two single quotes"
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//              '.'''       is .'
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    D4. "two single quotes" cannot solely be included in quoting
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//              ''''        is not '    it is ''
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//       NOTICE:  These are legal
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//              '.''.'      is .'.
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//              '.'''       is .'
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//                 dicision
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//                    /\
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//                   /__\
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//      output buffer    input buffer
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// To make our dicision (within an atom operation) without caring input and output buffer,
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// following calling pattern (within an atom operation) shall be avoided
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    P1 open_quoting()  then close_quoting()    (direct violation)   D1
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    P2 close_quoting() then open_quoting()     (direct violation)   D2
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    P3 empty open_quoting()                    (indirect violation) D1, D4
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    P4 empty close_quoting()                   (indirect violation) D2, D3
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    P5 open_quoting()  then two single quotes  (indirect violation) D4
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    P6 close_quoting() then two single quotes  (indirect violation) D3
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// two single quotes escaping will not open_ or close_ quoting()
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// The choice will not lose some quoing forms.
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// For open_quoting(),
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// we may get this form quoting     '''         P5
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// It may raise a bug               ''''x
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// If we expect
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//      '''.'       let the next char open the quoting
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//      '.''.'      the quoting is already opened by preceding char
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// For close_quoting()
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// we will get this form quoting    '.'''       P6
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// It may raise a bug               '.''''.'
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// If we expect
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//      '.'''\.     let the next char close the quoting
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//      '.''''.'    the expectation is wrong!  using  '.'\''.' instead
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// It's a hard work to re-adjust generation opportunity for various escaping form.
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// We just simply ignore it.
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass Escaper{
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    enum CHOICE {YES, NO, RAND};
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    enum ESCAPE_FORM {BSLASH_ONLY, QUOTE_ONLY, QUOTE_AND_BSLAH, RAND_ESC};
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    class Bool{ // A wrapper class for CHOICE, to auto adapter UBool class
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        private:
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            const CHOICE tag;
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        public:
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            Bool(CHOICE flag=RAND):tag(flag){}
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            operator UBool() {   // conversion operator
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return tag == RAND ? rand()%2 : tag == YES;
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                //if (tag == RAND){
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                //    return rand()%2 == 1;
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                //} else {
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                //    return tag == YES ? TRUE : FALSE;
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                //}
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    };
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Escaper(CHOICE escapeLiteral = RAND,
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        CHOICE twoQuotesEscape = RAND,
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ESCAPE_FORM escapeForm = RAND_ESC):
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        escape_form(escapeForm),
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        escape_literal(escapeLiteral),
334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        two_quotes_escape(twoQuotesEscape),
335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        is_quoting(FALSE){}
336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_char str;
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ESCAPE_FORM escape_form;
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Bool escape_literal;
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Bool two_quotes_escape;
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool quote_escape;
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool bslash_escape;
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool is_quoting;
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void set_options(){
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ESCAPE_FORM t = escape_form == RAND_ESC ? (ESCAPE_FORM) (rand()%3) : escape_form;
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        switch (t){
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case BSLASH_ONLY :
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    bslash_escape = TRUE; quote_escape = FALSE; break;
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case QUOTE_ONLY:
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    bslash_escape = FALSE;quote_escape = TRUE;  break;
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case QUOTE_AND_BSLAH:
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    bslash_escape = TRUE; quote_escape = TRUE;  break;
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                default:
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ;// error
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void reset(){
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        str.reset();
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        is_quoting = FALSE;
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inline void open_quoting(){
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(is_quoting){
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // do nothing
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str.append('\'');
369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            is_quoting = TRUE;
370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inline void close_quoting(){
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(is_quoting){
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str.append('\'');
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            is_quoting = FALSE;
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // do nothing
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // str  [in]    null-terminated c-string
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void append(const char * strToAppend){
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for(;*strToAppend != 0; strToAppend++){
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            append(*strToAppend);
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inline void append(const char c){
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        set_options();
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (c == '\\'){
392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            quote_escape ? open_quoting() : close_quoting();
393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            //bslash_escape always true here
394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str.append('\\');
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str.append('\\');
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (c == '\''){
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (two_quotes_escape){     // quoted using two single quotes
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // See documents in anonymous.design
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                str.append('\'');
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                str.append('\'');
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else{
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                quote_escape ? open_quoting() : close_quoting();
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                //bslash_escape always true here
404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                str.append('\\');
405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                str.append('\'');
406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (isSpecialAsciiChar(c) || isWhiteSpace(c)){
408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            quote_escape  ? open_quoting()   : close_quoting();
409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (bslash_escape) str.append('\\');
410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str.append(c);
411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else { //if (isAlphabet(c) || isDigit(c) || TRUE){ // treat others as literal
412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (escape_literal){
413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                quote_escape  ? open_quoting()   : close_quoting();
414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (bslash_escape)  str.append('\\');
415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                str.append(c);
416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                close_quoting();
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                str.append(c);
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Return a null-terminate c-string. The buffer is owned by callee.
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char * operator()(const char * literal /*c-string*/){
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        str.reset();
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for(;*literal != 0; literal++){
428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            append(*literal);
429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        close_quoting();    // P4 exception, to close whole quoting
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return str;
432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass WeightedRand{
436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Return a random number in [0, size)
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Every number has different chance (aka weight) to be selected.
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_int weights;
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    double total;
441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    WeightedRand(const WeightedRand &);
442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    WeightedRand & operator = (const WeightedRand &);
443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    WeightedRand(Buffer_int * weight_list = NULL, int size = 0){
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if ( weight_list == NULL){
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (int i=0; i<size; ++i) weights.append(DEFAULT_WEIGHT);
447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int s = weight_list->content_size();
449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (s < size){
450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                weights.append_array( (*weight_list),s);
451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                for (int i=s; i<size; ++i) weights.append(DEFAULT_WEIGHT);
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else { // s >= size
453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                weights.append_array( (*weight_list),size);
454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        total = 0;
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int c = weights.content_size();
458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (int i=0; i<c; ++i){
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            total += weights[i];
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void append(int weight){
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        weights.append(weight);
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        total += weight;
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Give a random number with the consideration of weight.
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Every random number is associated with a weight.
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // It identifies the chance to be selected,
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // larger weight has more chance to be selected.
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //  ______________________   every slot has equal chance
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //  [____][_][___][______]   each item has different slots, hence different chance
477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //
478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //  The algorithms to generate the number is illustrated by preceding figure.
480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //  First, a slot is selected by rand(). Then we translate the slot to corresponding item.
481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int next(){
483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // get a random in [0,1]
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        double reference_mark = (double)rand() / (double)RAND_MAX;
485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // get the slot's index, 0 <= mark <= total;
487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        double mark = total * reference_mark;
488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // translate the slot to corresponding item
490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int i=0;
491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (;;){
492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            mark -= weights[i];  // 0 <= mark <= total
493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (mark <= 0)
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            i++;
496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return i;
498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru///////////////////////////////////////////////////////////
502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// The parser result nodes
504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass Literal : public Pick {
507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const char* next(){
509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return str;
510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Literal(const char * s /*c-string*/){
512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        str.append_array(s, strlen(s) + 1);
513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_char str; //null-terminated c-string
516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass Variable : public Pick {
519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Variable(SymbolTable * symbols, const char * varName, Pick * varRef = NULL){
521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        this->var_name.append_array(varName, strlen(varName) + 1);
522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if ((symbol_table = symbols)){
523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            symbol_table->put(varName, varRef);
524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    operator const char *(){
528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return var_name;
529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const char* next(){
532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (symbol_table){
533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            Pick * var_ref = NULL;
534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            symbol_table->find(var_name, &var_ref);
535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (var_ref) {
536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return var_ref->next();
537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return "";  // dumb string
540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_char var_name;
543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SymbolTable * symbol_table;
544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass Quote : public Pick{
547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Quote(Pick & base):item(base),e(Escaper::NO, Escaper::NO, Escaper::BSLASH_ONLY){
549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const char* next(){
551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return e(item.next());
552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Pick & item;
555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_char str;
556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Escaper e;
557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass Morph : public Pick{
561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruThe difference between morph and an arbitrary random string is that
563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querua morph changes slowly. When we build collation rules, for example,
564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruit is a much better test if the strings we use are all in the same
565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru'neighborhood'; they share many common characters.
566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Morph(Pick & base):item(base){}
569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const char* next(){
571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        current.reset();
572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char * s = item.next();
573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        current.append_array(s, strlen(s) + 1);
574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if  (last.content_size() == 0) {
575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str.reset();
576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            last.reset();
577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str.append_array(current, current.content_size());
578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            last.append_array(current, current.content_size());
579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            morph();
581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return str;
583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Pick & item;
586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_char str;
587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_char last;
588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_char current;
589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char * p_last;
591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char * p_curr;
592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void copy_curr(){
594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (*p_curr) {
595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str.append(*p_curr);
596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            p_curr++;
597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void copy_last(){
601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (*p_last) {
602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str.append(*p_last);
603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            p_last++;
604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // copy 0, 1, or 2 character(s) to str
608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void copy(){
609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        static WeightedRand wr(& Buffer_int().append(DEFAULT_WEIGHT * 10), 5);
610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        switch (wr.next()){
612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case 0: // copy last  -- has 10 times chance than others
613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                copy_last();
614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case 1: // copy both
616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                copy_curr();
617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                copy_last();
618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case 2: // copy both
620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                copy_last();
621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                copy_curr();
622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case 3:
624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                copy_curr();
625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case 4:  // copy nothing
627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            default:
629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // ASSERT(FALSE);
630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ;
631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void morph(void){
635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int min = strlen(last);
636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int max = strlen(current);
637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (min > max){
638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int temp  = min;
639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            min = max;
640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            max = temp;
641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int len = min + rand()%(max - min + 1); // min + [0, diff]
644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        p_curr = current;
645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        p_last = last;
646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        str.reset();
647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (; str.content_size()<len && *p_curr && *p_last;){
649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            copy(); // copy 0, 1, or 2 character(s) to str
650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (str.content_size() == len) {
653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str.append(0);
654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            final();
655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (str.content_size() > len) { // if the last copy copied two characters
659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str[len]=0;
660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            final();
661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // str.content_size() < len
665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (*p_last) {
666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (; str.content_size() < len; copy_last());
667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (*p_curr){
668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (; str.content_size() < len; copy_curr());
669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int last_len = last.content_size();
672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (;str.content_size() < len;){
673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str.append(last[rand()%last_len]);
674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        str.append(0);
676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        final();
677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void final(){
680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        last.reset();
681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        last.append_array(current, current.content_size());
682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass Sequence : public Pick {
686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const char* next(){
688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        str.reset();
689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int s = items.content_size();
690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for(int i=0; i < s; i++){
691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            const char * t = items[i]->next();
692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str.append_array(t, strlen(t));
693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        str.append(0); // terminal null
695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return str;
696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void append (Pick * node){
699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        items.append(node);
700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual ~Sequence(){
703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int s = items.content_size();
704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for(int i=0; i < s; i++){
705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            //How can assure the item is got from heap?
706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            //Let's assume it.
707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete items[i]; // TOFIX: point alias/recursion problem
708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            items[i] = NULL;
709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_pPick items;
713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_char  str; //null-terminated c-string
714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass Repeat : public Pick {
717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Pick * item;
719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_char str;
720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    WeightedRand wr;
721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int min;
722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int max;
723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int select_a_count(){
724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return min + wr.next();
725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const char* next(){
728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        str.reset();
729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int c = select_a_count();
730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for(int i=0; i< c; i++){
731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            const char * t = item->next();
732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            str.append_array(t, strlen(t));
733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        str.append(0);
735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return str;
736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Repeat(Pick * base, int minCount =0, int maxCount = 1, Buffer_int * weights = NULL):
739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        wr(weights, maxCount-minCount +1) {
740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        this->item = base;
741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        this->min = minCount;
742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        this->max = maxCount;
743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual ~Repeat(){
745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete item;  // TOFIX: point alias/recursion problem
746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        item = NULL;
747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
748ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass Alternation : public Pick {
752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const char* next(){
754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        str.reset();
755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int i = wr.next();
756ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char * t = items[i]->next();
757ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        str.append_array(t, strlen(t) + 1);
758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return str;
759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
760ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual ~Alternation(){
761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int s = items.content_size();
762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for(int i=0; i < s; i++){
763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete items[i];  // TOFIX: point alias/recursion problem
764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            items[i] = NULL;
765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Alternation & append (Pick * node, int weight = DEFAULT_WEIGHT){
769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        items.append(node);
770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        wr.append(weight);
771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return *this;
772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_pPick items;
775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_char str; // null-terminated c-string
776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    WeightedRand wr;
777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru///////////////////////////////////////////////////////////
780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// The parser
782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruenum TokenType {STRING, VAR, NUMBER, STREAM_END, ERROR, QUESTION, STAR, PLUS, LBRACE, RBRACE, LPAR, RPAR, SEMI, EQ, COMMA, BAR, AT, WAVE, PERCENT};
785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass Scanner{
787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querufriend int DumpScanner(Scanner & s, UBool dumb);
788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char * source;
790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char * working;
791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char * history; // for debug
792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    enum StateType {START, IN_NUM, IN_VAR_FIRST, IN_VAR, IN_QUOTE, IN_QUOTE_BSLASH, IN_BSLASH, IN_STRING, DONE};
793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    StateType state;
794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void terminated(TokenType t){
795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        working--;       // return the peeked character
796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        tokenType = t;
797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        token.append(0); // close buffer
798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        state = DONE;
799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the buffer of "source" is owned by caller
802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Scanner(const char *src/*[in] c-string*/ = NULL):source(src){
803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        working = src;
804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        history = working;
805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        state = DONE;
806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        tokenType = ERROR;
807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //void setSource(const char *const src /*[in] c-string*/){
810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //    *(&const_cast<const char *>(source)) = src;
811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //}
812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_char token;
814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TokenType tokenType;
815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TokenType getNextToken(){
817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        token.reset();
818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        state = START;
819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        history = working; // for debug
820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (state != DONE){
821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            char c = *working++;
822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (c == 0 && state != START){//avoid buffer overflow. for IN_QUOE, IN_ESCAPE
823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                terminated(ERROR);
824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break; // while
825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            switch(state){
827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case START:
828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    tokenType = ERROR;
829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    switch(c){
830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '?'  : tokenType = QUESTION; break;
831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '*'  : tokenType = STAR; break;
832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '+'  : tokenType = PLUS; break;
833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '{'  : tokenType = LBRACE; break;
834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '}'  : tokenType = RBRACE; break;
835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '('  : tokenType = LPAR; break;
836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case ')'  : tokenType = RPAR; break;
837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case ';'  : tokenType = SEMI; break;
838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '='  : tokenType = EQ; break;
839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case ','  : tokenType = COMMA; break;
840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '|'  : tokenType = BAR; break;
841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '@'  : tokenType = AT; break;
842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '~'  : tokenType = WAVE; break;
843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '%'  : tokenType = PERCENT; break;
844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case 0    : tokenType = STREAM_END; working-- /*avoid buffer overflow*/; break;
845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (tokenType != ERROR){
847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        token.append(c);
848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        token.append(0);
849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        state = DONE;
850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        break; // START
851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    switch(c){
853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '$'  : state = IN_VAR_FIRST; token.append(c); break;
854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '\'' : state = IN_QUOTE;     break;
855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '\\' : state = IN_BSLASH;    break;
856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        default:
857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            if (isWhiteSpace(c)){    // state = START;   //do nothing
858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            } else if (isDigit(c)){     state = IN_NUM;    token.append(c);
859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            } else if (isAlphabet(c)){  state = IN_STRING; token.append(c);
860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            } else {terminated(ERROR);}
861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;//START
863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case IN_NUM:
864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (isDigit(c)){
865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        token.append(c);
866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else {
867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        terminated(NUMBER);
868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;//IN_NUM
870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case IN_VAR_FIRST:
871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (isAlphabet(c)){
872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        token.append(c);
873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        state = IN_VAR;
874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else {
875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        terminated(ERROR);
876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break; // IN_VAR_FISRT
878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case IN_VAR:
879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (isAlphabet(c) || isDigit(c)){
880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        token.append(c);
881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else {
882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        terminated(VAR);
883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;//IN_VAR
885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case IN_STRING:
886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // About the scanner's behavior for STRING, AT, and ESCAPE:
887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // All of them can be contacted with each other.
888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // This means the scanner will eat up as much as possible strings
889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    //   (STRING, AT, and ESCAPE) at one time, with no regard of their
890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    //   combining sequence.
891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    //
892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (c == '\''){
893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        state = IN_QUOTE; // the first time we see single quote
894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else if (c =='\\'){ // back slash character
895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        state = IN_BSLASH;
896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else if (isAlphabet(c) || isDigit(c)){
897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        token.append(c);
898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else{
899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        terminated(STRING);
900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;//IN_STRING
902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case IN_QUOTE:
903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (c == '\''){ // the second time we see single quote
904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        state = IN_STRING; // see document in IN_STRING
905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else if ( c== '\\') { // backslah escape in quote
906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        state = IN_QUOTE_BSLASH;
907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else {
908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        token.append(c);  // eat up everything, includes back slash
909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;//IN_QUOTE
911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case IN_QUOTE_BSLASH:
912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case IN_BSLASH:
913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    switch (c){
914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case 'n'  : token.append('\n'); break;
915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case 'r'  : token.append('\r'); break;
916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case 't'  : token.append('\t'); break;
917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '\'' : token.append('\''); break;
918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case '\\' : token.append('\\'); break;
919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        default: token.append(c); // unknown escaping, treat it as literal
920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (state == IN_BSLASH){
922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        state = IN_STRING; // see document in IN_STRING
923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else { // state == IN_QUOTE_BSLASH
924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        state = IN_QUOTE;
925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;//IN_BSLASH
927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case DONE:  /* should never happen */
928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                default:
929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    working--;
930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    tokenType = ERROR;
931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    state = DONE;
932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }//switch(state)
934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }//while (state != DONE)
935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return tokenType;
937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};//class Scanner
939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass Parser{
941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querufriend UBool TestParser();
942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querufriend class TestParserT;
943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querufriend class LanguageGenerator_impl;
944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Scanner s;
946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TokenType & token;
947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int min_max;   // for the evil infinite
948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool match(TokenType expected){
950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (token == expected) {
951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            token = s.getNextToken();
952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return TRUE;
953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            //s.dumpCurrentPoint();
955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool weight(int & value){
960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (token == NUMBER){
961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int temp = atoi(s.token);
962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            match(NUMBER);
963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (match(PERCENT)){
964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                value = temp;
965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return TRUE;
966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool repeat (Pick* &node /*in,out*/){
972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (node == NULL) return FALSE;
973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int count = -2;
975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int min = -2;
976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int max = -2;
977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UBool question = FALSE;
978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        switch (token){
979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case QUESTION:
980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                match(QUESTION);
981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                min = 0;
982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                max = 1;
983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                count = 2;
984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                question = TRUE;
985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case STAR:
987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                match(STAR);
988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                min = 0;
989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                max = -1;
990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                count = -1;
991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case PLUS:
993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                match(PLUS);
994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                min = 1;
995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                max = -1;
996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                count = -1;
997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case LBRACE:
999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                match(LBRACE);
1000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (token != NUMBER){
1001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return FALSE;
1002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }else {
1003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    min = atoi(s.token);
1004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    match(NUMBER);
1005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (token == RBRACE){
1006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        match(RBRACE);
1007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        max = min;
1008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        count = 1;
1009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else if (token == COMMA) {
1010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        match(COMMA);
1011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if (token == RBRACE){
1012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            match(RBRACE);
1013ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            max = -1;
1014ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            count = -1;
1015ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        } else if (token == NUMBER) {
1016ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            max = atoi(s.token);
1017ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            match(NUMBER);
1018ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            count = max - min + 1;
1019ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            if (!match(RBRACE)) {
1020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                return FALSE;
1021ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            }
1022ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        } else {
1023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            return FALSE;
1024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
1025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else {
1026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        return FALSE;
1027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            default:
1031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return FALSE;
1032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1033ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count == -2 || min == -2 || max == -2){
1035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            //ASSERT(FALSE);
1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
1037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // eat up following weights
1040ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Buffer_int weights;
1041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int w;
1042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (weight(w)){
1043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            weights.append(w);
1044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1046ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // for the evil infinite
1047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        min_max = min_max > min ? min_max : min;
1048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        min_max = min_max > max ? min_max : max;
1049ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (min_max > PSEUDO_INFINIT){
1050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE; // PSEUDO_INFINIT is less than the real maximum
1051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1052ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (max == -1){ // the evil infinite
1053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            max = PSEUDO_INFINIT;
1054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1055ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // for the strange question mark
1056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (question && weights.content_size() > 0){
1057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            Buffer_int w2;
1058ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            w2.append(DEFAULT_WEIGHT - weights[0]).append(weights[0]);
1059ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            node = new Repeat(node,min,max,&w2);
1060ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return TRUE;
1061ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1062ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        node = new Repeat(node,min,max,&weights);
1063ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return TRUE;
1064ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1065ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1066ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool core(Pick* &node /*out*/){
1067ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (node != NULL) return FALSE; //assert node == NULL
1068ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1069ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        switch(token){
1070ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case LPAR:
1071ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                match(LPAR);
1072ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(defination(node) && match(RPAR)){
1073ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return TRUE;
1074ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1075ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return FALSE;
1076ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case VAR:
1077ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                node = new Variable(&symbols, s.token);
1078ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                match(VAR);
1079ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return TRUE;
1080ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case STRING:
1081ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                node = new Literal(s.token);
1082ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                match(STRING);
1083ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return TRUE;
1084ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            default:
1085ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return FALSE;
1086ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1087ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1088ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool modified(Pick* &node /*out*/){
1089ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (node != NULL) return FALSE; //assert node == NULL
1090ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1091ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!core(node)) {
1092ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
1093ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1094ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1095ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (;;){
1096ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            switch(token){
1097ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case WAVE:
1098ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    match(WAVE);
1099ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    node = new Morph(*node);
1100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
1101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case AT:
1102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    match(AT);
1103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    node = new Quote(*node);
1104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
1105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case QUESTION:
1106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case STAR:
1107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case PLUS:
1108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case LBRACE:
1109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (!repeat(node)) return FALSE;
1110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
1111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case SEMI:      // rule definiation closed
1112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case RPAR:      // within parenthesis (core closed)
1113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case BAR:       // in alternation
1114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case NUMBER:    // in alternation, with weight
1115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case LPAR:      // in sequence
1116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case VAR:       // in sequence
1117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case STRING:    // in sequence
1118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return TRUE;
1119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                default:
1120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return FALSE;
1121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool sequence_list(Pick* &node /*in,out*/){
1127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (node == NULL) return FALSE; // assert node != NULL
1128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Sequence* seq = new Sequence();
1130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Pick * n = node;
1131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (token == VAR || token == STRING || token == LPAR){
1133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            seq->append(n);
1134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            n = NULL;
1135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (modified(n)){
1136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // go on
1137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                goto FAIL;
1139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (token == SEMI || token == RPAR || token == BAR){
1143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            seq->append(n);
1144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            node = seq;
1145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return TRUE;
1146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruFAIL:
1148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete seq;
1149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
1150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool sequence(Pick* &node /*out*/){
1154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (node != NULL) return FALSE; //assert node == NULL
1155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!modified(node)) {
1157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
1158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (token == VAR || token == STRING || token == LPAR){
1161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return sequence_list(node);
1162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return TRUE; // just a modified
1164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool alternation_list(Pick* &node /*in,out*/){
1168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (node == NULL) return FALSE; // assert node != NULL
1169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Alternation * alt = new Alternation();
1171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Pick * n = node;
1172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int w = DEFAULT_WEIGHT;
1173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (token == NUMBER || token == BAR){
1175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(token == NUMBER) {
1176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (weight(w)){
1177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (token == BAR){
1178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        // the middle item, go on
1179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else {
1180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        // the last item or encounter error
1181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        break; //while
1182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
1184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    goto FAIL;
1185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } // else token == BAR
1187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            match(BAR);
1188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            alt->append(n,w);
1189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            n = NULL;
1191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            w = DEFAULT_WEIGHT;
1192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (sequence(n)){
1193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // go on
1194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                goto FAIL;
1196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (token == SEMI || token == RPAR) {
1200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            alt->append(n,w);
1201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            node = alt;
1202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return TRUE;
1203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruFAIL:
1205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete alt;
1206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
1207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool alternation(Pick* &node /*out*/){
1210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (node != NULL) return FALSE; //assert node == NULL
1211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // 'sequence' has higher precedence than 'alternation'
1213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!sequence(node)){
1214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
1215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (token == BAR || token == NUMBER){ // find a real alternation1, create it.
1218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return alternation_list(node);
1219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return TRUE;    // just a sequence_old
1221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool defination(Pick* &node /*out*/){
1226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (node != NULL) return FALSE; //assert node == NULL
1227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return alternation(node);
1228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool rule(){
1231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (token == VAR){
1232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            Buffer_char name;
1233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            name.append_array(s.token, strlen(s.token) + 1);
1234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            match(VAR);
1235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (match(EQ)){
1237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                Pick * t = NULL;
1238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(defination(t)){
1239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    symbols.put(name, t);
1240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return match(SEMI);
1241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
1245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
1247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool rules(){
1248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        symbols.reset();
1249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        token = s.getNextToken();
1250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (rule()){
1251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (token == STREAM_END){
1253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return TRUE;
1254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            //s.dumpCurrentPoint();
1256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
1257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
1261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SymbolTable symbols;
1262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Parser(const char *const source):s(source), token(s.tokenType){
1264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        min_max = -2;
1265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool parse(){
1267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return rules();
1268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; // class Parser
1271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru///////////////////////////////////////////////////////////
1274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
1275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
1276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
1277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint DumpScanner(Scanner & s, UBool dump = TRUE){
1279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int len = strlen(s.source);
1280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int error_start_offset = s.history - s.source;
1281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (dump){
1282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        printf("\n=================== DumpScanner ================\n");
1283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fwrite(s.source, len, 1, stdout);
1284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        printf("\n-----parsed-------------------------------------\n");
1285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fwrite(s.source, s.history - s.source, 1, stdout);
1286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        printf("\n-----current------------------------------------\n");
1287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fwrite(s.history, s.working - s.history, 1, stdout);
1288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        printf("\n-----unparsed-----------------------------------\n");
1289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fwrite(s.working, (s.source + len - s.working), 1, stdout);
1290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        printf("\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
1291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return error_start_offset;
1293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass LanguageGenerator_impl{
1296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
1297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LanguageGenerator_impl(const char *const bnf_definition, const char *const top_node)
1298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        :par(bnf_definition), top_node_name(top_node){
1299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        srand((unsigned)time( NULL ));
1300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LanguageGenerator::PARSE_RESULT parseBNF(UBool debug = TRUE){
1303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (par.parse()){
1304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (par.symbols.find(top_node_name, &top_node_ref) == SymbolTable::HAS_REF) {
1305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (par.symbols.is_complete()) {
1306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return LanguageGenerator::OK;
1307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
1308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (debug) printf("The bnf definition is incomplete.\n");
1309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return LanguageGenerator::INCOMPLETE;
1310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (debug) printf("No top node is found.\n");
1313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return LanguageGenerator::NO_TOP_NODE;
1314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(debug) {
1317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                printf("The bnf definition is wrong\n");
1318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                DumpScanner(par.s, TRUE);
1319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return LanguageGenerator::BNF_DEF_WRONG;
1321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char * next(){
1324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return top_node_ref->next();
1325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
1328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Parser par;
1329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *const top_node_name;
1330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Pick * top_node_ref;
1331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
1332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLanguageGenerator::LanguageGenerator():lang_gen(NULL){
1334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLanguageGenerator::~LanguageGenerator(){
1337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete lang_gen;
1338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLanguageGenerator::PARSE_RESULT LanguageGenerator::parseBNF(const char *const bnf_definition /*in*/, const char *const top_node/*in*/, UBool debug){
1341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (lang_gen){
1342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete lang_gen;
1343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lang_gen = new LanguageGenerator_impl(bnf_definition, top_node);
1345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    PARSE_RESULT r = lang_gen->parseBNF(debug);
1346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (r != OK){
1347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete lang_gen;
1348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lang_gen = NULL;
1349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return r;
1350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return r;
1352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst char *LanguageGenerator::next(){ // Return a null-terminated c-string. The buffer is owned by callee.
1355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (lang_gen){
1356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return lang_gen->next();
1357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }else {
1358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return "";
1359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru///////////////////////////////////////////////////////////
1363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
1364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// The test code for WBNF
1365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
1366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define CALL(fun) \
1368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fun()){ \
1369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        printf("Pass: " #fun "\n");\
1370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else { \
1371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        printf("FAILED: !!! " #fun " !!!\n"); \
1372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DUMP_R(fun, var, times) \
1375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {printf("\n========= " #fun " =============\n"); \
1376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int i=0; i<times; i++) { \
1377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char * t = var.next();\
1378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fwrite(t,strlen(t),1,stdout); \
1379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        printf("\n");   \
1380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }   \
1381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");}
1382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if TEST_WBNF_TEST
1386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool TestQuote(){
1387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *const str = "This ' A !,z| qq [] .new\tline";
1388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //const char *const str_r = "This \\' A '!,'z'|' qq '[]' '.'new\tline";
1389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ////
1390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //// :(  we must quote our string to following C syntax
1391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ////     cannot type the literal here, it makes our code rather human unreadable
1392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ////     very very unconformable!
1393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ////
1394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ///*
1395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //*/
1396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //const char *const s1    =   "ab'c";
1398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //const char (* s1_r1) [] = { "ab''c",    // ab''c
1399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //                            "ab\\'c",   // ab\'c
1400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //                           };//
1401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ///*
1402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // .      '.'     \.
1403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // ..     \.\.    '.'\.   '.'\.   '..'    // '.''.'  wrong
1404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //*/
1405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //const char *const s2    =   "a..'.b";       // a..'.b
1407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //const char (*s2_r) []   = { "a'..''.'b"     // a'..''.'b
1408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //                           ,"a'..\\'.'b"    // a'..\'.'b
1409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //                           ,"a'..'\\''.'b"  // a'..'\''.'b
1410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //                          };//
1411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //const char *const s3    =   "a..\\.b";      // a..\.b
1413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //const char (*s3_r) []   = { "a'..\\\\.'b"   // a'..\\.'b
1414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //                           ,"a'..'\\\\'.'b" // a'..'\\'.'b
1415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //                          };//
1416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //                            // no catact operation, no choice, must be compact
1418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    srand((unsigned)time( NULL ));
1420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //Escaper l(Escaper::NO, Escaper::NO, Escaper::RAND_ESC);
1422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Pick *p = new Literal(str);
1423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Quote q(*p);
1424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DUMP_R(TestQuote, (*p), 1);
1426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DUMP_R(TestQuote, q, 20);
1427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
1428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool TestLiteral(){
1430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char * s = "test string99.";
1431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Literal n(s);
1432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char * r = n.next();
1433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return strcmp(s,r) == 0;
1434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool TestSequence(){
1437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Sequence seq;
1438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    seq.append(new Literal("abc "));
1439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    seq.append(new Literal(", s"));
1440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return strcmp(seq.next(), "abc , s") == 0;
1442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool TestAlternation(){
1444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    srand((unsigned)time( NULL ));
1445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Alternation alt;
1446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    alt.append(new Literal("aaa_10%"),10);
1447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    alt.append(new Literal("bbb_0%"),0);
1448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    alt.append(new Literal("ccc_10%"),10);
1449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    alt.append(new Literal("ddddddd_50%"),50);
1450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DUMP_R(TestAlternation, alt, 50);
1452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
1454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool TestBuffer(){
1457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_int t;
1458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t.append(1).append(0).append(5);
1459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int s = t.content_size();
1460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int i=0; i<s; ++i){
1461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        printf("%d\n", t[i]);
1462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
1464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool TestWeightedRand(){
1467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    srand((unsigned)time( NULL ));
1468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Buffer_int t;
1469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t.append(1).append(0).append(5);
1470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    WeightedRand wr(&Buffer_int().append(10).append(0).append(50),4);
1471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    WeightedRand wr(&t,3);
1472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int i=0; i< 50; ++i){
1473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        printf("%d\n", wr.next());
1474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
1476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool TestRepeat(){
1479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    srand((unsigned)time( NULL ));
1480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Repeat rep(new Literal("aaa1-5 "), 1, 5);
1481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DUMP_R(TestRepeat, rep, 50);
1482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Repeat r2(new Literal("b{1,3}1%0%5% "), 1, 3, &Buffer_int().append(1).append(0).append(5));
1484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DUMP_R(TestRepeat, r2, 50);
1485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Repeat r3(new Literal("aaa5-5 "), 5, 5);
1487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DUMP_R(TestRepeat, r3, 50);
1488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
1490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool TestVariable(){
1493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SymbolTable tab;
1494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Pick * value = new Literal("string1");
1495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Variable var1(&tab, "x", value);
1496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Variable var2(&tab, "y");
1498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    tab.put(var2, value); // TOFIX: point alias/recursion problem
1499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Pick * value2 = new Literal("string2");
1500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    tab.put(var2, value2);
1501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Pick * value3 = new Literal("string3");
1503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Variable var3(&tab, "z");
1504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    tab.put("z", value3);
1505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool pass;
1507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = strcmp(var1.next(), value->next()) == 0;
1508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && strcmp(var2.next(), value2->next()) == 0;
1509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && strcmp(var3.next(), value3->next()) == 0;
1510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return pass;
1511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool TestSymbolTable(){
1514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Literal * n1 = new Literal("string1");
1515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Literal * n2 = new Literal("string2");
1516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SymbolTable t;
1517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t.put("abc", n1);
1518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t.put("$aaa", n2);
1519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    t.put("alias", n1);  // TOFIX: point alias/recursion problem
1520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t.put("bbb");
1521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool pass;
1523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = t.find(NULL) == SymbolTable::EMPTY;
1524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && t.find("ccc") == SymbolTable::NO_VAR;
1525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && t.find("bbb") == SymbolTable::NO_REF;
1526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && t.find("abc") == SymbolTable::HAS_REF;
1527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && t.find("$aaa") == SymbolTable::HAS_REF;
1528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t.reset();
1530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && t.find("abc") == SymbolTable::NO_VAR;
1531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return pass;
1532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool TestScanner(void){
1536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //const char str1[] = "$root = $command{0,5} $reset $mostRules{1,20};";
1537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //const char str1_r[][20] = {"$root", "=", "$command", "{", "0", ",", "5", "}",
1538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //    "$reset", "$mostRules", "{", "1", ",", "20", "}", ";"};
1539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char str2[] = "$p2 =(\\\\ $s $string $s)? 25%;";
1541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char str2_r[][20] = {"$p2", "=", "(", "\\", "$s", "$string", "$s", ")", "?", "25", "%", ";"};
1542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *str = str2;
1544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char (*str_r)[20] = str2_r;
1545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int tokenNum = sizeof(str2_r)/sizeof(char[20]);
1546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Scanner t(str);
1548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool pass = TRUE;
1549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t.getNextToken();
1550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int i = 0;
1551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (pass){
1552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (t.tokenType == STREAM_END){
1553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pass = pass? i == tokenNum : FALSE;
1554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;//while
1555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (t.tokenType == ERROR){
1556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pass = FALSE;
1557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;//while
1558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pass = strcmp( &(t.token[0]), str_r[i++]) == 0;
1560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            t.getNextToken();
1561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //const char ts[] = "$commandList = '['"
1565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //" ( alternate ' ' $alternateOptions"
1566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //" | backwards ' 2'"
1567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //" | normalization ' ' $onoff "
1568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //" | caseLevel ' ' $onoff "
1569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //" | hiraganaQ ' ' $onoff"
1570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //" | caseFirst ' ' $caseFirstOptions"
1571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //" | strength ' ' $strengthOptions"
1572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //" ) ']';" ;
1573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //Scanner t2(ts);
1575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //pass = TRUE;
1576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //do {
1577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //    t2.getNextToken();
1578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //    if (t2.tokenType == ERROR){
1579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //        DumpScanner(t2);
1580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //        return FALSE;
1581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //    }
1582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //}while (t.tokenType != STREAM_END);
1583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return pass;
1585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass TestParserT {
1588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
1589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool operator () (const char *const str, const int exp_error_offset = -1, const UBool dump = TRUE){
1590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Parser par(str);
1591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (par.rules()){
1592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if ( exp_error_offset == -1){
1593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return TRUE;
1594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }else {
1595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            DumpScanner(par.s,dump);
1596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
1597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }else {
1599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return DumpScanner(par.s, dump) == exp_error_offset;
1600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
1603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool TestParser(){
1605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TestParserT test;
1606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool pass = TRUE;
1608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test ("$s = ' ' ? 50%;");
1609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$x = ($var {1,2}) 3%;");         // legal
1610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$x = $var {1,2} 3% | b 4%;");    // legal
1611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$x = $var {1,2} 3%;");           // legal
1612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$m = $c ? 2% 4% | $r 5% | $n 25%;"); // legal
1613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$a = b ? 2% | c 5%;");               // legal
1614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$x = A B 5% C 10% | D;", 8, FALSE);  // illegal 5%
1615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$x = aa 45% | bb 5% cc;", 19, FALSE);// illegal cc
1616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$x = (b 5%) (c 6%);");               // legal
1617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$x = (b 5%) c 6%;", 13, FALSE);      // illegal 6%
1618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$x = b 5% (c 6%);", 9, FALSE);       // illegal (c 6%)
1619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$x = b 5% c 6%;", 9, FALSE);         // illegal c 6%
1620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$x = b 5%;");                        // legal
1621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$x = aa 45% | bb 5% cc;", 19, FALSE);// illegal cc
1622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$x = a | b  | c 4% | d 5%;");        // legal
1623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$s = ' ' ? 50% abc;");               // legal
1624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$s =  a | c d | e f;");              // legal
1625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test( "$z = q 0% | p 1% | r 100%;");         // legal How to check parsed tree??
1626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$s = ' ' ? 50%;");
1628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$relationList = '<' | '<<' |  ';' | '<<<' | ',' | '=';");
1629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$p1 = ($string $s '|' $s)? 25%;");
1630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$p2 = (\\\\ $s $string $s)? 25%;");
1631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$rel2 = $p1 $string $s $p2;");
1632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$relation = $relationList $s ($rel1 | $rel2) $crlf;");
1633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$command = $commandList $crlf;");
1634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$reset = '&' $s ($beforeList $s)? 10% ($positionList 100% | $string 10%) $crlf;");
1635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$mostRules = $command 1% | $reset 5% | $relation 25%;");
1636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test("$root = $command{0,5} $reset $mostRules{1,20};");
1637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char collationBNF[] =
1639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$s = ' '? 50%;"
1640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$crlf = '\r\n';"
1641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$alternateOptions = non'-'ignorable | shifted;"
1643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$onoff = on | off;"
1644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$caseFirstOptions = off | upper | lower;"
1645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$strengthOptions = '1' | '2' | '3' | '4' | 'I';"
1646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$commandList = '['"
1647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    " ( alternate ' ' $alternateOptions"
1648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    " | backwards ' 2'"
1649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    " | normalization ' ' $onoff "
1650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    " | caseLevel ' ' $onoff "
1651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    " | hiraganaQ ' ' $onoff"
1652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    " | caseFirst ' ' $caseFirstOptions"
1653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    " | strength ' ' $strengthOptions"
1654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    " ) ']';"
1655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$command = $commandList $crlf;"
1656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$ignorableTypes = (tertiary | secondary | primary) ' ' ignorable;"
1658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$allTypes = variable | regular | implicit | trailing | $ignorableTypes;"
1659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$positionList = '[' (first | last) ' ' $allTypes ']';"
1660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$beforeList = '[before ' ('1' | '2' | '3') ']';"
1662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$relationList = ("
1664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "   '<'"
1665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    " | '<<'"
1666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    " | ';'"
1667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    " | '<<<'"
1668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    " | ','"
1669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    " | '='"
1670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ");"
1671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$string = $magic;"
1672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$rel1 = '[variable top]' $s;"
1673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$p1 = ($string $s '|' $s)? 25%;"
1674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$p2 = (\\\\ $s $string $s)? 25%;"
1675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$rel2 = $p1 $string $s $p2;"
1676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$relation = $relationList $s ($rel1 | $rel2) $crlf;"
1677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$reset = '&' $s ($beforeList $s)? 10% ($positionList 1% | $string 10%) $crlf;"
1679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$mostRules = $command 1% | $reset 5% | $relation 25%;"
1680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "$root = $command{0,5} $reset $mostRules{1,20};"
1681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ;
1682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = pass && test(collationBNF);
1684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return pass;
1687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool TestMorph(){
1690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    srand((unsigned)time( NULL ));
1691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Alternation * alt = new Alternation();
1693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    (*alt)
1695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .append(new Literal("a")).append(new Literal("b")).append(new Literal("c"))
1696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .append(new Literal("d")).append(new Literal("e")).append(new Literal("f"))
1697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .append(new Literal("g")).append(new Literal("h")).append(new Literal("i"))
1698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .append(new Literal("j")).append(new Literal("k")).append(new Literal("l"))
1699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    .append(new Literal("m")).append(new Literal("n")).append(new Literal("o"))
1700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ;
1701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Repeat * rep = new Repeat( alt ,5,5 );
1703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Morph m( *rep);
1704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    DUMP_R(TestMorph,(*rep),20);
1706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DUMP_R(TestMorph,m,100);
1707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
1709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
1712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool TestLanguageGenerator(){
1714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //LanguageGenerator g;
1715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //const char *const s = "$s = p 0% | q 1%;";
1716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //g.parseBNF(s, "$s");
1717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool pass;
1718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //= strcmp("q", g.next()) == 0;
1719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *const def =
1721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        //"$a = $b;"
1722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        //"$b = $c;"
1723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        //"$c = $t;"
1724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        //"$t = abc $z{1,2};"
1725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        //"$k = a | b | c | d | e | f | g ;"
1726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        //"$z = q 0% | p 1% | r 1%;"
1727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        "$x = a ? 0%;"
1728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ; // end of string
1729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    const char * s = "abczz";
1730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
1731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
1732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LanguageGenerator g;
1733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pass = g.parseBNF(def, "$x",TRUE);
1734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru////    LanguageGenerator g(collationBNF, "$root", "$magic", new MagicNode());
1735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
1736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (pass != LanguageGenerator::OK) return FALSE;
1737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DUMP_R(TestLanguageGenerator, g, 20);
1739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return pass;
1740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ////UBool pass = strcmp(s,r) == 0;
1742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //if (pass){
1744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //    printf("TestRandomLanguageGenerator passed.\n");
1745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //} else {
1746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //    printf("TestRandomLanguageGenerator FAILED!!!\n");
1747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //}
1748ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //return pass;
1749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid TestWbnf(void){
1752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    srand((unsigned)time( NULL ));
1753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //CALL(TestLiteral);
1755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //CALL(TestSequence);
1756ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //CALL(TestSymbolTable);
1757ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //CALL(TestVariable);
1758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //TestRepeat();
1760ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //TestAlternation();
1761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //TestMorph();
1762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //TestQuote();
1764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //TestBuffer();
1765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //TestWeightedRand();
1766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //CALL(TestScanner);
1768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //CALL(TestParser);
1769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    CALL(TestLanguageGenerator);
1770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1772