public Token NextToken(bool skipEol = false) { // игнорируемые разделители while (Ch == ' ' || Ch == '\t' || (skipEol && Ch == '\n')) NextCh(); if (Ch == '/' && Commnet0() || Ch == '/' && Commnet1() || Ch == ';' && Commnet2()) return NextToken(skipEol); if (Eof) return new Token { Position = Pos, Type = TokenType.EndFile }; if (Ch == '\n') { NextCh(); return new Token {Position = Pos, Type = TokenType.EndLine}; } _tokVal.Length = 0; if (Col == 1) return GetLabel(); if (Ch == '"') return GetString(true); if (Ch == '\'') return GetString(false); //if (char.IsDigit(Ch) || Ch == '#' || Ch == '$' || Ch == '%') return GetNumber(); if (char.IsDigit(Ch) || Ch == '#' || Ch == '%') return GetNumber(); if (Ch == '.') { NextCh(); if (char.IsLetter(Ch)) return GetIdentifier(); return new Token {Position = Pos, Type = TokenType.Repeat}; } if (char.IsLetter(Ch) || Ch == '_') return GetIdentifier(); var res = new Token {Position = Pos}; switch (Ch) { case '!': NextCh(); if (Ch == '=') { NextCh(); res.Type = TokenType.NotEqual; break; } res.Type = TokenType.LogicalNot; break; case '~': NextCh(); res.Type = TokenType.Complement; break; case '+': NextCh(); res.Type = TokenType.Plus; break; case '-': NextCh(); res.Type = TokenType.Minus; break; case '*': NextCh(); res.Type = TokenType.Mul; break; case '/': NextCh(); res.Type = TokenType.Div; break; case '%': NextCh(); res.Type = TokenType.Mod; break; case '<': NextCh(); switch (Ch) { case '<': // << NextCh(); res.Type = TokenType.ShiftLeft; break; case '=': // <= NextCh(); res.Type = TokenType.LessOrEqual; break; case '?': // <? NextCh(); res.Type = TokenType.Minimum; break; default: // < res.Type = TokenType.Less; break; } break; case '>': NextCh(); switch (Ch) { case '>': NextCh(); if (Ch == '>') // >>> { NextCh(); res.Type = TokenType.UnsignedShiftRight; break; } res.Type = TokenType.ShiftRight; // >> break; case '?': // >? NextCh(); res.Type = TokenType.Maximum; break; case '=': // >= NextCh(); res.Type = TokenType.GreaterOrEqual; break; default: // > res.Type = TokenType.Greater; break; } break; case '=': NextCh(); // = if (Ch == '=') NextCh(); // == res.Type = TokenType.Equal; break; case '&': NextCh(); if (Ch == '&') // && { NextCh(); res.Type = TokenType.LogicalAnd; break; } res.Type = TokenType.BitAnd; // & break; case '|': NextCh(); if (Ch == '|') // || { NextCh(); res.Type = TokenType.LogicalOr; break; } res.Type = TokenType.BitOr; // | break; case '^': NextCh(); res.Type = TokenType.BitXor; break; case '(': NextCh(); res.Type = TokenType.LParam; break; case ')': NextCh(); res.Type = TokenType.RParam; break; case '[': NextCh(); res.Type = TokenType.LIndex; break; case ']': NextCh(); res.Type = TokenType.RIndex; break; case '$': NextCh(); if (Ch == '$') // $$ { NextCh(); res.Type = TokenType.CurrentPage; break; } if (char.IsDigit(Ch) || IsHexLetter(Ch)) return GetHexNumber(res.Position); // hex Число res.Type = TokenType.CurrentPc; // $ break; case '#': NextCh(); if (Ch == '#') // ## { NextCh(); res.Type = TokenType.DefaultAlign; break; } res.Type = TokenType.NextAlign; // # break; case ':': NextCh(); res.Type = TokenType.Colon; break; case ',': NextCh(); res.Type = TokenType.Comma; break; default: throw new ApplicationException("неожиданый символ"); } return res; }
private Token GetNumber() { var startpos = Pos; var firstCh = Ch; var binOnly = true; var octOnly = true; if (Ch == '$' || Ch == '#') { NextCh(); return GetHexNumber(startpos); } if (Ch == '%') { NextCh(); return GetBinNumber(startpos); } if (Ch == '0' && IsChar('x')) { NextCh(); NextCh(); return GetHexNumber(startpos); } var c = GetCh() ?? (char)0; if ( Ch == '0' && IsHexLetter(c)) { NextCh(); return GetHexNumber(startpos); } var res = new Token {Position = startpos, Type = TokenType.Number}; while (!Eof) { var tmp = GetCh() ?? (char)0; var last = ((!char.IsLetter(tmp) && !char.IsDigit(tmp)) || IsWs(tmp)); if (IsHexLetter(Ch)) { if (firstCh == '0') return GetHexNumber(startpos); if (!last) return GetHexNumber(startpos); } if (char.IsDigit(Ch)) { if (Ch > '1') binOnly = false; if (Ch > '7') octOnly = false; AddChar(); continue; } var t = char.ToLower(Ch); if (t == 'b' && binOnly && firstCh == '1') { NextCh(); res.Modifer = "bin"; res.Value = _tokVal.ToString(); //NextCh(); if (!char.IsLetter(Ch) || IsWs()) return res; } if (t == 'h') { NextCh(); res.Modifer = "hex"; res.Value = _tokVal.ToString(); //NextCh(); if (!char.IsLetter(Ch) || IsWs()) return res; } if ((t=='o' || t=='q') && octOnly) { NextCh(); res.Modifer = "oct"; res.Value = _tokVal.ToString(); //NextCh(); if (!char.IsLetter(Ch) || IsWs()) return res; } if (t == 'd'|| IsWs() || !char.IsLetter(Ch)) // если d в конце либо пробел было символ то число ок { res.Modifer = "dec"; res.Value = _tokVal.ToString(); if (t == 'd') // проверим что после d все ок { NextCh(); if (!char.IsLetter(Ch) || IsWs()) return res; } else return res; } AddChar(); throw new ApplicationException($"Неверный символ в числе \"{_tokVal}\", в позиции {Pos}"); } throw new ApplicationException("Неожиданный конец файла"); }
private Token GetBinNumber(Position startPos) { var res = new Token {Position = startPos, Type = TokenType.Number, Modifer = "bin"}; AddChar(); while (!Eof) { if (Ch == '0' || Ch == '1') { AddChar(); continue; } if (Ch == 'b' || Ch == 'B') { NextCh(); break; } // если следом за числом идет пробел или не буква то ок if (!char.IsLetter(Ch) || IsWs()) break; throw new ApplicationException($"Неверный символ в Bin числе, в позиции {Pos}"); } res.Value = _tokVal.ToString(); return res; }
private Token GetHexNumber(Position startPos) { var res = new Token {Position = startPos, Type = TokenType.Number, Modifer = "hex"}; AddChar(); while (!Eof) { if (char.IsDigit(Ch) || IsHexLetter(Ch)) { AddChar(); continue; } if (Ch == 'h' || Ch == 'H') { NextCh(); res.Value = _tokVal.ToString(); break; } // если следом за числом идет пробел или не буква то ок if (!char.IsLetter(Ch) || IsWs()) break; AddChar(); throw new ApplicationException($"Неверный символ в Hex числе \"{_tokVal}\" в позиции {Pos.Line}:{Pos.Col}"); } res.Value = _tokVal.ToString(); return res; }
protected void NextToken() { Token = _scanner.NextToken(); }