diff options
-rw-r--r-- | LuaSL/src/LuaSL_LSL_tree.c | 605 | ||||
-rw-r--r-- | LuaSL/src/LuaSL_LSL_tree.h | 95 | ||||
-rw-r--r-- | LuaSL/src/LuaSL_lemon_yaccer.y | 3 | ||||
-rw-r--r-- | LuaSL/src/LuaSL_lexer.l | 6 | ||||
-rw-r--r-- | LuaSL/test.lsl | 2 |
5 files changed, 508 insertions, 203 deletions
diff --git a/LuaSL/src/LuaSL_LSL_tree.c b/LuaSL/src/LuaSL_LSL_tree.c index d26a31e..5c97719 100644 --- a/LuaSL/src/LuaSL_LSL_tree.c +++ b/LuaSL/src/LuaSL_LSL_tree.c | |||
@@ -3,11 +3,13 @@ | |||
3 | #include <stdlib.h> | 3 | #include <stdlib.h> |
4 | #include <stdio.h> | 4 | #include <stdio.h> |
5 | 5 | ||
6 | static void evaluateIntegerToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right); | 6 | static LSL_Leaf *evaluateFloatToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right); |
7 | static void evaluateNoToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right); | 7 | static LSL_Leaf *evaluateIntegerToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right); |
8 | static void evaluateOperationToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right); | 8 | static LSL_Leaf *evaluateNoToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right); |
9 | static void eveluateParenthesisToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right); | 9 | static LSL_Leaf *evaluateOperationToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right); |
10 | static void evaluateStatementToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right); | 10 | static LSL_Leaf *eveluateParenthesisToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right); |
11 | static LSL_Leaf *evaluateStatementToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right); | ||
12 | static void outputFloatToken(FILE *file, LSL_Leaf *content); | ||
11 | static void outputIntegerToken(FILE *file, LSL_Leaf *content); | 13 | static void outputIntegerToken(FILE *file, LSL_Leaf *content); |
12 | static void outputParenthesisToken(FILE *file, LSL_Leaf *content); | 14 | static void outputParenthesisToken(FILE *file, LSL_Leaf *content); |
13 | static void outputStatementToken(FILE *file, LSL_Leaf *content); | 15 | static void outputStatementToken(FILE *file, LSL_Leaf *content); |
@@ -15,112 +17,164 @@ static void outputStatementToken(FILE *file, LSL_Leaf *content); | |||
15 | LSL_Token LSL_Tokens[] = | 17 | LSL_Token LSL_Tokens[] = |
16 | { | 18 | { |
17 | // Various forms of "space". | 19 | // Various forms of "space". |
18 | {LSL_COMMENT, "/*", LSL_NONE, NULL, NULL, NULL}, | 20 | {LSL_COMMENT, ST_NONE, "/*", LSL_NONE, NULL, NULL, NULL}, |
19 | {LSL_COMMENT_LINE, "//", LSL_NONE, NULL, NULL, NULL}, | 21 | {LSL_COMMENT_LINE, ST_NONE, "//", LSL_NONE, NULL, NULL, NULL}, |
20 | {LSL_SPACE, " ", LSL_NONE, NULL, NULL, NULL}, | 22 | {LSL_SPACE, ST_NONE, " ", LSL_NONE, NULL, NULL, NULL}, |
21 | 23 | ||
22 | // Operators, in order of precedence, low to high | 24 | // Operators, in order of precedence, low to high |
23 | // Left to right, unless oterwise stated. | 25 | // Left to right, unless oterwise stated. |
24 | // According to http://wiki.secondlife.com/wiki/Category:LSL_Operators | 26 | // According to http://wiki.secondlife.com/wiki/Category:LSL_Operators |
25 | {LSL_BOOL_AND, "&&", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, | 27 | {LSL_BOOL_AND, ST_BOOLEAN, "&&", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, |
26 | // QUIRK - Seems to be some disagreement about BOOL_AND/BOOL_OR precedence. Either they are equal, or OR is higher. | 28 | // QUIRK - Seems to be some disagreement about BOOL_AND/BOOL_OR precedence. Either they are equal, or OR is higher. |
27 | // QUIRK - No boolean short circuiting. | 29 | // QUIRK - No boolean short circuiting. |
28 | // QUIRK - Booleans and conditionals are executed right to left. Or maybe not, depending on who you believe. | 30 | // QUIRK - Booleans and conditionals are executed right to left. Or maybe not, depending on who you believe. |
29 | {LSL_BOOL_OR, "||", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, | 31 | {LSL_BOOL_OR, ST_BOOLEAN, "||", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, |
30 | {LSL_BIT_OR, "|", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 32 | {LSL_BIT_OR, ST_BITWISE, "|", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
31 | {LSL_BIT_XOR, "^", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 33 | {LSL_BIT_XOR, ST_BITWISE, "^", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
32 | {LSL_BIT_AND, "&", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 34 | {LSL_BIT_AND, ST_BITWISE, "&", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
33 | // QUIRK - Booleans and conditionals are executed right to left. Or maybe not, depending on who you believe. | 35 | // QUIRK - Booleans and conditionals are executed right to left. Or maybe not, depending on who you believe. |
34 | {LSL_NOT_EQUAL, "!=", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, | 36 | {LSL_NOT_EQUAL, ST_EQUALITY, "!=", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, |
35 | {LSL_EQUAL, "==", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, | 37 | {LSL_EQUAL, ST_EQUALITY, "==", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, |
36 | {LSL_GREATER_EQUAL, ">=", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, | 38 | {LSL_GREATER_EQUAL, ST_COMPARISON, ">=", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, |
37 | {LSL_LESS_EQUAL, "<=", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, | 39 | {LSL_LESS_EQUAL, ST_COMPARISON, "<=", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, |
38 | {LSL_GREATER_THAN, ">", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, | 40 | {LSL_GREATER_THAN, ST_COMPARISON, ">", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, |
39 | {LSL_LESS_THAN, "<", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, | 41 | {LSL_LESS_THAN, ST_COMPARISON, "<", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, |
40 | {LSL_RIGHT_SHIFT, ">>", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 42 | {LSL_RIGHT_SHIFT, ST_BITWISE, ">>", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
41 | {LSL_LEFT_SHIFT, "<<", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 43 | {LSL_LEFT_SHIFT, ST_BITWISE, "<<", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
42 | // {LSL_CONCATENATE, "+", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 44 | // {LSL_CONCATENATE, ST_ADD, "+", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
43 | {LSL_ADD, "+", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 45 | {LSL_ADD, ST_ADD, "+", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
44 | {LSL_SUBTRACT, "-", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 46 | {LSL_SUBTRACT, ST_SUBTRACT, "-", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
45 | // {LSL_CROSS_PRODUCT, "%", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 47 | // {LSL_CROSS_PRODUCT, ST_NONE, "%", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
46 | // {LSL_DOT_PRODUCT, "*", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 48 | // {LSL_DOT_PRODUCT, ST_NONE, "*", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
47 | {LSL_MULTIPLY, "*", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 49 | {LSL_MULTIPLY, ST_MULTIPLY, "*", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
48 | {LSL_MODULO, "%", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 50 | {LSL_MODULO, ST_MODULO, "%", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
49 | {LSL_DIVIDE, "/", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 51 | {LSL_DIVIDE, ST_MULTIPLY, "/", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
50 | {LSL_NEGATION, "-", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, | 52 | {LSL_NEGATION, ST_NEGATE, "-", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, |
51 | {LSL_BOOL_NOT, "!", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, | 53 | {LSL_BOOL_NOT, ST_BOOL_NOT, "!", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, |
52 | {LSL_BIT_NOT, "~", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, | 54 | {LSL_BIT_NOT, ST_BIT_NOT, "~", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, |
53 | // {LSL_TYPECAST_CLOSE, ")", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, | 55 | // {LSL_TYPECAST_CLOSE, ST_NONE, ")", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, |
54 | // {LSL_TYPECAST_OPEN, "(", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, | 56 | // {LSL_TYPECAST_OPEN, ST_NONE, "(", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, |
55 | {LSL_ANGLE_CLOSE, ">", LSL_LEFT2RIGHT | LSL_CREATION, NULL, NULL, evaluateOperationToken}, | 57 | {LSL_ANGLE_CLOSE, ST_NONE, ">", LSL_LEFT2RIGHT | LSL_CREATION, NULL, NULL, evaluateOperationToken}, |
56 | {LSL_ANGLE_OPEN, "<", LSL_LEFT2RIGHT | LSL_CREATION, NULL, NULL, evaluateOperationToken}, | 58 | {LSL_ANGLE_OPEN, ST_NONE, "<", LSL_LEFT2RIGHT | LSL_CREATION, NULL, NULL, evaluateOperationToken}, |
57 | {LSL_BRACKET_CLOSE, "]", LSL_INNER2OUTER | LSL_CREATION, NULL, NULL, evaluateOperationToken}, | 59 | {LSL_BRACKET_CLOSE, ST_NONE, "]", LSL_INNER2OUTER | LSL_CREATION, NULL, NULL, evaluateOperationToken}, |
58 | {LSL_BRACKET_OPEN, "[", LSL_INNER2OUTER | LSL_CREATION, NULL, NULL, evaluateOperationToken}, | 60 | {LSL_BRACKET_OPEN, ST_NONE, "[", LSL_INNER2OUTER | LSL_CREATION, NULL, NULL, evaluateOperationToken}, |
59 | {LSL_PARENTHESIS_CLOSE, ")", LSL_INNER2OUTER, NULL, NULL, evaluateNoToken}, | 61 | {LSL_PARENTHESIS_CLOSE, ST_NONE, ")", LSL_INNER2OUTER, NULL, NULL, evaluateNoToken}, |
60 | {LSL_PARENTHESIS_OPEN, "(", LSL_INNER2OUTER, outputParenthesisToken, NULL, eveluateParenthesisToken}, | 62 | {LSL_PARENTHESIS_OPEN, ST_NONE, "(", LSL_INNER2OUTER, outputParenthesisToken, NULL, eveluateParenthesisToken}, |
61 | // {LSL_ASSIGNMENT_CONCATENATE, "+=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, | 63 | // {LSL_ASSIGNMENT_CONCATENATE, ST_CONCATENATION "+=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, |
62 | {LSL_ASSIGNMENT_ADD, "+=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, | 64 | {LSL_ASSIGNMENT_ADD, ST_CONCATENATION, "+=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, |
63 | {LSL_ASSIGNMENT_SUBTRACT, "-=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, | 65 | {LSL_ASSIGNMENT_SUBTRACT, ST_ASSIGNMENT, "-=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, |
64 | {LSL_ASSIGNMENT_MULTIPLY, "*=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, | 66 | {LSL_ASSIGNMENT_MULTIPLY, ST_ASSIGNMENT, "*=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, |
65 | {LSL_ASSIGNMENT_MODULO, "%=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, | 67 | {LSL_ASSIGNMENT_MODULO, ST_MODULO, "%=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, |
66 | {LSL_ASSIGNMENT_DIVIDE, "/=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, | 68 | {LSL_ASSIGNMENT_DIVIDE, ST_ASSIGNMENT, "/=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, |
67 | {LSL_ASSIGNMENT_PLAIN, "=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, | 69 | {LSL_ASSIGNMENT_PLAIN, ST_CONCATENATION, "=", LSL_RIGHT2LEFT | LSL_ASSIGNMENT, NULL, NULL, evaluateOperationToken}, |
68 | {LSL_DOT, ".", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, | 70 | {LSL_DOT, ST_NONE, ".", LSL_RIGHT2LEFT, NULL, NULL, evaluateOperationToken}, |
69 | // {LSL_DECREMENT_POST, "--", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, | 71 | // {LSL_DECREMENT_POST, ST_NONE, "--", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, |
70 | {LSL_DECREMENT_PRE, "--", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, | 72 | {LSL_DECREMENT_PRE, ST_NONE, "--", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, |
71 | // {LSL_INCREMENT_POST, "++", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, | 73 | // {LSL_INCREMENT_POST, ST_NONE, "++", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, |
72 | {LSL_INCREMENT_PRE, "++", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, | 74 | {LSL_INCREMENT_PRE, ST_NONE, "++", LSL_RIGHT2LEFT | LSL_UNARY, NULL, NULL, evaluateOperationToken}, |
73 | {LSL_COMMA, ",", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, | 75 | {LSL_COMMA, ST_NONE, ",", LSL_LEFT2RIGHT, NULL, NULL, evaluateOperationToken}, |
74 | 76 | ||
75 | {LSL_EXPRESSION, "expression", LSL_NONE, NULL, NULL, NULL}, | 77 | {LSL_EXPRESSION, ST_NONE, "expression", LSL_NONE , NULL, NULL, NULL}, |
76 | 78 | ||
77 | // Types. | 79 | // Types. |
78 | {LSL_FLOAT, "float", LSL_NONE, NULL, NULL, NULL}, | 80 | {LSL_FLOAT, ST_NONE, "float", LSL_NONE, outputFloatToken, NULL, evaluateFloatToken}, |
79 | {LSL_INTEGER, "integer", LSL_NONE, outputIntegerToken, NULL, evaluateIntegerToken}, | 81 | {LSL_INTEGER, ST_NONE, "integer", LSL_NONE, outputIntegerToken, NULL, evaluateIntegerToken}, |
80 | // {LSL_KEY, "key", LSL_NONE, NULL, NULL, NULL}, | 82 | // {LSL_KEY, ST_NONE, "key", LSL_NONE, NULL, NULL, NULL}, |
81 | // {LSL_LIST, "list", LSL_NONE, NULL, NULL, NULL}, | 83 | // {LSL_LIST, ST_NONE, "list", LSL_NONE, NULL, NULL, NULL}, |
82 | // {LSL_ROTATION, "rotation", LSL_NONE, NULL, NULL, NULL}, | 84 | // {LSL_ROTATION, ST_NONE, "rotation", LSL_NONE, NULL, NULL, NULL}, |
83 | // {LSL_STRING, "string", LSL_NONE, NULL, NULL, NULL}, | 85 | // {LSL_STRING, ST_NONE, "string", LSL_NONE, NULL, NULL, NULL}, |
84 | // {LSL_VECTOR, "vector", LSL_NONE, NULL, NULL, NULL}, | 86 | // {LSL_VECTOR, ST_NONE, "vector", LSL_NONE, NULL, NULL, NULL}, |
85 | 87 | ||
86 | // Types names. | 88 | // Types names. |
87 | {LSL_TYPE_FLOAT, "float", LSL_NONE, NULL, NULL, NULL}, | 89 | {LSL_TYPE_FLOAT, ST_NONE, "float", LSL_NONE, NULL, NULL, NULL}, |
88 | {LSL_TYPE_INTEGER, "integer", LSL_NONE, NULL, NULL, NULL}, | 90 | {LSL_TYPE_INTEGER, ST_NONE, "integer", LSL_NONE, NULL, NULL, NULL}, |
89 | {LSL_TYPE_KEY, "key", LSL_NONE, NULL, NULL, NULL}, | 91 | {LSL_TYPE_KEY, ST_NONE, "key", LSL_NONE, NULL, NULL, NULL}, |
90 | {LSL_TYPE_LIST, "list", LSL_NONE, NULL, NULL, NULL}, | 92 | {LSL_TYPE_LIST, ST_NONE, "list", LSL_NONE, NULL, NULL, NULL}, |
91 | {LSL_TYPE_ROTATION, "rotation", LSL_NONE, NULL, NULL, NULL}, | 93 | {LSL_TYPE_ROTATION, ST_NONE, "rotation", LSL_NONE, NULL, NULL, NULL}, |
92 | {LSL_TYPE_STRING, "string", LSL_NONE, NULL, NULL, NULL}, | 94 | {LSL_TYPE_STRING, ST_NONE, "string", LSL_NONE, NULL, NULL, NULL}, |
93 | {LSL_TYPE_VECTOR, "vector", LSL_NONE, NULL, NULL, NULL}, | 95 | {LSL_TYPE_VECTOR, ST_NONE, "vector", LSL_NONE, NULL, NULL, NULL}, |
94 | 96 | ||
95 | // Then the rest of the syntax tokens. | 97 | // Then the rest of the syntax tokens. |
96 | {LSL_IDENTIFIER, "identifier", LSL_NONE, NULL, NULL, NULL}, | 98 | {LSL_IDENTIFIER, ST_NONE, "identifier", LSL_NONE, NULL, NULL, NULL}, |
97 | 99 | ||
98 | {LSL_LABEL, "@", LSL_NONE, NULL, NULL, NULL}, | 100 | {LSL_LABEL, ST_NONE, "@", LSL_NONE, NULL, NULL, NULL}, |
99 | 101 | ||
100 | {LSL_DO, "do", LSL_NONE, NULL, NULL, NULL}, | 102 | {LSL_DO, ST_NONE, "do", LSL_NONE, NULL, NULL, NULL}, |
101 | {LSL_FOR, "for", LSL_NONE, NULL, NULL, NULL}, | 103 | {LSL_FOR, ST_NONE, "for", LSL_NONE, NULL, NULL, NULL}, |
102 | // {LSL_ELSE_IF, "else if", LSL_NONE, NULL, NULL, NULL}, | 104 | // {LSL_ELSE_IF, ST_NONE, "else if", LSL_NONE, NULL, NULL, NULL}, |
103 | {LSL_ELSE, "else", LSL_NONE, NULL, NULL, NULL}, | 105 | {LSL_ELSE, ST_NONE, "else", LSL_NONE, NULL, NULL, NULL}, |
104 | {LSL_IF, "if", LSL_NONE, NULL, NULL, NULL}, | 106 | {LSL_IF, ST_NONE, "if", LSL_NONE, NULL, NULL, NULL}, |
105 | {LSL_JUMP, "jump", LSL_NONE, NULL, NULL, NULL}, | 107 | {LSL_JUMP, ST_NONE, "jump", LSL_NONE, NULL, NULL, NULL}, |
106 | {LSL_RETURN, "return", LSL_NONE, NULL, NULL, NULL}, | 108 | {LSL_RETURN, ST_NONE, "return", LSL_NONE, NULL, NULL, NULL}, |
107 | {LSL_STATE_CHANGE, "state", LSL_NONE, NULL, NULL, NULL}, | 109 | {LSL_STATE_CHANGE, ST_NONE, "state", LSL_NONE, NULL, NULL, NULL}, |
108 | {LSL_WHILE, "while", LSL_NONE, NULL, NULL, NULL}, | 110 | {LSL_WHILE, ST_NONE, "while", LSL_NONE, NULL, NULL, NULL}, |
109 | {LSL_STATEMENT, ";", LSL_NOIGNORE, outputStatementToken, NULL, evaluateStatementToken}, | 111 | {LSL_STATEMENT, ST_NONE, ";", LSL_NOIGNORE, outputStatementToken, NULL, evaluateStatementToken}, |
110 | 112 | ||
111 | {LSL_BLOCK_CLOSE, "}", LSL_NONE, NULL, NULL, NULL}, | 113 | {LSL_BLOCK_CLOSE, ST_NONE, "}", LSL_NONE, NULL, NULL, NULL}, |
112 | {LSL_BLOCK_OPEN, "{", LSL_NONE, NULL, NULL, NULL}, | 114 | {LSL_BLOCK_OPEN, ST_NONE, "{", LSL_NONE, NULL, NULL, NULL}, |
113 | // {LSL_PARAMETER, "parameter", LSL_NONE, NULL, NULL, NULL}, | 115 | // {LSL_PARAMETER, ST_NONE, "parameter", LSL_NONE, NULL, NULL, NULL}, |
114 | // {LSL_FUNCTION, "function", LSL_NONE, NULL, NULL, NULL}, | 116 | // {LSL_FUNCTION, ST_NONE, "function", LSL_NONE, NULL, NULL, NULL}, |
115 | // {LSL_STATE, "state", LSL_NONE, NULL, NULL, NULL}, | 117 | // {LSL_STATE, ST_NONE, "state", LSL_NONE, NULL, NULL, NULL}, |
116 | {LSL_SCRIPT, "", LSL_NONE, NULL, NULL, NULL}, | 118 | {LSL_SCRIPT, ST_NONE, "", LSL_NONE, NULL, NULL, NULL}, |
117 | 119 | ||
118 | {LSL_UNKNOWN, "unknown", LSL_NONE, NULL, NULL, NULL}, | 120 | {LSL_UNKNOWN, ST_NONE, "unknown", LSL_NONE, NULL, NULL, NULL}, |
119 | 121 | ||
120 | // A sentinal. | 122 | // A sentinal. |
121 | {999999, NULL, LSL_NONE, NULL, NULL, NULL} | 123 | {999999, ST_NONE, NULL, LSL_NONE, NULL, NULL, NULL} |
122 | }; | 124 | }; |
123 | 125 | ||
126 | allowedTypes allowed[] = | ||
127 | { | ||
128 | {OT_nothing, (ST_NONE)}, | ||
129 | |||
130 | {OT_bool, (ST_BOOL_NOT)}, | ||
131 | {OT_integer, (ST_BIT_NOT | ST_NEGATE)}, | ||
132 | {OT_float, (ST_NONE)}, | ||
133 | {OT_key, (ST_NONE)}, | ||
134 | {OT_list, (ST_NONE)}, | ||
135 | {OT_rotation, (ST_NONE)}, | ||
136 | {OT_string, (ST_NONE)}, | ||
137 | {OT_vector, (ST_NONE)}, | ||
138 | {OT_other, (ST_NONE)}, | ||
139 | |||
140 | {OT_bool, (ST_BOOLEAN | ST_EQUALITY)}, | ||
141 | {OT_integer, (ST_MULTIPLY | ST_ADD | ST_SUBTRACT | ST_EQUALITY | ST_COMPARISON | ST_CONCATENATION | ST_ASSIGNMENT | ST_MODULO | ST_BITWISE)}, | ||
142 | {OT_float, (ST_MULTIPLY | ST_ADD | ST_SUBTRACT | ST_EQUALITY | ST_COMPARISON | ST_CONCATENATION | ST_ASSIGNMENT)}, | ||
143 | {OT_float, (ST_MULTIPLY | ST_ADD | ST_SUBTRACT | ST_EQUALITY | ST_COMPARISON | ST_CONCATENATION | ST_ASSIGNMENT)}, | ||
144 | {OT_float, (ST_MULTIPLY | ST_ADD | ST_SUBTRACT | ST_EQUALITY | ST_COMPARISON | ST_CONCATENATION | ST_ASSIGNMENT)}, | ||
145 | {OT_string, (ST_ADD | ST_EQUALITY | ST_CONCATENATION)}, | ||
146 | {OT_string, (ST_ADD | ST_EQUALITY | ST_CONCATENATION)}, | ||
147 | {OT_string, (ST_ADD | ST_EQUALITY | ST_CONCATENATION)}, | ||
148 | {OT_list, (ST_ADD | ST_EQUALITY | ST_CONCATENATION)}, | ||
149 | {OT_list, (ST_ADD | ST_COMPARISON | ST_CONCATENATION)}, | ||
150 | {OT_list, (ST_ADD | ST_COMPARISON | ST_CONCATENATION)}, | ||
151 | {OT_integer, (ST_ADD | ST_COMPARISON)}, | ||
152 | {OT_float, (ST_ADD | ST_COMPARISON)}, | ||
153 | {OT_list, (ST_ADD | ST_CONCATENATION)}, | ||
154 | {OT_vector, (ST_MULTIPLY | ST_ADD | ST_SUBTRACT | ST_EQUALITY | ST_CONCATENATION | ST_ASSIGNMENT | ST_MODULO)}, | ||
155 | {OT_vector, (ST_MULTIPLY)}, | ||
156 | {OT_vector, (ST_MULTIPLY)}, | ||
157 | {OT_rotation, (ST_MULTIPLY | ST_ADD | ST_SUBTRACT | ST_EQUALITY | ST_CONCATENATION | ST_ASSIGNMENT)}, | ||
158 | {OT_other, (ST_NONE)}, | ||
159 | {OT_invalid, (ST_NONE)} | ||
160 | }; | ||
161 | |||
162 | opType opExpr[][10] = | ||
163 | { | ||
164 | {OT_nothing, OT_bool, OT_integer, OT_float, OT_key, OT_list, OT_rotation, OT_string, OT_vector, OT_other}, | ||
165 | {OT_bool, OT_boolBool, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_invalid}, | ||
166 | {OT_integer, OT_invalid, OT_intInt, OT_intFloat, OT_invalid, OT_intList, OT_invalid, OT_invalid, OT_invalid, OT_invalid}, | ||
167 | {OT_float, OT_invalid, OT_floatInt, OT_floatFloat, OT_invalid, OT_floatList, OT_invalid, OT_invalid, OT_invalid, OT_invalid}, | ||
168 | {OT_key, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_keyString, OT_invalid, OT_invalid}, | ||
169 | {OT_list, OT_invalid, OT_listInt, OT_listFloat, OT_invalid, OT_listList, OT_invalid, OT_invalid, OT_invalid, OT_listOther}, | ||
170 | {OT_rotation, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_rotationRotation, OT_invalid, OT_invalid, OT_invalid}, | ||
171 | {OT_string, OT_invalid, OT_invalid, OT_invalid, OT_stringKey, OT_invalid, OT_invalid, OT_stringString, OT_invalid, OT_invalid}, | ||
172 | {OT_vector, OT_invalid, OT_invalid, OT_vectorFloat, OT_invalid, OT_invalid, OT_vectorRotation, OT_invalid, OT_vectorVector, OT_invalid}, | ||
173 | {OT_other, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_invalid, OT_otherOther} | ||
174 | |||
175 | }; | ||
176 | |||
177 | |||
124 | LSL_Token **tokens = NULL; | 178 | LSL_Token **tokens = NULL; |
125 | int lowestToken = 999999; | 179 | int lowestToken = 999999; |
126 | 180 | ||
@@ -157,8 +211,68 @@ LSL_Leaf *addOperation(LSL_Leaf *left, LSL_Leaf *lval, LSL_Leaf *right) | |||
157 | { | 211 | { |
158 | if (lval) | 212 | if (lval) |
159 | { | 213 | { |
214 | opType lType, rType; | ||
215 | |||
160 | lval->left = left; | 216 | lval->left = left; |
161 | lval->right = right; | 217 | lval->right = right; |
218 | |||
219 | // Try to figure out what type of operation this is. | ||
220 | if (NULL == left) | ||
221 | lType = OT_nothing; | ||
222 | else | ||
223 | { | ||
224 | lType = left->basicType; | ||
225 | if (OT_vector < lType) | ||
226 | lType = allowed[lType].result; | ||
227 | } | ||
228 | if (NULL == right) | ||
229 | rType = OT_nothing; | ||
230 | else | ||
231 | { | ||
232 | rType = right->basicType; | ||
233 | if (OT_vector < rType) | ||
234 | rType = allowed[rType].result; | ||
235 | } | ||
236 | |||
237 | // The basic lookup. | ||
238 | lval->basicType = opExpr[lType][rType]; | ||
239 | if (OT_invalid != lval->basicType) | ||
240 | { | ||
241 | // Check if it's an allowed operation. | ||
242 | if (0 == (lval->token->subType & allowed[lval->basicType].subTypes)) | ||
243 | { | ||
244 | lval->basicType = OT_invalid; | ||
245 | } | ||
246 | else | ||
247 | { | ||
248 | // Double check the corner cases. | ||
249 | switch (lval->token->subType) | ||
250 | { | ||
251 | case ST_BOOLEAN : | ||
252 | lval->basicType = OT_bool; | ||
253 | break; | ||
254 | case ST_COMPARISON : | ||
255 | lval->basicType = OT_bool; | ||
256 | break; | ||
257 | case ST_MULTIPLY : | ||
258 | if (OT_vectorVector == lval->basicType) | ||
259 | { | ||
260 | if (LSL_MULTIPLY == lval->token->type) | ||
261 | { | ||
262 | lval->basicType = OT_float; | ||
263 | // lval->token = tokens[LSL_DOT_PRODUCT - lowestToken]; | ||
264 | } | ||
265 | else | ||
266 | lval->basicType = OT_vector; | ||
267 | } | ||
268 | break; | ||
269 | default : | ||
270 | break; | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | if (OT_invalid == lval->basicType) | ||
275 | fprintf(stderr, "Invalid operation [%s] type at line %d column %d\n", lval->token->token, lval->line, lval->column); | ||
162 | } | 276 | } |
163 | 277 | ||
164 | return lval; | 278 | return lval; |
@@ -174,7 +288,10 @@ LSL_Leaf *addParenthesis(LSL_Leaf *lval, LSL_Leaf *expr, LSL_Leaf *rval) | |||
174 | parens->expression = expr; | 288 | parens->expression = expr; |
175 | parens->right = rval; | 289 | parens->right = rval; |
176 | if (lval) | 290 | if (lval) |
291 | { | ||
177 | lval->value.parenthesis = parens; | 292 | lval->value.parenthesis = parens; |
293 | lval->basicType = expr->basicType; | ||
294 | } | ||
178 | } | 295 | } |
179 | return lval; | 296 | return lval; |
180 | } | 297 | } |
@@ -194,69 +311,83 @@ LSL_Leaf *addStatement(LSL_Leaf *lval, LSL_Type type, LSL_Leaf *expr) | |||
194 | return lval; | 311 | return lval; |
195 | } | 312 | } |
196 | 313 | ||
197 | static void evaluateLeaf(LSL_Leaf *leaf, LSL_Leaf *left, LSL_Leaf *right) | 314 | static LSL_Leaf *evaluateLeaf(LSL_Leaf *leaf, LSL_Leaf *left, LSL_Leaf *right) |
198 | { | 315 | { |
316 | LSL_Leaf *result = NULL; | ||
317 | |||
199 | if (leaf) | 318 | if (leaf) |
200 | { | 319 | { |
201 | LSL_Leaf lresult; | 320 | LSL_Leaf *lresult = NULL; |
202 | LSL_Leaf rresult; | 321 | LSL_Leaf *rresult = NULL; |
203 | |||
204 | memcpy(&lresult, left, sizeof(LSL_Leaf)); | ||
205 | memcpy(&rresult, right, sizeof(LSL_Leaf)); | ||
206 | 322 | ||
207 | if (LSL_RIGHT2LEFT & leaf->token->flags) | 323 | if (LSL_RIGHT2LEFT & leaf->token->flags) |
208 | { | 324 | { |
209 | memcpy(&rresult, left, sizeof(LSL_Leaf)); | 325 | rresult = evaluateLeaf(leaf->right, left, right); |
210 | evaluateLeaf(leaf->right, &rresult, right); | ||
211 | if (!(LSL_UNARY & leaf->token->flags)) | 326 | if (!(LSL_UNARY & leaf->token->flags)) |
212 | { | 327 | lresult = evaluateLeaf(leaf->left, left, right); |
213 | evaluateLeaf(leaf->left, &lresult, right); | ||
214 | } | ||
215 | } | 328 | } |
216 | else // Assume left to right. | 329 | else // Assume left to right. |
217 | { | 330 | { |
218 | evaluateLeaf(leaf->left, &lresult, right); | 331 | lresult = evaluateLeaf(leaf->left, left, right); |
219 | if (!(LSL_UNARY & leaf->token->flags)) | 332 | if (!(LSL_UNARY & leaf->token->flags)) |
220 | { | 333 | rresult = evaluateLeaf(leaf->right, left, right); |
221 | memcpy(&rresult, left, sizeof(LSL_Leaf)); | ||
222 | evaluateLeaf(leaf->right, &rresult, right); | ||
223 | } | ||
224 | } | 334 | } |
225 | 335 | ||
226 | if (leaf->token->evaluate) | 336 | if (leaf->token->evaluate) |
227 | { | 337 | result = leaf->token->evaluate(leaf, lresult, rresult); |
228 | leaf->token->evaluate(leaf, &lresult, &rresult); | ||
229 | memcpy(left, &lresult, sizeof(LSL_Leaf)); | ||
230 | } | ||
231 | else | 338 | else |
232 | { | 339 | { |
340 | result = calloc(1, sizeof(LSL_Leaf)); | ||
341 | if (rresult && result) | ||
342 | memcpy(result, rresult, sizeof(LSL_Leaf)); | ||
343 | } | ||
344 | |||
345 | if (lresult) | ||
346 | free(lresult); | ||
347 | if (rresult) | ||
348 | free(rresult); | ||
349 | } | ||
350 | |||
351 | return result; | ||
352 | } | ||
353 | |||
354 | static LSL_Leaf *evaluateFloatToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right) | ||
355 | { | ||
356 | LSL_Leaf *result = malloc(sizeof(LSL_Leaf)); | ||
357 | |||
358 | if (content && result) | ||
359 | { | ||
233 | #ifdef LUASL_DEBUG | 360 | #ifdef LUASL_DEBUG |
234 | printf(" eval <%s %d %d %d %d> ", leaf->token->token, left->value.integerValue, right->value.integerValue, lresult.value.integerValue, rresult.value.integerValue); | 361 | printf(" <%g> ", content->value.floatValue); |
235 | #endif | 362 | #endif |
236 | memcpy(left, &rresult, sizeof(LSL_Leaf)); | 363 | memcpy(result, content, sizeof(LSL_Leaf)); |
237 | } | 364 | result->basicType = OT_float; |
238 | } | 365 | } |
366 | return result; | ||
239 | } | 367 | } |
240 | 368 | ||
241 | static void evaluateIntegerToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right) | 369 | static LSL_Leaf *evaluateIntegerToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right) |
242 | { | 370 | { |
243 | if (content) | 371 | LSL_Leaf *result = malloc(sizeof(LSL_Leaf)); |
372 | |||
373 | if (content && result) | ||
244 | { | 374 | { |
245 | #ifdef LUASL_DEBUG | 375 | #ifdef LUASL_DEBUG |
246 | printf(" <%d> ", content->value.integerValue); | 376 | printf(" <%d> ", content->value.integerValue); |
247 | #endif | 377 | #endif |
248 | left->value.integerValue = content->value.integerValue; | 378 | memcpy(result, content, sizeof(LSL_Leaf)); |
249 | left->token = tokens[LSL_INTEGER - lowestToken]; | 379 | result->basicType = OT_integer; |
250 | } | 380 | } |
381 | return result; | ||
251 | } | 382 | } |
252 | 383 | ||
253 | static void evaluateNoToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right) | 384 | static LSL_Leaf *evaluateNoToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right) |
254 | { | 385 | { |
255 | // Do nothing, that's the point. | 386 | // Do nothing, that's the point. |
387 | |||
388 | return content; | ||
256 | } | 389 | } |
257 | 390 | ||
258 | static void evaluateOperationToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right) | ||
259 | { | ||
260 | /* Typecasting | 391 | /* Typecasting |
261 | 392 | ||
262 | LSL is statically typed, so stored values are not converted, only the values used in expressions are. | 393 | LSL is statically typed, so stored values are not converted, only the values used in expressions are. |
@@ -288,108 +419,192 @@ Any binary operation involving a float and an integer implicitly casts the integ | |||
288 | A boolean operation deals with TRUE (1) and FALSE (0). Any non zero value is a TRUE (generally sigh). | 419 | A boolean operation deals with TRUE (1) and FALSE (0). Any non zero value is a TRUE (generally sigh). |
289 | Bitwise operations only apply to integers. The shifts are arithmatic, not logical. Right shifted bits are dropped, left shifts the sign bit. | 420 | Bitwise operations only apply to integers. The shifts are arithmatic, not logical. Right shifted bits are dropped, left shifts the sign bit. |
290 | 421 | ||
291 | intefer = integer0 % integer1; // Apparently only applies to integers. | 422 | integer = integer0 % integer1; // Apparently only applies to integers. |
292 | string = string0 + string1; // Concatenation. | 423 | string = string0 + string1; // Concatenation. |
293 | list = list0 + list1; // Concatenation. Also works if either is not a list, it's promoted to a list first. | 424 | list = list0 + list1; // Concatenation. Also works if either is not a list, it's promoted to a list first. |
294 | list = (list=[]) + list + ["new_item"]; // Voodoo needed for old LSL, works in Mono but not needed, does not work in OS. Works for strings to. | 425 | list = (list=[]) + list + ["new_item"]; // Voodoo needed for old LSL, works in Mono but not needed, does not work in OS. Works for strings to. |
295 | list == != // Only compares the lengths, probably applies to the other conditionals to. | 426 | bool = list == != int // Only compares the lengths, probably applies to the other conditionals to. |
296 | vector = vector0 + vector1; // Add elements together. | 427 | vector = vector0 + vector1; // Add elements together. |
297 | vector = vector0 - vector1; // Subtract elements of vector1 from elements of vector0. | 428 | vector = vector0 - vector1; // Subtract elements of vector1 from elements of vector0. |
298 | float = vector0 * vector1; // A dot product of the vectors. | 429 | float = vector0 * vector1; // A dot product of the vectors. |
299 | vector = vector0 % vector1; // A cross product of the vectors. | 430 | vector = vector0 % vector1; // A cross product of the vectors. |
300 | vector = vector * float; // Scale the vector, works the other way around I think. | 431 | vector = vector * float; // Scale the vector, works the other way around I think. Works for integer to, but it will end up being cast to float. |
301 | vector = vector * integer; // Scale the vector, works the other way around I think. | 432 | vector = vector / float; // Scale the vector, works the other way around I think. Works for integer to, but it will end up being cast to float. |
302 | vector = vector / float; // Scale the vector, works the other way around I think. | ||
303 | vector = vector / integer; // Scale the vector, works the other way around I think. | ||
304 | vector = vector * rotation; // Rotate the vector by the rotation. Other way around wont compile. | 433 | vector = vector * rotation; // Rotate the vector by the rotation. Other way around wont compile. |
305 | vector = vector / rotation; // Rotate the vector by the rotation, in the opposite direction. Other way around wont compile. | 434 | vector = vector / rotation; // Rotate the vector by the rotation, in the opposite direction. Other way around wont compile. |
306 | rotation = llGetRot() * rotation; // Rotate an object around the global axis. | 435 | rotation = llGetRot() * rotation; // Rotate an object around the global axis. |
307 | rotation = rotation * llGetLocalRot(); // Rotate an object around the local axis. | 436 | rotation = rotation * llGetLocalRot(); // Rotate an object around the local axis. |
308 | rotation = rotation0 * rotation1; // Add two rotations, so the result is as if you applied each rotation one after the other. | 437 | rotation = rotation0 * rotation1; // Add two rotations, so the result is as if you applied each rotation one after the other. |
438 | // Division rotates in the opposite direction. | ||
309 | rotation = rotation0 + rotation1; // Similar to vector, but it's a meaningless thing as far as rotations go. | 439 | rotation = rotation0 + rotation1; // Similar to vector, but it's a meaningless thing as far as rotations go. |
310 | rotation = rotation0 - rotation1; // Similar to vector, but it's a meaningless thing as far as rotations go. | 440 | rotation = rotation0 - rotation1; // Similar to vector, but it's a meaningless thing as far as rotations go. |
311 | // Division rotates in the opposite direction. | 441 | |
442 | A boolean operator results in a boolean value. (any types) | ||
443 | A comparison operator results in a boolean value. (any types) | ||
444 | A bitwise operator results in an integer value. (intInt or int) | ||
445 | A dot product operator results in a float value. (vector * vector) | ||
446 | A vectorFloat results in a vector value. | ||
312 | 447 | ||
313 | */ | 448 | */ |
314 | 449 | ||
450 | static LSL_Leaf *evaluateOperationToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right) | ||
451 | { | ||
452 | LSL_Leaf *result = calloc(1, sizeof(LSL_Leaf)); | ||
315 | 453 | ||
316 | if (content) | 454 | if (content && result) |
317 | { | 455 | { |
318 | #ifdef LUASL_DEBUG | 456 | #ifdef LUASL_DEBUG |
319 | printf(" [%s] ", content->token->token); | 457 | printf(" [%s] ", content->token->token); |
320 | #endif | 458 | #endif |
321 | 459 | ||
322 | switch (content->token->type) | 460 | memcpy(result, content, sizeof(LSL_Leaf)); |
461 | |||
462 | // Figure out the type of the operation. | ||
463 | if (OT_vector < result->basicType) | ||
464 | result->basicType = allowed[result->basicType].result; | ||
465 | |||
466 | switch (result->basicType) | ||
323 | { | 467 | { |
324 | case LSL_COMMA : | 468 | case OT_float : |
325 | case LSL_INCREMENT_PRE : | 469 | { |
326 | // case LSL_INCREMENT_POST : | 470 | float fleft = left->value.floatValue; |
327 | case LSL_DECREMENT_PRE : | 471 | float fright = right->value.floatValue; |
328 | // case LSL_DECREMENT_POST : | 472 | |
329 | case LSL_DOT : | 473 | // Do the casting. |
330 | case LSL_ASSIGNMENT_PLAIN : | 474 | if (OT_floatInt == content->basicType) |
331 | case LSL_ASSIGNMENT_DIVIDE : | 475 | fright = right->value.integerValue; |
332 | case LSL_ASSIGNMENT_MODULO : | 476 | if (OT_intFloat == content->basicType) |
333 | case LSL_ASSIGNMENT_MULTIPLY : | 477 | fleft = left->value.integerValue; |
334 | case LSL_ASSIGNMENT_SUBTRACT : | 478 | switch (result->token->type) |
335 | case LSL_ASSIGNMENT_ADD : | 479 | { |
336 | // case LSL_ASSIGNMENT_CONCATENATE : | 480 | case LSL_COMMA : |
337 | case LSL_PARENTHESIS_OPEN : | 481 | case LSL_INCREMENT_PRE : |
338 | case LSL_PARENTHESIS_CLOSE : | 482 | // case LSL_INCREMENT_POST : |
339 | case LSL_BRACKET_OPEN : | 483 | case LSL_DECREMENT_PRE : |
340 | case LSL_BRACKET_CLOSE : | 484 | // case LSL_DECREMENT_POST : |
341 | case LSL_ANGLE_OPEN : | 485 | case LSL_ASSIGNMENT_PLAIN : |
342 | case LSL_ANGLE_CLOSE : | 486 | case LSL_ASSIGNMENT_DIVIDE : |
343 | // case LSL_TYPECAST_OPEN : | 487 | case LSL_ASSIGNMENT_MULTIPLY : |
344 | // case LSL_TYPECAST_CLOSE : | 488 | case LSL_ASSIGNMENT_SUBTRACT : |
489 | case LSL_ASSIGNMENT_ADD : | ||
490 | case LSL_BRACKET_OPEN : | ||
491 | case LSL_BRACKET_CLOSE : | ||
492 | case LSL_ANGLE_OPEN : | ||
493 | case LSL_ANGLE_CLOSE : | ||
494 | // case LSL_TYPECAST_OPEN : | ||
495 | // case LSL_TYPECAST_CLOSE : | ||
496 | // case LSL_DOT_PRODUCT : | ||
497 | break; | ||
498 | case LSL_NEGATION : result->value.floatValue = 0 - fright; break; | ||
499 | case LSL_DIVIDE : result->value.floatValue = fleft / fright; break; | ||
500 | case LSL_MULTIPLY : result->value.floatValue = fleft * fright; break; | ||
501 | case LSL_SUBTRACT : result->value.floatValue = fleft - fright; break; | ||
502 | case LSL_ADD : result->value.floatValue = fleft + fright; break; | ||
503 | case LSL_LESS_THAN : result->value.floatValue = fleft < fright; break; | ||
504 | case LSL_GREATER_THAN : result->value.floatValue = fleft > fright; break; | ||
505 | case LSL_LESS_EQUAL : result->value.floatValue = fleft <= fright; break; | ||
506 | case LSL_GREATER_EQUAL : result->value.floatValue = fleft >= fright; break; | ||
507 | case LSL_EQUAL : result->value.floatValue = fleft == fright; break; | ||
508 | case LSL_NOT_EQUAL : result->value.floatValue = fleft != fright; break; | ||
509 | } | ||
510 | #ifdef LUASL_DEBUG | ||
511 | printf(" (=%g) ", result->value.floatValue); | ||
512 | #endif | ||
345 | break; | 513 | break; |
346 | case LSL_BIT_NOT : left->value.integerValue = ~ right->value.integerValue; break; | 514 | } |
347 | case LSL_BOOL_NOT : left->value.integerValue = ! right->value.integerValue; break; | 515 | |
348 | case LSL_NEGATION : left->value.integerValue = 0 - right->value.integerValue; break; | 516 | case OT_integer : |
349 | case LSL_DIVIDE : left->value.integerValue = left->value.integerValue / right->value.integerValue; break; | 517 | { |
350 | case LSL_MODULO : left->value.integerValue = left->value.integerValue % right->value.integerValue; break; | 518 | switch (result->token->type) |
351 | case LSL_MULTIPLY : left->value.integerValue = left->value.integerValue * right->value.integerValue; break; | 519 | { |
352 | // case LSL_DOT_PRODUCT : break; | 520 | case LSL_COMMA : |
353 | // case LSL_CROSS_PRODUCT : break; | 521 | case LSL_INCREMENT_PRE : |
354 | case LSL_SUBTRACT : left->value.integerValue = left->value.integerValue - right->value.integerValue; break; | 522 | // case LSL_INCREMENT_POST : |
355 | case LSL_ADD : left->value.integerValue = left->value.integerValue + right->value.integerValue; break; | 523 | case LSL_DECREMENT_PRE : |
356 | // case LSL_CONCATENATE : break; | 524 | // case LSL_DECREMENT_POST : |
357 | case LSL_LEFT_SHIFT : left->value.integerValue = left->value.integerValue << right->value.integerValue; break; | 525 | case LSL_DOT : |
358 | case LSL_RIGHT_SHIFT : left->value.integerValue = left->value.integerValue >> right->value.integerValue; break; | 526 | case LSL_ASSIGNMENT_PLAIN : |
359 | case LSL_LESS_THAN : left->value.integerValue = left->value.integerValue < right->value.integerValue; break; | 527 | case LSL_ASSIGNMENT_DIVIDE : |
360 | case LSL_GREATER_THAN : left->value.integerValue = left->value.integerValue > right->value.integerValue; break; | 528 | case LSL_ASSIGNMENT_MODULO : |
361 | case LSL_LESS_EQUAL : left->value.integerValue = left->value.integerValue <= right->value.integerValue; break; | 529 | case LSL_ASSIGNMENT_MULTIPLY : |
362 | case LSL_GREATER_EQUAL : left->value.integerValue = left->value.integerValue >= right->value.integerValue; break; | 530 | case LSL_ASSIGNMENT_SUBTRACT : |
363 | case LSL_EQUAL : left->value.integerValue = left->value.integerValue == right->value.integerValue; break; | 531 | case LSL_ASSIGNMENT_ADD : |
364 | case LSL_NOT_EQUAL : left->value.integerValue = left->value.integerValue != right->value.integerValue; break; | 532 | case LSL_BRACKET_OPEN : |
365 | case LSL_BIT_AND : left->value.integerValue = left->value.integerValue & right->value.integerValue; break; | 533 | case LSL_BRACKET_CLOSE : |
366 | case LSL_BIT_XOR : left->value.integerValue = left->value.integerValue ^ right->value.integerValue; break; | 534 | case LSL_ANGLE_OPEN : |
367 | case LSL_BIT_OR : left->value.integerValue = left->value.integerValue | right->value.integerValue; break; | 535 | case LSL_ANGLE_CLOSE : |
368 | case LSL_BOOL_OR : left->value.integerValue = left->value.integerValue || right->value.integerValue; break; | 536 | // case LSL_TYPECAST_OPEN : |
369 | case LSL_BOOL_AND : left->value.integerValue = left->value.integerValue && right->value.integerValue; break; | 537 | // case LSL_TYPECAST_CLOSE : |
370 | } | 538 | break; |
539 | case LSL_BIT_NOT : result->value.integerValue = ~ right->value.integerValue; break; | ||
540 | case LSL_BOOL_NOT : result->value.integerValue = ! right->value.integerValue; break; | ||
541 | case LSL_NEGATION : result->value.integerValue = 0 - right->value.integerValue; break; | ||
542 | case LSL_DIVIDE : result->value.integerValue = left->value.integerValue / right->value.integerValue; break; | ||
543 | case LSL_MODULO : result->value.integerValue = left->value.integerValue % right->value.integerValue; break; | ||
544 | case LSL_MULTIPLY : result->value.integerValue = left->value.integerValue * right->value.integerValue; break; | ||
545 | case LSL_SUBTRACT : result->value.integerValue = left->value.integerValue - right->value.integerValue; break; | ||
546 | case LSL_ADD : result->value.integerValue = left->value.integerValue + right->value.integerValue; break; | ||
547 | case LSL_LEFT_SHIFT : result->value.integerValue = left->value.integerValue << right->value.integerValue; break; | ||
548 | case LSL_RIGHT_SHIFT : result->value.integerValue = left->value.integerValue >> right->value.integerValue; break; | ||
549 | case LSL_LESS_THAN : result->value.integerValue = left->value.integerValue < right->value.integerValue; break; | ||
550 | case LSL_GREATER_THAN : result->value.integerValue = left->value.integerValue > right->value.integerValue; break; | ||
551 | case LSL_LESS_EQUAL : result->value.integerValue = left->value.integerValue <= right->value.integerValue; break; | ||
552 | case LSL_GREATER_EQUAL : result->value.integerValue = left->value.integerValue >= right->value.integerValue; break; | ||
553 | case LSL_EQUAL : result->value.integerValue = left->value.integerValue == right->value.integerValue; break; | ||
554 | case LSL_NOT_EQUAL : result->value.integerValue = left->value.integerValue != right->value.integerValue; break; | ||
555 | case LSL_BIT_AND : result->value.integerValue = left->value.integerValue & right->value.integerValue; break; | ||
556 | case LSL_BIT_XOR : result->value.integerValue = left->value.integerValue ^ right->value.integerValue; break; | ||
557 | case LSL_BIT_OR : result->value.integerValue = left->value.integerValue | right->value.integerValue; break; | ||
558 | case LSL_BOOL_OR : result->value.integerValue = left->value.integerValue || right->value.integerValue; break; | ||
559 | case LSL_BOOL_AND : result->value.integerValue = left->value.integerValue && right->value.integerValue; break; | ||
560 | } | ||
371 | #ifdef LUASL_DEBUG | 561 | #ifdef LUASL_DEBUG |
372 | printf(" (=%d) ", left->value.integerValue); | 562 | printf(" (=%d) ", result->value.integerValue); |
373 | #endif | 563 | #endif |
564 | break; | ||
565 | } | ||
566 | |||
567 | default : | ||
568 | break; | ||
569 | } | ||
374 | } | 570 | } |
571 | return result; | ||
375 | } | 572 | } |
376 | 573 | ||
377 | static void eveluateParenthesisToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right) | 574 | static LSL_Leaf *eveluateParenthesisToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right) |
378 | { | 575 | { |
576 | LSL_Leaf *result = NULL; | ||
577 | |||
379 | if (content) | 578 | if (content) |
380 | evaluateLeaf(content->value.parenthesis->expression, left, right); | 579 | result = evaluateLeaf(content->value.parenthesis->expression, left, right); |
580 | return result; | ||
381 | } | 581 | } |
382 | 582 | ||
383 | 583 | ||
384 | static void evaluateStatementToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right) | 584 | static LSL_Leaf *evaluateStatementToken(LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right) |
385 | { | 585 | { |
586 | LSL_Leaf *result = NULL; | ||
587 | |||
386 | if (content) | 588 | if (content) |
387 | { | 589 | { |
388 | evaluateLeaf(content->value.statementValue->expressions, left, right); | 590 | result = evaluateLeaf(content->value.statementValue->expressions, left, right); |
389 | printf("\nResult is %d.\n", left->value.integerValue); | 591 | if (result) |
390 | left->value.integerValue = 0; | 592 | { |
391 | right->value.integerValue = 0; | 593 | switch (result->basicType) |
594 | { | ||
595 | case OT_float : printf("\nResult is the float %g.\n", result->value.floatValue); break; | ||
596 | case OT_integer : printf("\nResult is the integer %d.\n", result->value.integerValue); break; | ||
597 | default : printf("\nResult of an unknown type [%d] %d!\n", result->basicType, result->value.integerValue); break; | ||
598 | } | ||
599 | free(result); | ||
600 | result = NULL; | ||
601 | } | ||
602 | if (left) | ||
603 | left->value.integerValue = 0; | ||
604 | if (right) | ||
605 | right->value.integerValue = 0; | ||
392 | } | 606 | } |
607 | return result; | ||
393 | } | 608 | } |
394 | 609 | ||
395 | static void outputLeaf(FILE *file, LSL_Leaf *leaf) | 610 | static void outputLeaf(FILE *file, LSL_Leaf *leaf) |
@@ -407,6 +622,12 @@ static void outputLeaf(FILE *file, LSL_Leaf *leaf) | |||
407 | } | 622 | } |
408 | } | 623 | } |
409 | 624 | ||
625 | static void outputFloatToken(FILE *file, LSL_Leaf *content) | ||
626 | { | ||
627 | if (content) | ||
628 | fprintf(file, "%g", content->value.floatValue); | ||
629 | } | ||
630 | |||
410 | static void outputIntegerToken(FILE *file, LSL_Leaf *content) | 631 | static void outputIntegerToken(FILE *file, LSL_Leaf *content) |
411 | { | 632 | { |
412 | if (content) | 633 | if (content) |
@@ -585,16 +806,9 @@ int main(int argc, char **argv) | |||
585 | char outName[PATH_MAX]; | 806 | char outName[PATH_MAX]; |
586 | char luaName[PATH_MAX]; | 807 | char luaName[PATH_MAX]; |
587 | 808 | ||
588 | LSL_Leaf left, right; | ||
589 | |||
590 | left.value.integerValue = 0; | ||
591 | left.token = tokens[LSL_INTEGER - lowestToken]; | ||
592 | right.value.integerValue = 0; | ||
593 | right.token = tokens[LSL_INTEGER - lowestToken]; | ||
594 | |||
595 | outputLeaf(stdout, param.ast); | 809 | outputLeaf(stdout, param.ast); |
596 | printf("\n"); | 810 | printf("\n"); |
597 | evaluateLeaf(param.ast, &left, &right); | 811 | evaluateLeaf(param.ast, NULL, NULL); |
598 | printf("\n"); | 812 | printf("\n"); |
599 | 813 | ||
600 | strcpy(outName, fileName); | 814 | strcpy(outName, fileName); |
@@ -611,7 +825,6 @@ int main(int argc, char **argv) | |||
611 | printf("Return value of %s is %d\n", buffer, count); | 825 | printf("Return value of %s is %d\n", buffer, count); |
612 | if (0 != count) | 826 | if (0 != count) |
613 | fprintf(stderr, "%s says they are different!\n", buffer); | 827 | fprintf(stderr, "%s says they are different!\n", buffer); |
614 | |||
615 | } | 828 | } |
616 | else | 829 | else |
617 | fprintf(stderr, "Unable to open file %s for writing!\n", outName); | 830 | fprintf(stderr, "Unable to open file %s for writing!\n", outName); |
@@ -625,9 +838,7 @@ int main(int argc, char **argv) | |||
625 | fprintf(stderr, "Unable to open file %s for writing!\n", luaName); | 838 | fprintf(stderr, "Unable to open file %s for writing!\n", luaName); |
626 | burnLeaf(param.ast); | 839 | burnLeaf(param.ast); |
627 | } | 840 | } |
628 | |||
629 | } | 841 | } |
630 | |||
631 | } | 842 | } |
632 | else | 843 | else |
633 | { | 844 | { |
diff --git a/LuaSL/src/LuaSL_LSL_tree.h b/LuaSL/src/LuaSL_LSL_tree.h index 558dc8d..d2d767c 100644 --- a/LuaSL/src/LuaSL_LSL_tree.h +++ b/LuaSL/src/LuaSL_LSL_tree.h | |||
@@ -30,6 +30,7 @@ extern int yydebug; | |||
30 | // http://w-hat.com/stackdepth is a useful discussion about some aspects of the LL parser. | 30 | // http://w-hat.com/stackdepth is a useful discussion about some aspects of the LL parser. |
31 | 31 | ||
32 | 32 | ||
33 | typedef struct _allowedTypes allowedTypes; | ||
33 | typedef struct _LSL_Token LSL_Token; | 34 | typedef struct _LSL_Token LSL_Token; |
34 | typedef struct _LSL_Leaf LSL_Leaf; | 35 | typedef struct _LSL_Leaf LSL_Leaf; |
35 | typedef struct _LSL_Parenthesis LSL_Parenthesis; | 36 | typedef struct _LSL_Parenthesis LSL_Parenthesis; |
@@ -47,7 +48,7 @@ typedef int LSL_Type; | |||
47 | 48 | ||
48 | typedef void (*convertToken2Lua) (FILE *file, LSL_Leaf *content); | 49 | typedef void (*convertToken2Lua) (FILE *file, LSL_Leaf *content); |
49 | typedef void (*outputToken) (FILE *file, LSL_Leaf *content); | 50 | typedef void (*outputToken) (FILE *file, LSL_Leaf *content); |
50 | typedef void (*evaluateToken) (LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right); | 51 | typedef LSL_Leaf * (*evaluateToken) (LSL_Leaf *content, LSL_Leaf *left, LSL_Leaf *right); |
51 | 52 | ||
52 | #ifndef FALSE | 53 | #ifndef FALSE |
53 | typedef enum | 54 | typedef enum |
@@ -69,9 +70,99 @@ typedef enum | |||
69 | LSL_NOIGNORE = 64 | 70 | LSL_NOIGNORE = 64 |
70 | } LSL_Flags; | 71 | } LSL_Flags; |
71 | 72 | ||
73 | typedef enum | ||
74 | { | ||
75 | OT_nothing, | ||
76 | |||
77 | OT_bool, | ||
78 | OT_integer, | ||
79 | OT_float, | ||
80 | OT_key, | ||
81 | OT_list, | ||
82 | OT_rotation, | ||
83 | OT_string, | ||
84 | OT_vector, | ||
85 | OT_other, | ||
86 | |||
87 | OT_boolBool, | ||
88 | OT_intInt, | ||
89 | OT_intFloat, | ||
90 | OT_floatInt, | ||
91 | OT_floatFloat, | ||
92 | OT_keyString, | ||
93 | OT_stringKey, | ||
94 | OT_stringString, | ||
95 | OT_listList, | ||
96 | OT_listInt, | ||
97 | OT_listFloat, | ||
98 | OT_intList, | ||
99 | OT_floatList, | ||
100 | OT_listOther, | ||
101 | OT_vectorVector, | ||
102 | OT_vectorFloat, | ||
103 | OT_vectorRotation, | ||
104 | OT_rotationRotation, | ||
105 | OT_otherOther, | ||
106 | OT_invalid | ||
107 | } opType; | ||
108 | |||
109 | /* | ||
110 | Each op is of a specific type - | ||
111 | |||
112 | bool ! | ||
113 | int - ~ | ||
114 | float - | ||
115 | |||
116 | bool bool && || == != = | ||
117 | int int * / + - % == != < > <= >= = += -= *= /= %= & | ^ << >> | ||
118 | int float cast to float float | ||
119 | float int cast to float float | ||
120 | float float * / + - == != < > <= >= = += -= *= /= | ||
121 | |||
122 | key string cast to string string | ||
123 | string key cast to string string | ||
124 | string string + == != = += | ||
125 | |||
126 | list list + == != = += | ||
127 | list integer/float + < > <= >= = += | ||
128 | integer/float list + < > <= >= | ||
129 | list other + = += | ||
130 | |||
131 | vector vector * / + - % == != = += -= *= /= %= | ||
132 | vector float * / | ||
133 | vector rotation * / | ||
134 | |||
135 | rotation rotation * / + - == != = += -= *= /= | ||
136 | */ | ||
137 | |||
138 | typedef enum | ||
139 | { | ||
140 | ST_NONE = 0, | ||
141 | ST_ASSIGNMENT = 1, // -= *= /= | ||
142 | ST_BIT_NOT = 2, // ~ | ||
143 | ST_BOOL_NOT = 4, // ! | ||
144 | ST_BITWISE = 8, // & | ^ << >> | ||
145 | ST_BOOLEAN = 16, // && !! | ||
146 | ST_COMPARISON = 32, // < > <= >= | ||
147 | ST_CONCATENATION = 64, // = += | ||
148 | ST_EQUALITY = 128, // == != | ||
149 | ST_ADD = 512, // + | ||
150 | ST_SUBTRACT = 1024, // - | ||
151 | ST_NEGATE = 2048, // - | ||
152 | ST_MULTIPLY = 4096, // * / | ||
153 | ST_MODULO = 8192 // % %= | ||
154 | } opSubType; | ||
155 | |||
156 | struct _allowedTypes | ||
157 | { | ||
158 | opType result; | ||
159 | int subTypes; | ||
160 | }; | ||
161 | |||
72 | struct _LSL_Token | 162 | struct _LSL_Token |
73 | { | 163 | { |
74 | LSL_Type type; | 164 | LSL_Type type; |
165 | opSubType subType; | ||
75 | char *token; | 166 | char *token; |
76 | LSL_Flags flags; | 167 | LSL_Flags flags; |
77 | outputToken output; | 168 | outputToken output; |
@@ -86,8 +177,10 @@ struct _LSL_Leaf | |||
86 | LSL_Token *token; | 177 | LSL_Token *token; |
87 | char *ignorableText; | 178 | char *ignorableText; |
88 | int line, column; | 179 | int line, column; |
180 | opType basicType; | ||
89 | union | 181 | union |
90 | { | 182 | { |
183 | opType operationValue; | ||
91 | LSL_Parenthesis *parenthesis; | 184 | LSL_Parenthesis *parenthesis; |
92 | 185 | ||
93 | float floatValue; | 186 | float floatValue; |
diff --git a/LuaSL/src/LuaSL_lemon_yaccer.y b/LuaSL/src/LuaSL_lemon_yaccer.y index bd0aa52..045c997 100644 --- a/LuaSL/src/LuaSL_lemon_yaccer.y +++ b/LuaSL/src/LuaSL_lemon_yaccer.y | |||
@@ -60,8 +60,9 @@ expr(A) ::= LSL_PARENTHESIS_OPEN(B) expr(C) LSL_PARENTHESIS_CLOSE(D). { A = addP | |||
60 | %nonassoc LSL_COMMA. | 60 | %nonassoc LSL_COMMA. |
61 | 61 | ||
62 | %nonassoc LSL_FLOAT. | 62 | %nonassoc LSL_FLOAT. |
63 | expr(A) ::= LSL_FLOAT(B). { B->basicType = OT_float; A = B; } | ||
63 | %nonassoc LSL_INTEGER. | 64 | %nonassoc LSL_INTEGER. |
64 | expr(A) ::= LSL_INTEGER(B). { A = B; } | 65 | expr(A) ::= LSL_INTEGER(B). { B->basicType = OT_integer; A = B; } |
65 | 66 | ||
66 | %nonassoc LSL_TYPE_FLOAT LSL_TYPE_INTEGER LSL_TYPE_KEY LSL_TYPE_LIST LSL_TYPE_ROTATION LSL_TYPE_STRING LSL_TYPE_VECTOR. | 67 | %nonassoc LSL_TYPE_FLOAT LSL_TYPE_INTEGER LSL_TYPE_KEY LSL_TYPE_LIST LSL_TYPE_ROTATION LSL_TYPE_STRING LSL_TYPE_VECTOR. |
67 | 68 | ||
diff --git a/LuaSL/src/LuaSL_lexer.l b/LuaSL/src/LuaSL_lexer.l index 2b60634..2b57f68 100644 --- a/LuaSL/src/LuaSL_lexer.l +++ b/LuaSL/src/LuaSL_lexer.l | |||
@@ -19,9 +19,9 @@ HEX [[:xdigit:]] | |||
19 | DECIMAL [[:digit:]] | 19 | DECIMAL [[:digit:]] |
20 | /* LSL has no octal integer type. */ | 20 | /* LSL has no octal integer type. */ |
21 | INTEGER ({DECIMAL}+)|(0[xX]{HEX}+) | 21 | INTEGER ({DECIMAL}+)|(0[xX]{HEX}+) |
22 | EXPONANT [eE][+-]?{DECIMAL} | 22 | EXPONANT [eE][+-]?{DECIMAL}+ |
23 | /* Floats can be "0." but I don't think ".0" is valid. */ | 23 | /* Floats can be "0." but I don't think ".0" is valid. It might be though, need to double check that. */ |
24 | FLOAT {DECIMAL}("."{DECIMAL})?{EXPONANT}?[fF]? | 24 | FLOAT {DECIMAL}+"."{DECIMAL}*{EXPONANT}?[fF]? |
25 | CHAR '(\\.|[^\\'\n])+' | 25 | CHAR '(\\.|[^\\'\n])+' |
26 | STRING \"(\\.|[^\\"\n])*\" | 26 | STRING \"(\\.|[^\\"\n])*\" |
27 | IDENTIFIER [[:alpha:]](_|[[:alpha:]]|[[:digit:]])* | 27 | IDENTIFIER [[:alpha:]](_|[[:alpha:]]|[[:digit:]])* |
diff --git a/LuaSL/test.lsl b/LuaSL/test.lsl index 022163a..56864d3 100644 --- a/LuaSL/test.lsl +++ b/LuaSL/test.lsl | |||
@@ -2,5 +2,5 @@ | |||
2 | 3 /* c5 */ * /* c6 */ ( /* c7 */ 5 /* c8 */ + /* c9 */ 1 /* cA */ ) /* cB */ ; /* cE */ | 2 | 3 /* c5 */ * /* c6 */ ( /* c7 */ 5 /* c8 */ + /* c9 */ 1 /* cA */ ) /* cB */ ; /* cE */ |
3 | // Some more arithmetic - | 3 | // Some more arithmetic - |
4 | 1+1; | 4 | 1+1; |
5 | 5 | 20.5 + 20 + 1.5; | |
6 | // This is the end my friend. \ No newline at end of file | 6 | // This is the end my friend. \ No newline at end of file |