10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

C#Flex の使い方とか

C#FlexはGPLで配布されてるアプリケーションです。
字句解析を行うアプリケーションですね。
字句解析が何かはどこか適当な所に任せておいて…

まぁ、要するに
a+b*5+(4+5)

a,+,b,*,5,+,(,4,+,5,)
に分けたり

if(a==b)




if,(,a,==,b,),{…

に分けたりする行程
この後構文解析する
構文解析器については星一の日記というサイトに簡単に書いてある

このソフトはコンパイラコンパイラとか言ってソースコードをはく…でそれをプロジェクトに入れて使う…
ライセンスはGPLだけどはかれたソースコードの著作権はその入力データの著作者を継承する。
なので、GPLソフトは使うなとか言われていなければ大丈夫

簡単な入力コード




using System;
using System.IO;
namespace Calc{


%%


%class Scanner

%char
%unicode

%{
static int line=1;
public static int Line{get{return line;}}
public bool IsEnd(){ return zzAtEOF; }
%}

%eof{

Console.WriteLine("\n"+line+"Lines");
line=1;
%eof}

blank = [ \t]
//hiragana= [\u3040-\u30f4]
//jp = {hiragana}|[\u4e00-\u9fa0\uf900-\ufa0b]
//id = ({jp}|[a-zA-Z_])({jp}|[a-zA-Z_0-9])*
int = [1-9][0-9]*|0
//hint = "0x"[0-9a-fA-F]+
//double = ({int})"."({int})
ln = "\r\n"|"\n"


%%

{

"==" {return Token.Eq;}
[-+*/%] {return (int)yytext()[0];}


{blank}+ {;}
{ln} {line++;}

{int} {return new Yytoken(Token.Ival,Int32.Parse(yytext()));}
<<EOF>> {return 0;}
. {new Error(line,"識別子として認識できません。:"+yytext());}

}


%%
}


ここまで以下解説

using System;
using System.IO;
namespace Calc{


%%

この%%より上の部分はそのまま吐かれるコードに書き出される

using System;
using System.IO;

は使用している名前空間
これ書かないとだめ

内部でTextReader使ってるから

%class Scanner

%char
%unicode

クラス名をScannerにしてchar使ってunicode使う…
らしいよ?

%{
static int line=1;
public static int Line{get{return line;}}
public bool IsEnd(){ return zzAtEOF; }
%}

%{~%}内はソースコードにべた書きされる。
lineがstaticだとエラー処理の時楽っていうか変なメンバ入れなくてすむように…
public bool IsEnd(){ return zzAtEOF; }は解析終了したかどうか

%lineというのを上に書けば行数記録してくれるらしいんだけど0行目からカウントが始まるので非常にわかりにくい


%eof{

Console.WriteLine("\n"+line+"Lines");
line=1;
%eof}

%eofの名の通りファイルが終わったら呼び出される処理
lineはstaticなので1にしておく
因みに日本語使うと文字化けするひどいひどい

blank = [ \t]
//hiragana= [\u3040-\u30f4]
//jp = {hiragana}|[\u4e00-\u9fa0\uf900-\ufa0b]
//id = ({jp}|[a-zA-Z_])({jp}|[a-zA-Z_0-9])*
int = [1-9][0-9]*|0
//hint = "0x"[0-9a-fA-F]+
//double = ({int})"."({int})
ln = "\r\n"|"\n"

正規表現のルール表
正規表現は解説は別の所に
//はコメント(使わない)
blankは[ \t]だから「 (半角スペース)」orタブ文字は空白と考える…の意味

hiragana= [\u3040-\u30f4]

はひらがなと書いてあるけどその実ひらがな+カタカナの範囲+α
ユニコード指定じゃないと文字化け…

jp = {hiragana}|[\u4e00-\u9fa0\uf900-\ufa0b]

は日本語
大体網羅してると思う…漏れがあっても責任とらん
仮名文字か漢字

id = ({jp}|[a-zA-Z_])({jp}|[a-zA-Z_0-9])*

は変数とか使うときに
日本語とa-z,A-Z,_が一文字目でそれに0-9を追加したやつが何文字か続いても続かなくてもいい

int = [1-9][0-9]*|0

整数は09とかは禁止するただし0のみ例外

//hint = "0x"[0-9a-fA-F]+
//double = ({int})"."({int})

は16進数とdouble使うのでしたらどうぞ

ln = "\r\n"|"\n"

改行本当はEnvironment.NewLine使いたいけどまぁ、二つ

YYINITIALで囲んでルール定義
左の正規表現と合致した場合右の処理が実行される。
戻り値はYytokenこの処理内で戻らなくても良い

Yytokenは自分で定義する。
ここでは以下の通り定義してみる

class Yytoken
{
public int Token { get; private set; }
public int Ival { get; private set; }

public Yytoken()
{
}
public Yytoken(int t)
{
Token = t;
}
public Yytoken(int t, int i) : this(t) { Ival = i; }

public static implicit operator Yytoken(int t)
{ return new Yytoken(t); }
public static implicit operator int(Yytoken y) { return y.Token; }


}

とりあえずintから/への暗黙的変換を危ないけど使ってみる
------------------------------------------------------------------------

{

"==" {return Token.Eq;}
[-+*/%] {return (int)yytext()[0];}


{blank}+ {;}
{ln} {line++;}

{int} {return new Yytoken(Token.Ival,Int32.Parse(yytext()));}
<<EOF>> {return 0;}
. {new Error(line,"識別子として認識できません。:"+yytext());}

}

"==" {return Token.Eq;}
等しいかどうかの演算子のつもり(何に使っても良いけど^^:)

Token.Eq

はmonoのjayが吐くコードに書かれているすべてがpublic const int の258からぐらいから始まる数字達
こんな感じで羅列するわけさ

public static class Token
{
public const int Eq=258;
}

その258までの理由は

[-+*/%] {return (int)yytext()[0];}

yytext()は読み込み中でプールされている文字列
その0文字目をintで戻してやる。
たとえば「+」が入ったら
(int)yytext()[0]は(int)'+'と等しい

上の"=="の時はyytext()には「==」がプールされている

{blank}+ {;}
{ln} {line++;}

空白文字の連続は何もしない…明示的に;入れてある。
改行は行数増やす上述の通り値を返す必要はない

{int} {return new Yytoken(Token.Ival,Int32.Parse(yytext()));}

Int32.Parse(yytext())でyytext()に入ってるのをintに変換


<<EOF>> {return 0;}

はEOFになったら0を返してみる

. {new Error(line,"識別子として認識できません。:"+yytext());}

はError処理.ですべての文字を捕まえてエラーとしている
これやんないと例外が出る。

newでインスタンス生成してるけど
速度面考えたらResult.Errorとかにした方が良かったかなぁ~

コンパイル方法はcmdでってたたけばいい

\ csflex --csharp ファイル名

因みに沈黙は成功の意でもなく普通にログが出てくる

上の定義コードはNYSLで使ってください。(別にそこまであれなものでもない)
スポンサーサイト

Comment

Secret

検索フォーム

RSSリンクの表示

リンク

リンクというか個人的によく使うアルゴリズムの解説サイト… C#でなかったりする

ブロとも申請フォーム

この人とブロともになる

QRコード

QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。