Skip to content

Commit c83ad51

Browse files
authored
Merge pull request #42 from javecs/feature/optional
ルールに必須ではない項目を設定する機能を追加しました。
2 parents af9183e + 7b7e67f commit c83ad51

14 files changed

Lines changed: 101 additions & 78 deletions

File tree

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ plugins {
1616
}
1717

1818
group 'xyz.javecs.tools'
19-
version '0.1.4'
19+
version '0.1.5'
2020

2121
apply plugin: 'kotlin'
2222
apply plugin: 'antlr'

src/main/antlr/Text2Expr.g4

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ optionalValue: '(' NUMBER ')' ;
2020
// BF : Base form
2121
// RD : Reading
2222
// PR : Pronunciation
23-
PREFIX: 'SF' | 'P'LEVEL | 'BF' | 'RD' | 'PR' ;
24-
LEVEL: [1234] ;
23+
PREFIX: 'SF' | 'P1' | 'P2' | 'P3' | 'P4' | 'BF' | 'RD' | 'PR' ;
2524

2625
// Hiragana : 3040–309F
2726
// Katakana : 30A0–30FF

src/main/java/xyz/javecs/tools/text2expr/parser/Text2Expr.tokens

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@ T__4=5
66
T__5=6
77
T__6=7
88
PREFIX=8
9-
LEVEL=9
10-
JAPANESE=10
11-
SYMBOL=11
12-
OPERATOR=12
13-
NUMBER=13
14-
ID=14
15-
NEWLINE=15
16-
WS=16
9+
JAPANESE=9
10+
SYMBOL=10
11+
OPERATOR=11
12+
NUMBER=12
13+
ID=13
14+
NEWLINE=14
15+
WS=15
1716
'='=1
1817
','=2
1918
':'=3

src/main/java/xyz/javecs/tools/text2expr/parser/Text2ExprLexer.java

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ public class Text2ExprLexer extends Lexer {
1717
protected static final PredictionContextCache _sharedContextCache =
1818
new PredictionContextCache();
1919
public static final int
20-
T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, PREFIX=8, LEVEL=9,
21-
JAPANESE=10, SYMBOL=11, OPERATOR=12, NUMBER=13, ID=14, NEWLINE=15, WS=16;
20+
T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, PREFIX=8, JAPANESE=9,
21+
SYMBOL=10, OPERATOR=11, NUMBER=12, ID=13, NEWLINE=14, WS=15;
2222
public static String[] channelNames = {
2323
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
2424
};
@@ -28,15 +28,15 @@ public class Text2ExprLexer extends Lexer {
2828
};
2929

3030
public static final String[] ruleNames = {
31-
"T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "PREFIX", "LEVEL",
32-
"JAPANESE", "SYMBOL", "OPERATOR", "NUMBER", "ID", "NEWLINE", "WS"
31+
"T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "PREFIX", "JAPANESE",
32+
"SYMBOL", "OPERATOR", "NUMBER", "ID", "NEWLINE", "WS"
3333
};
3434

3535
private static final String[] _LITERAL_NAMES = {
3636
null, "'='", "','", "':'", "'?'", "'|'", "'('", "')'"
3737
};
3838
private static final String[] _SYMBOLIC_NAMES = {
39-
null, null, null, null, null, null, null, null, "PREFIX", "LEVEL", "JAPANESE",
39+
null, null, null, null, null, null, null, null, "PREFIX", "JAPANESE",
4040
"SYMBOL", "OPERATOR", "NUMBER", "ID", "NEWLINE", "WS"
4141
};
4242
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
@@ -97,36 +97,37 @@ public Text2ExprLexer(CharStream input) {
9797
public ATN getATN() { return _ATN; }
9898

9999
public static final String _serializedATN =
100-
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\22n\b\1\4\2\t\2\4"+
100+
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\21p\b\1\4\2\t\2\4"+
101101
"\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+
102-
"\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\3\2\3\2\3"+
103-
"\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t"+
104-
"\3\t\3\t\3\t\3\t\5\t<\n\t\3\n\3\n\3\13\6\13A\n\13\r\13\16\13B\3\f\3\f"+
105-
"\6\fG\n\f\r\f\16\fH\3\f\3\f\3\r\3\r\3\16\6\16P\n\16\r\16\16\16Q\3\16\3"+
106-
"\16\6\16V\n\16\r\16\16\16W\5\16Z\n\16\3\17\3\17\7\17^\n\17\f\17\16\17"+
107-
"a\13\17\3\20\5\20d\n\20\3\20\3\20\3\21\6\21i\n\21\r\21\16\21j\3\21\3\21"+
108-
"\2\2\22\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17"+
109-
"\35\20\37\21!\22\3\2\t\3\2\63\66\4\2\u3042\u3101\u4e02\ua001\7\2\'\'*"+
110-
"/\61\61??``\3\2\62;\4\2C\\c|\5\2\62;C\\c|\4\2\13\13\"\"\2y\2\3\3\2\2\2"+
111-
"\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2"+
112-
"\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2"+
113-
"\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\3#\3\2\2\2\5%\3\2\2"+
114-
"\2\7\'\3\2\2\2\t)\3\2\2\2\13+\3\2\2\2\r-\3\2\2\2\17/\3\2\2\2\21;\3\2\2"+
115-
"\2\23=\3\2\2\2\25@\3\2\2\2\27D\3\2\2\2\31L\3\2\2\2\33O\3\2\2\2\35[\3\2"+
116-
"\2\2\37c\3\2\2\2!h\3\2\2\2#$\7?\2\2$\4\3\2\2\2%&\7.\2\2&\6\3\2\2\2\'("+
117-
"\7<\2\2(\b\3\2\2\2)*\7A\2\2*\n\3\2\2\2+,\7~\2\2,\f\3\2\2\2-.\7*\2\2.\16"+
118-
"\3\2\2\2/\60\7+\2\2\60\20\3\2\2\2\61\62\7U\2\2\62<\7H\2\2\63\64\7R\2\2"+
119-
"\64<\5\23\n\2\65\66\7D\2\2\66<\7H\2\2\678\7T\2\28<\7F\2\29:\7R\2\2:<\7"+
120-
"T\2\2;\61\3\2\2\2;\63\3\2\2\2;\65\3\2\2\2;\67\3\2\2\2;9\3\2\2\2<\22\3"+
121-
"\2\2\2=>\t\2\2\2>\24\3\2\2\2?A\t\3\2\2@?\3\2\2\2AB\3\2\2\2B@\3\2\2\2B"+
122-
"C\3\2\2\2C\26\3\2\2\2DF\7$\2\2EG\4#\u0080\2FE\3\2\2\2GH\3\2\2\2HF\3\2"+
123-
"\2\2HI\3\2\2\2IJ\3\2\2\2JK\7$\2\2K\30\3\2\2\2LM\t\4\2\2M\32\3\2\2\2NP"+
124-
"\t\5\2\2ON\3\2\2\2PQ\3\2\2\2QO\3\2\2\2QR\3\2\2\2RY\3\2\2\2SU\7\60\2\2"+
125-
"TV\t\5\2\2UT\3\2\2\2VW\3\2\2\2WU\3\2\2\2WX\3\2\2\2XZ\3\2\2\2YS\3\2\2\2"+
126-
"YZ\3\2\2\2Z\34\3\2\2\2[_\t\6\2\2\\^\t\7\2\2]\\\3\2\2\2^a\3\2\2\2_]\3\2"+
127-
"\2\2_`\3\2\2\2`\36\3\2\2\2a_\3\2\2\2bd\7\17\2\2cb\3\2\2\2cd\3\2\2\2de"+
128-
"\3\2\2\2ef\7\f\2\2f \3\2\2\2gi\t\b\2\2hg\3\2\2\2ij\3\2\2\2jh\3\2\2\2j"+
129-
"k\3\2\2\2kl\3\2\2\2lm\b\21\2\2m\"\3\2\2\2\f\2;BHQWY_cj\3\b\2\2";
102+
"\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\3\2\3\2\3\3\3\3\3\4"+
103+
"\3\4\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3"+
104+
"\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\5\t@\n\t\3\n\6\nC\n\n\r\n\16\nD\3\13\3"+
105+
"\13\6\13I\n\13\r\13\16\13J\3\13\3\13\3\f\3\f\3\r\6\rR\n\r\r\r\16\rS\3"+
106+
"\r\3\r\6\rX\n\r\r\r\16\rY\5\r\\\n\r\3\16\3\16\7\16`\n\16\f\16\16\16c\13"+
107+
"\16\3\17\5\17f\n\17\3\17\3\17\3\20\6\20k\n\20\r\20\16\20l\3\20\3\20\2"+
108+
"\2\21\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35"+
109+
"\20\37\21\3\2\b\4\2\u3042\u3101\u4e02\ua001\7\2\'\'*/\61\61??``\3\2\62"+
110+
";\4\2C\\c|\5\2\62;C\\c|\4\2\13\13\"\"\2~\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3"+
111+
"\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2"+
112+
"\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35"+
113+
"\3\2\2\2\2\37\3\2\2\2\3!\3\2\2\2\5#\3\2\2\2\7%\3\2\2\2\t\'\3\2\2\2\13"+
114+
")\3\2\2\2\r+\3\2\2\2\17-\3\2\2\2\21?\3\2\2\2\23B\3\2\2\2\25F\3\2\2\2\27"+
115+
"N\3\2\2\2\31Q\3\2\2\2\33]\3\2\2\2\35e\3\2\2\2\37j\3\2\2\2!\"\7?\2\2\""+
116+
"\4\3\2\2\2#$\7.\2\2$\6\3\2\2\2%&\7<\2\2&\b\3\2\2\2\'(\7A\2\2(\n\3\2\2"+
117+
"\2)*\7~\2\2*\f\3\2\2\2+,\7*\2\2,\16\3\2\2\2-.\7+\2\2.\20\3\2\2\2/\60\7"+
118+
"U\2\2\60@\7H\2\2\61\62\7R\2\2\62@\7\63\2\2\63\64\7R\2\2\64@\7\64\2\2\65"+
119+
"\66\7R\2\2\66@\7\65\2\2\678\7R\2\28@\7\66\2\29:\7D\2\2:@\7H\2\2;<\7T\2"+
120+
"\2<@\7F\2\2=>\7R\2\2>@\7T\2\2?/\3\2\2\2?\61\3\2\2\2?\63\3\2\2\2?\65\3"+
121+
"\2\2\2?\67\3\2\2\2?9\3\2\2\2?;\3\2\2\2?=\3\2\2\2@\22\3\2\2\2AC\t\2\2\2"+
122+
"BA\3\2\2\2CD\3\2\2\2DB\3\2\2\2DE\3\2\2\2E\24\3\2\2\2FH\7$\2\2GI\4#\u0080"+
123+
"\2HG\3\2\2\2IJ\3\2\2\2JH\3\2\2\2JK\3\2\2\2KL\3\2\2\2LM\7$\2\2M\26\3\2"+
124+
"\2\2NO\t\3\2\2O\30\3\2\2\2PR\t\4\2\2QP\3\2\2\2RS\3\2\2\2SQ\3\2\2\2ST\3"+
125+
"\2\2\2T[\3\2\2\2UW\7\60\2\2VX\t\4\2\2WV\3\2\2\2XY\3\2\2\2YW\3\2\2\2YZ"+
126+
"\3\2\2\2Z\\\3\2\2\2[U\3\2\2\2[\\\3\2\2\2\\\32\3\2\2\2]a\t\5\2\2^`\t\6"+
127+
"\2\2_^\3\2\2\2`c\3\2\2\2a_\3\2\2\2ab\3\2\2\2b\34\3\2\2\2ca\3\2\2\2df\7"+
128+
"\17\2\2ed\3\2\2\2ef\3\2\2\2fg\3\2\2\2gh\7\f\2\2h\36\3\2\2\2ik\t\7\2\2"+
129+
"ji\3\2\2\2kl\3\2\2\2lj\3\2\2\2lm\3\2\2\2mn\3\2\2\2no\b\20\2\2o \3\2\2"+
130+
"\2\f\2?DJSY[ael\3\b\2\2";
130131
public static final ATN _ATN =
131132
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
132133
static {

src/main/java/xyz/javecs/tools/text2expr/parser/Text2ExprLexer.tokens

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@ T__4=5
66
T__5=6
77
T__6=7
88
PREFIX=8
9-
LEVEL=9
10-
JAPANESE=10
11-
SYMBOL=11
12-
OPERATOR=12
13-
NUMBER=13
14-
ID=14
15-
NEWLINE=15
16-
WS=16
9+
JAPANESE=9
10+
SYMBOL=10
11+
OPERATOR=11
12+
NUMBER=12
13+
ID=13
14+
NEWLINE=14
15+
WS=15
1716
'='=1
1817
','=2
1918
':'=3

src/main/java/xyz/javecs/tools/text2expr/parser/Text2ExprParser.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ public class Text2ExprParser extends Parser {
1717
protected static final PredictionContextCache _sharedContextCache =
1818
new PredictionContextCache();
1919
public static final int
20-
T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, PREFIX=8, LEVEL=9,
21-
JAPANESE=10, SYMBOL=11, OPERATOR=12, NUMBER=13, ID=14, NEWLINE=15, WS=16;
20+
T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, PREFIX=8, JAPANESE=9,
21+
SYMBOL=10, OPERATOR=11, NUMBER=12, ID=13, NEWLINE=14, WS=15;
2222
public static final int
2323
RULE_text2expr = 0, RULE_text = 1, RULE_word = 2, RULE_field = 3, RULE_value = 4,
2424
RULE_expr = 5, RULE_optionalValue = 6;
@@ -30,7 +30,7 @@ public class Text2ExprParser extends Parser {
3030
null, "'='", "','", "':'", "'?'", "'|'", "'('", "')'"
3131
};
3232
private static final String[] _SYMBOLIC_NAMES = {
33-
null, null, null, null, null, null, null, null, "PREFIX", "LEVEL", "JAPANESE",
33+
null, null, null, null, null, null, null, null, "PREFIX", "JAPANESE",
3434
"SYMBOL", "OPERATOR", "NUMBER", "ID", "NEWLINE", "WS"
3535
};
3636
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
@@ -143,7 +143,7 @@ public final Text2exprContext text2expr() throws RecognitionException {
143143
setState(23);
144144
_errHandler.sync(this);
145145
_la = _input.LA(1);
146-
} while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__1) | (1L << T__2) | (1L << T__3) | (1L << T__4) | (1L << T__5) | (1L << T__6) | (1L << PREFIX) | (1L << LEVEL) | (1L << JAPANESE) | (1L << SYMBOL) | (1L << OPERATOR) | (1L << NUMBER) | (1L << ID) | (1L << NEWLINE) | (1L << WS))) != 0) );
146+
} while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__1) | (1L << T__2) | (1L << T__3) | (1L << T__4) | (1L << T__5) | (1L << T__6) | (1L << PREFIX) | (1L << JAPANESE) | (1L << SYMBOL) | (1L << OPERATOR) | (1L << NUMBER) | (1L << ID) | (1L << NEWLINE) | (1L << WS))) != 0) );
147147
}
148148
}
149149
catch (RecognitionException re) {
@@ -613,7 +613,7 @@ private boolean value_sempred(ValueContext _localctx, int predIndex) {
613613
}
614614

615615
public static final String _serializedATN =
616-
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\22T\4\2\t\2\4\3\t"+
616+
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\21T\4\2\t\2\4\3\t"+
617617
"\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\3\2\6\2\22\n\2\r\2\16\2\23"+
618618
"\3\2\3\2\6\2\30\n\2\r\2\16\2\31\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\5\3$\n"+
619619
"\3\3\4\3\4\3\4\3\4\3\4\3\4\7\4,\n\4\f\4\16\4/\13\4\3\5\3\5\3\5\3\5\3\6"+
@@ -622,18 +622,18 @@ private boolean value_sempred(ValueContext _localctx, int predIndex) {
622622
"\n\t\2\4\6\b\n\f\16\2\3\3\2\5\6\2V\2\21\3\2\2\2\4#\3\2\2\2\6%\3\2\2\2"+
623623
"\b\60\3\2\2\2\n=\3\2\2\2\fM\3\2\2\2\16O\3\2\2\2\20\22\5\4\3\2\21\20\3"+
624624
"\2\2\2\22\23\3\2\2\2\23\21\3\2\2\2\23\24\3\2\2\2\24\25\3\2\2\2\25\27\7"+
625-
"\21\2\2\26\30\5\f\7\2\27\26\3\2\2\2\30\31\3\2\2\2\31\27\3\2\2\2\31\32"+
626-
"\3\2\2\2\32\3\3\2\2\2\33\34\5\6\4\2\34\35\7\21\2\2\35$\3\2\2\2\36\37\7"+
627-
"\20\2\2\37 \7\3\2\2 !\5\6\4\2!\"\7\21\2\2\"$\3\2\2\2#\33\3\2\2\2#\36\3"+
625+
"\20\2\2\26\30\5\f\7\2\27\26\3\2\2\2\30\31\3\2\2\2\31\27\3\2\2\2\31\32"+
626+
"\3\2\2\2\32\3\3\2\2\2\33\34\5\6\4\2\34\35\7\20\2\2\35$\3\2\2\2\36\37\7"+
627+
"\17\2\2\37 \7\3\2\2 !\5\6\4\2!\"\7\20\2\2\"$\3\2\2\2#\33\3\2\2\2#\36\3"+
628628
"\2\2\2$\5\3\2\2\2%&\b\4\1\2&\'\5\b\5\2\'-\3\2\2\2()\f\4\2\2)*\7\4\2\2"+
629629
"*,\5\6\4\5+(\3\2\2\2,/\3\2\2\2-+\3\2\2\2-.\3\2\2\2.\7\3\2\2\2/-\3\2\2"+
630630
"\2\60\61\7\n\2\2\61\62\t\2\2\2\62\63\5\n\6\2\63\t\3\2\2\2\64\65\b\6\1"+
631-
"\2\65\67\7\f\2\2\668\5\16\b\2\67\66\3\2\2\2\678\3\2\2\28>\3\2\2\29;\7"+
632-
"\r\2\2:<\5\16\b\2;:\3\2\2\2;<\3\2\2\2<>\3\2\2\2=\64\3\2\2\2=9\3\2\2\2"+
631+
"\2\65\67\7\13\2\2\668\5\16\b\2\67\66\3\2\2\2\678\3\2\2\28>\3\2\2\29;\7"+
632+
"\f\2\2:<\5\16\b\2;:\3\2\2\2;<\3\2\2\2<>\3\2\2\2=\64\3\2\2\2=9\3\2\2\2"+
633633
">D\3\2\2\2?@\f\5\2\2@A\7\7\2\2AC\5\n\6\6B?\3\2\2\2CF\3\2\2\2DB\3\2\2\2"+
634634
"DE\3\2\2\2E\13\3\2\2\2FD\3\2\2\2GI\13\2\2\2HG\3\2\2\2IJ\3\2\2\2JH\3\2"+
635-
"\2\2JK\3\2\2\2KN\3\2\2\2LN\7\21\2\2MH\3\2\2\2ML\3\2\2\2N\r\3\2\2\2OP\7"+
636-
"\b\2\2PQ\7\17\2\2QR\7\t\2\2R\17\3\2\2\2\f\23\31#-\67;=DJM";
635+
"\2\2JK\3\2\2\2KN\3\2\2\2LN\7\20\2\2MH\3\2\2\2ML\3\2\2\2N\r\3\2\2\2OP\7"+
636+
"\b\2\2PQ\7\16\2\2QR\7\t\2\2R\17\3\2\2\2\f\23\31#-\67;=DJM";
637637
public static final ATN _ATN =
638638
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
639639
static {

src/main/kotlin/xyz/javecs/tools/text2expr/rules/RuleBuilder.kt

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import com.atilika.kuromoji.ipadic.Token
44
import com.atilika.kuromoji.ipadic.Tokenizer
55
import xyz.javecs.tools.expr.Calculator
66
import xyz.javecs.tools.text2expr.utils.normalize
7+
import javax.swing.text.html.Option
78

9+
private val NotFound = -2
10+
private val Optional = -3
811
private val tokenizer = Tokenizer()
912
data class Evaluation(val value: Number = Double.NaN, val expr: List<String> = ArrayList(), val variables: Map<String, Double> = HashMap())
1013
class RuleBuilder(source: String, val name: String = "") {
@@ -13,8 +16,8 @@ class RuleBuilder(source: String, val name: String = "") {
1316
parser.visit(parser(source).text2expr())
1417
}
1518

16-
private fun indexOf(word: Word, tokens: List<Token>, start: Int): Int {
17-
for (i in start..tokens.lastIndex) {
19+
private fun indexOf(word: Word, tokens: List<Token>, start: Int, end: Int): Pair<Int, Boolean> {
20+
for (i in start..end) {
1821
val token = tokens[i]
1922
var matched = 0
2023
for ((key, value) in word.fields) {
@@ -29,9 +32,9 @@ class RuleBuilder(source: String, val name: String = "") {
2932
"PR" -> if (value.contains(token.pronunciation)) matched++
3033
}
3134
}
32-
if (word.fields.size == matched) return i
35+
if (word.fields.size == matched) return Pair(i, false)
3336
}
34-
return -1
37+
return if (word.isOptional()) Pair(Optional, true) else Pair(NotFound, false)
3538
}
3639

3740
fun rule(): Array<Word> = parser.rule.toTypedArray()
@@ -43,11 +46,17 @@ class RuleBuilder(source: String, val name: String = "") {
4346

4447
fun matches(text: String, recognizedId: (id: Pair<String, String>) -> Unit = {}): Boolean {
4548
val tokens = tokenizer.tokenize(text)
46-
var start = -1
49+
var offset = -1
50+
var remained = rule().size
4751
rule().forEach {
48-
start = indexOf(it, tokens, start + 1)
49-
if (start < 0) return false
50-
if (it.id.isNotEmpty()) recognizedId(Pair(it.id, tokens[start].surface))
52+
val (index, optional) = indexOf(it, tokens, start = offset + 1, end = Math.min(tokens.size - remained, tokens.lastIndex))
53+
if (index == NotFound) return false
54+
if (it.id.isNotEmpty()) {
55+
val value = if (optional) it.optionalValue().toString() else tokens[index].surface
56+
recognizedId(Pair(it.id, value))
57+
}
58+
if (!optional) offset = index
59+
remained--
5160
}
5261
return true
5362
}

src/main/kotlin/xyz/javecs/tools/text2expr/rules/RuleParser.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import xyz.javecs.tools.text2expr.parser.Text2ExprLexer
77
import xyz.javecs.tools.text2expr.parser.Text2ExprParser
88

99
data class Field(var key: String = "", var value: MutableList<String> = ArrayList(), var isOptional: Boolean = false, var optionalValue: Double = Double.NaN)
10-
class Word(var fields: MutableList<Field> = ArrayList(), val id: String = "")
10+
class Word(var fields: MutableList<Field> = ArrayList(), val id: String = "") {
11+
fun isOptional() = fields.find { it.isOptional } != null
12+
fun optionalValue(): Double? = fields.find { it.isOptional }?.optionalValue
13+
}
1114

1215
internal fun parser(source: String): Text2ExprParser {
1316
val charStream = CharStreams.fromString(source)

src/main/resources/rules/length/mileToKilometer.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
x=P2:数
1+
x = P2?数(1)
22
SF:マイル|"mile"
33
SF:キロメートル|キロ|"km"
44

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
SF:時速
22
x=P2:数
33
SF:キロメートル|キロ|"km"
4-
y=P2:数
5-
SF:秒間
4+
y=P2?数(1)
5+
SF?秒間
66
SF:メートル|"m"
77

88
(x * 1000 / 3600) * y

0 commit comments

Comments
 (0)