Пример #1
0
        /// <summary>
        /// ソース名とソースを指定して解析します。
        /// </summary>
        /// <param name="name">ソース名</param>
        /// <param name="source">解析対象のソースコード</param>
        /// <returns></returns>
        private KecaknoahLexResult AnalyzeFromText(string name, string source)
        {
            var result = new KecaknoahLexResult(name);
            var line = 0;
            var col = 0;
            var cq = "";
            Tuple<string, KecaknoahTokenType> kw;
            Match lm;
            KecaknoahError ei;
            while (source != "")
            {
                //空白論理行

                if (source.StartsWith(Environment.NewLine))
                {
                    source = source.Substring(Environment.NewLine.Length);
                    result.AddToken(new KecaknoahToken { Position = new Tuple<int, int>(line, col), TokenString = "<NewLine>", Type = KecaknoahTokenType.NewLine });
                    line++;
                    col = 0;
                    continue;
                }
                /*
                if (source.StartsWith(";"))
                {
                    source = source.Substring(1);
                    result.AddToken(new KecaknoahToken { Position = new Tuple<int, int>(line, col), TokenString = ";", Type = KecaknoahTokenType.Semicolon });
                    col++;
                    continue;
                }
                */
                Tuple<string, string> mcq = null;
                if ((mcq = MultilineCommentQuotations.FirstOrDefault(p => source.StartsWith(p.Item1))) != null)
                {
                    source = source.Substring(mcq.Item1.Length);
                    col += mcq.Item1.Length;
                    var ce = source.IndexOf(mcq.Item2);
                    var ecs = source.IndexOf(mcq.Item1);
                    //不正な複数行コメント
                    if ((ecs >= 0 && ecs < ce) || ce < 0)
                    {
                        ei = new KecaknoahError
                        {
                            Column = col,
                            Line = line,
                            Message = "不正な複数行コメントです。コメントが終了していないか、入れ子になっています。"
                        };
                        result.Error = ei;
                        result.Success = false;
                        return result;
                    }
                    while (true)
                    {
                        ce = source.IndexOf(mcq.Item2);
                        var cl = source.IndexOf(Environment.NewLine);
                        if ((cl > 0 && ce < cl) || cl < 0)
                        {
                            source = source.Substring(ce + mcq.Item2.Length);
                            col += ce + mcq.Item2.Length;
                            break;
                        }
                        else
                        {
                            source = source.Substring(cl + Environment.NewLine.Length);
                            line++;
                            col = 0;
                        }
                    }
                    continue;
                }
                //コメント
                if ((cq = LineCommentStart.FirstOrDefault(p => source.StartsWith(p))) != null)
                {
                    source = source.Substring(cq.Length);
                    col += cq.Length;
                    var cl = source.IndexOf(Environment.NewLine);
                    if (cl >= 0)
                    {
                        source = source.Substring(cl + Environment.NewLine.Length);
                        line++;
                        col = 0;
                    }
                    else
                    {
                        //ラストコメント
                        source = "";
                    }
                    continue;
                }
                //空白
                if ((lm = WhitespacePattern.Match(source)).Success && lm.Index == 0)
                {
                    source = source.Substring(lm.Length);
                    col += lm.Length;
                    continue;
                }
                //演算子
                if ((kw = Operators.FirstOrDefault(p => source.StartsWith(p.Item1))) != null)
                {
                    source = source.Substring(kw.Item1.Length);
                    col += kw.Item1.Length;
                    result.AddToken(kw.CreateToken(col, line));
                    continue;
                }
                //識別子・キーワード
                if ((lm = IdentiferPattern.Match(source)).Success && lm.Index == 0)
                {
                    if ((kw = Keywords.FirstOrDefault(p => lm.Value == p.Item1)) != null)
                    {
                        source = source.Substring(kw.Item1.Length);
                        col += kw.Item1.Length;
                        result.AddToken(kw.CreateToken(col, line));
                    }
                    else
                    {
                        source = source.Substring(lm.Length);
                        col += lm.Length;
                        result.AddToken(lm.Value.CreateTokenAsIdentifer(col, line));
                    }
                    continue;
                }
                //リテラル
                if ((lm = BinaryNumberPattern.Match(source)).Success && lm.Index == 0)
                {
                    source = source.Substring(lm.Length);
                    col += lm.Length;
                    result.AddToken(lm.Value.CreateTokenAsBinaryNumber(col, line));
                    if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) continue;
                }
                if ((lm = OctadecimalNumberPattern.Match(source)).Success && lm.Index == 0)
                {
                    source = source.Substring(lm.Length);
                    col += lm.Length;
                    result.AddToken(lm.Value.CreateTokenAsOctadecimalNumber(col, line));
                    if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) continue;
                }
                if ((lm = HexadecimalNumberPattern.Match(source)).Success && lm.Index == 0)
                {
                    source = source.Substring(lm.Length);
                    col += lm.Length;
                    result.AddToken(lm.Value.CreateTokenAsHexadecimalNumber(col, line));
                    if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) continue;
                }
                if ((lm = HexatridecimalNumberPattern.Match(source)).Success && lm.Index == 0)
                {
                    source = source.Substring(lm.Length);
                    col += lm.Length;
                    result.AddToken(lm.Value.CreateTokenAsHexatridecimalNumber(col, line));
                    if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) continue;
                }
                if ((lm = DecimalNumberPattern.Match(source)).Success && lm.Index == 0)
                {
                    source = source.Substring(lm.Length);
                    col += lm.Length;
                    result.AddToken(lm.Value.CreateTokenAsDecimalNumber(col, line));
                    if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) continue;
                }
                if ((cq = StringQuotation.FirstOrDefault(p => source.StartsWith(p))) != null)
                {
                    source = source.Substring(cq.Length);
                    col += cq.Length;
                    int qp = 0, eqp = 0, inp = 0;
                    var ls = "";
                    do
                    {
                        eqp = source.IndexOf("\\" + cq);
                        qp = source.IndexOf(cq);
                        inp = source.IndexOf(Environment.NewLine);
                        if (inp >= 0 && inp < qp)
                        {
                            ei = new KecaknoahError
                            {
                                Column = col,
                                Line = line,
                                Message = "文字列リテラル中に直接改行が含まれています。改行を表現したい場合、\\nを利用してください。"
                            };
                            result.Error = ei;
                            result.Success = false;
                            return result;
                        }
                        if (qp < 0)
                        {
                            ei = new KecaknoahError
                            {
                                Column = col,
                                Line = line,
                                Message = "文字列リテラルが閉じていません。"
                            };
                            result.Error = ei;
                            result.Success = false;
                            return result;
                        }
                        if (eqp >= 0 && qp - eqp == 1)
                        {
                            ls += source.Substring(0, qp + cq.Length);
                            source = source.Substring(qp + cq.Length);
                            col += qp + cq.Length - 1;
                            continue;
                        }
                        else
                        {
                            ls += source.Substring(0, qp);
                            source = source.Substring(qp + cq.Length);
                            foreach (var i in StringLiteralEscapes) ls = ls.Replace(i.Item1, i.Item2);
                            result.AddToken(new KecaknoahToken { Position = new Tuple<int, int>(col, line), TokenString = ls, Type = KecaknoahTokenType.StringLiteral });
                            col += qp + cq.Length;
                            break;
                        }
                    } while (true);
                    continue;
                }
                //不明
                ei = new KecaknoahError
                {
                    Column = col,
                    Line = line,
                    Message = "不正なトークンです。"
                };
                result.Error = ei;
                result.Success = false;
                return result;
            }
            result.Success = true;
            return result;
        }
Пример #2
0
 /// <summary>
 /// 指定された<see cref="KecaknoahLexResult"/>を式として解析します。
 /// </summary>
 /// <param name="lex">字句解析の結果</param>
 /// <returns>構築されたAST</returns>
 public KecaknoahAst ParseAsExpression(KecaknoahLexResult lex)
 {
     var result = new KecaknoahAst(lex.SourceName);
     try
     {
         var q = new Queue<KecaknoahToken>(lex.Tokens);
         var top = ParseExpression(q);
         if (q.Count != 0) throw new KecaknoahParseException(q.Dequeue().CreateErrorAt("解析されないトークンが残っています。"));
         result.RootNode = top;
         result.Success = true;
     }
     catch (KecaknoahParseException e)
     {
         result.RootNode = null;
         result.Success = false;
         result.Error = e.Error;
     }
     return result;
 }
Пример #3
0
        /// <summary>
        /// ソース名とソースを指定して解析します。
        /// </summary>
        /// <param name="name">ソース名</param>
        /// <param name="source">解析対象のソースコード</param>
        /// <returns></returns>
        private KecaknoahLexResult AnalyzeFromText(string name, string source)
        {
            var result = new KecaknoahLexResult(name);
            var line   = 0;
            var col    = 0;
            var cq     = "";
            Tuple <string, KecaknoahTokenType> kw;
            Match          lm;
            KecaknoahError ei;

            while (source != "")
            {
                //空白論理行

                if (source.StartsWith(Environment.NewLine))
                {
                    source = source.Substring(Environment.NewLine.Length);
                    result.AddToken(new KecaknoahToken {
                        Position = new Tuple <int, int>(line, col), TokenString = "<NewLine>", Type = KecaknoahTokenType.NewLine
                    });
                    line++;
                    col = 0;
                    continue;
                }

                /*
                 * if (source.StartsWith(";"))
                 * {
                 *  source = source.Substring(1);
                 *  result.AddToken(new KecaknoahToken { Position = new Tuple<int, int>(line, col), TokenString = ";", Type = KecaknoahTokenType.Semicolon });
                 *  col++;
                 *  continue;
                 * }
                 */
                Tuple <string, string> mcq = null;
                if ((mcq = MultilineCommentQuotations.FirstOrDefault(p => source.StartsWith(p.Item1))) != null)
                {
                    source = source.Substring(mcq.Item1.Length);
                    col   += mcq.Item1.Length;
                    var ce  = source.IndexOf(mcq.Item2);
                    var ecs = source.IndexOf(mcq.Item1);
                    //不正な複数行コメント
                    if ((ecs >= 0 && ecs < ce) || ce < 0)
                    {
                        ei = new KecaknoahError
                        {
                            Column  = col,
                            Line    = line,
                            Message = "不正な複数行コメントです。コメントが終了していないか、入れ子になっています。"
                        };
                        result.Error   = ei;
                        result.Success = false;
                        return(result);
                    }
                    while (true)
                    {
                        ce = source.IndexOf(mcq.Item2);
                        var cl = source.IndexOf(Environment.NewLine);
                        if ((cl > 0 && ce < cl) || cl < 0)
                        {
                            source = source.Substring(ce + mcq.Item2.Length);
                            col   += ce + mcq.Item2.Length;
                            break;
                        }
                        else
                        {
                            source = source.Substring(cl + Environment.NewLine.Length);
                            line++;
                            col = 0;
                        }
                    }
                    continue;
                }
                //コメント
                if ((cq = LineCommentStart.FirstOrDefault(p => source.StartsWith(p))) != null)
                {
                    source = source.Substring(cq.Length);
                    col   += cq.Length;
                    var cl = source.IndexOf(Environment.NewLine);
                    if (cl >= 0)
                    {
                        source = source.Substring(cl + Environment.NewLine.Length);
                        line++;
                        col = 0;
                    }
                    else
                    {
                        //ラストコメント
                        source = "";
                    }
                    continue;
                }
                //空白
                if ((lm = WhitespacePattern.Match(source)).Success && lm.Index == 0)
                {
                    source = source.Substring(lm.Length);
                    col   += lm.Length;
                    continue;
                }
                //演算子
                if ((kw = Operators.FirstOrDefault(p => source.StartsWith(p.Item1))) != null)
                {
                    source = source.Substring(kw.Item1.Length);
                    col   += kw.Item1.Length;
                    result.AddToken(kw.CreateToken(col, line));
                    continue;
                }
                //識別子・キーワード
                if ((lm = IdentiferPattern.Match(source)).Success && lm.Index == 0)
                {
                    if ((kw = Keywords.FirstOrDefault(p => lm.Value == p.Item1)) != null)
                    {
                        source = source.Substring(kw.Item1.Length);
                        col   += kw.Item1.Length;
                        result.AddToken(kw.CreateToken(col, line));
                    }
                    else
                    {
                        source = source.Substring(lm.Length);
                        col   += lm.Length;
                        result.AddToken(lm.Value.CreateTokenAsIdentifer(col, line));
                    }
                    continue;
                }
                //リテラル
                if ((lm = BinaryNumberPattern.Match(source)).Success && lm.Index == 0)
                {
                    source = source.Substring(lm.Length);
                    col   += lm.Length;
                    result.AddToken(lm.Value.CreateTokenAsBinaryNumber(col, line));
                    if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0)
                    {
                        continue;
                    }
                }
                if ((lm = OctadecimalNumberPattern.Match(source)).Success && lm.Index == 0)
                {
                    source = source.Substring(lm.Length);
                    col   += lm.Length;
                    result.AddToken(lm.Value.CreateTokenAsOctadecimalNumber(col, line));
                    if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0)
                    {
                        continue;
                    }
                }
                if ((lm = HexadecimalNumberPattern.Match(source)).Success && lm.Index == 0)
                {
                    source = source.Substring(lm.Length);
                    col   += lm.Length;
                    result.AddToken(lm.Value.CreateTokenAsHexadecimalNumber(col, line));
                    if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0)
                    {
                        continue;
                    }
                }
                if ((lm = HexatridecimalNumberPattern.Match(source)).Success && lm.Index == 0)
                {
                    source = source.Substring(lm.Length);
                    col   += lm.Length;
                    result.AddToken(lm.Value.CreateTokenAsHexatridecimalNumber(col, line));
                    if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0)
                    {
                        continue;
                    }
                }
                if ((lm = DecimalNumberPattern.Match(source)).Success && lm.Index == 0)
                {
                    source = source.Substring(lm.Length);
                    col   += lm.Length;
                    result.AddToken(lm.Value.CreateTokenAsDecimalNumber(col, line));
                    if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0)
                    {
                        continue;
                    }
                }
                if ((cq = StringQuotation.FirstOrDefault(p => source.StartsWith(p))) != null)
                {
                    source = source.Substring(cq.Length);
                    col   += cq.Length;
                    int qp = 0, eqp = 0, inp = 0;
                    var ls = "";
                    do
                    {
                        eqp = source.IndexOf("\\" + cq);
                        qp  = source.IndexOf(cq);
                        inp = source.IndexOf(Environment.NewLine);
                        if (inp >= 0 && inp < qp)
                        {
                            ei = new KecaknoahError
                            {
                                Column  = col,
                                Line    = line,
                                Message = "文字列リテラル中に直接改行が含まれています。改行を表現したい場合、\\nを利用してください。"
                            };
                            result.Error   = ei;
                            result.Success = false;
                            return(result);
                        }
                        if (qp < 0)
                        {
                            ei = new KecaknoahError
                            {
                                Column  = col,
                                Line    = line,
                                Message = "文字列リテラルが閉じていません。"
                            };
                            result.Error   = ei;
                            result.Success = false;
                            return(result);
                        }
                        if (eqp >= 0 && qp - eqp == 1)
                        {
                            ls    += source.Substring(0, qp + cq.Length);
                            source = source.Substring(qp + cq.Length);
                            col   += qp + cq.Length - 1;
                            continue;
                        }
                        else
                        {
                            ls    += source.Substring(0, qp);
                            source = source.Substring(qp + cq.Length);
                            foreach (var i in StringLiteralEscapes)
                            {
                                ls = ls.Replace(i.Item1, i.Item2);
                            }
                            result.AddToken(new KecaknoahToken {
                                Position = new Tuple <int, int>(col, line), TokenString = ls, Type = KecaknoahTokenType.StringLiteral
                            });
                            col += qp + cq.Length;
                            break;
                        }
                    } while (true);
                    continue;
                }
                //不明
                ei = new KecaknoahError
                {
                    Column  = col,
                    Line    = line,
                    Message = "不正なトークンです。"
                };
                result.Error   = ei;
                result.Success = false;
                return(result);
            }
            result.Success = true;
            return(result);
        }
Пример #4
0
 /// <summary>
 /// 指定された<see cref="KecaknoahLexResult"/>を元にASTを構築します。
 /// </summary>
 /// <param name="lex">字句解析の結果</param>
 /// <returns>構築されたAST</returns>
 public KecaknoahAst Parse(KecaknoahLexResult lex)
 {
     var result = new KecaknoahAst(lex.SourceName);
     try
     {
         var top = ParseFirstLevel(new Queue<KecaknoahToken>(lex.Tokens));
         result.RootNode = top;
         result.Success = true;
     }
     catch (KecaknoahParseException e)
     {
         result.RootNode = null;
         result.Success = false;
         result.Error = e.Error;
     }
     return result;
 }