1 /**
2  *  Yudit Unicode Editor Source File
3  *
4  *  GNU Copyright (C) 1997-2006  Gaspar Sinai <gaspar@yudit.org>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License, version 2,
8  *  dated June 1991. See file COPYYING for details.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 
20 #include "stoolkit/syntax/SPattern.h"
21 #include "stoolkit/SCharClass.h"
22 
23 /**
24  * A sample pattern that can be extended. This pattern
25  * now highlights the following:
26  *
27  * 123... number
28  * Yuko   keyword
29  * yuko   error
30  * YUKO (kanji) define
31  * characters none
32  * other  control
33  *
34  * @author Gaspar Sinai
35  * @version 2007-11-27
36  */
SPattern(void)37 SPattern::SPattern (void) :
38 ACT_NONE ("none"),
39 ACT_ERROR ("error"),
40 ACT_NUMBER ("number"),
41 ACT_KEYWORD ("keyword"),
42 ACT_VARIABLE ("variable"),
43 ACT_DEFINE ("define"),
44 ACT_CONTROL ("control"),
45 ACT_OTHER ("other")
46 {
47   clear ();
48 }
49 
~SPattern()50 SPattern::~SPattern ()
51 {
52 }
53 
54 //
55 void
clear()56 SPattern::clear ()
57 {
58   action = ACT_NONE;
59   matchBegin = SD_MATCH_EOD;
60   matchEnd = 0;
61   next = 0;
62   current.clear ();
63 }
64 
65 // This method will be overwritten
66 bool
checkMatch()67 SPattern::checkMatch ()
68 {
69   return checkMatchTest();
70 }
71 
72 void
append(SS_UCS4 in)73 SPattern::append (SS_UCS4 in)
74 {
75   if (next == 0) matchEnd = 0;
76   current.append (in);
77   next++;
78 }
79 
80 // We all ignore the last character in the buffer,
81 // that is next position, and it is non-inclusive
82 // note that current position is next - 1, and
83 // we dont look at current.
84 bool
checkMatchTest()85 SPattern::checkMatchTest ()
86 {
87   // We are lucky, none of our staring chars are used in the other pattern.
88   if (current.size() >= 3 &&
89     current[current.size()-3] == 0x512A // YUU
90       && current[current.size()-2] == 0x5B50) // KO
91   {
92     if (singleMatchTest (3)) return true;
93     current.remove(0);
94     current.remove(0);
95 
96     matchBegin = next-1-2;
97     matchEnd = next-1;
98     action = ACT_DEFINE;
99     return true;
100   }
101   else if (current.size() >= 2
102     && current[current.size()-2] == (SS_UCS4)'\n') // YUU
103   {
104     if (singleMatchTest (2)) return true;
105     current.remove(0);
106     matchBegin = next-1-1;
107     matchEnd = next-1;
108     action = ACT_CONTROL;
109     return true;
110   }
111   else if (current.size() >= 5
112     && current[current.size()-5] == (SS_UCS4)'y'
113     && current[current.size()-4] == (SS_UCS4)'u'
114     && current[current.size()-3] == (SS_UCS4)'k'
115     && current[current.size()-2] == (SS_UCS4)'o')
116   {
117     if (singleMatchTest (5)) return true;
118     current.remove(0);
119     current.remove(0);
120     current.remove(0);
121     current.remove(0);
122     matchBegin = next-1-4;
123     matchEnd = next-1;
124     action = ACT_ERROR;
125     return true;
126   }
127   else if (current.size() >= 5
128     && current[current.size()-5] == (SS_UCS4)'Y'
129     && current[current.size()-4] == (SS_UCS4)'u'
130     && current[current.size()-3] == (SS_UCS4)'k'
131     && current[current.size()-2] == (SS_UCS4)'o')
132   {
133     if (singleMatchTest (5)) return true;
134     current.remove(0);
135     current.remove(0);
136     current.remove(0);
137     current.remove(0);
138     matchBegin = next-1-4;
139     matchEnd = next-1;
140     action = ACT_KEYWORD;
141     return true;
142   }
143   bool isEOD = current.size() > 0 &&  current[current.size()-1] == SD_MATCH_EOD;
144   return singleMatchTest (isEOD ? 1: 5);
145 }
146 
147 // match current[0] and remove it.
148 bool
singleMatchTest(unsigned int leaveSize)149 SPattern::singleMatchTest (unsigned int leaveSize)
150 {
151   if (current.size() > leaveSize)
152   {
153     matchBegin = matchEnd;
154     matchEnd++;
155     action = ACT_NONE;
156     SD_CharClass cc = getCharClass (current[0]);
157     switch (cc)
158     {
159     // letter
160     case SD_CC_Lu:
161     case SD_CC_Ll:
162     case SD_CC_Lt:
163     case SD_CC_Lm:
164     case SD_CC_Lo:
165       current.remove (0);
166       if (!singleMatchTest (leaveSize))
167       {
168         return false;
169       }
170       return true;
171     case SD_CC_Nd:
172     case SD_CC_Nl:
173     case SD_CC_No:
174       action = ACT_NUMBER;
175       break;
176     case SD_CC_So:
177       action = ACT_OTHER;
178       break;
179     default:
180       action = ACT_CONTROL;
181     }
182     current.remove (0);
183     return true;
184   }
185   return false;
186 }
187