1

시간이 포함 된 데이터베이스의 열이 HH:MM 형식입니다. 이제 11:00 - 12:00과 같은 간단한 표현식이 있다면 나는 C#에서 확장 메서드를 쉽게 만들 수 있습니다. SubtractTime으로 호출하고 런타임에 내 인수를 전달합니다. 나는 예를 들어 데이터베이스에 내 공식을 저장합니다 :디자인 지원 : 런타임에 계산 된 식의 시간 계산

Condition      Value 
ExamTimeRemaing > 10:00  SubtractTime(Original,Remaining)  

을 이제 위의 경우에 내가 런타임에 내 SubtractTime 기능을 사용하여 반사 호출 할 수 있습니다, 그러나 내 문제는 이것이다, 어떤 내 표현처럼 복잡하게 될 경우 :

10:00 + 12:00 * 00:02 - 10:11 

어떻게 표현식을 구문 분석합니까? 코딩에 도움이 필요하지 않습니다. 이미 시간을 틱으로 변환 한 다음 내 확장을 HH:MM으로 가지고 있습니다. 이것은 디자인에 관한 질문입니다. 나는 규칙 엔진을 효율적으로 생성 할 수 있도록 확장 가능한 솔루션을 원한다.

+11

12:00 * 00:02의 결과는 무엇입니까? –

+4

이것은 일반적인 렉서/파서 질문입니다. 나는 렉서와 그램저가 무엇인지에 대해 독해 할 것을 강력하게 권고 할 수있다. Antlr과 금색 파서는 좋은 출발점입니다. – atlaste

+1

HH MM의 곱셈은 @PaulZahra가 언급 한대로 정교 할 필요가 있습니다. –

답변

0

나는 그것을 문자열로 저장하고 연산자를 찾는다. 올바른 순서로 결과를 구문 분석하고 계산하는 재귀 함수 ParseAndCalc (문자열 입력)를 만듭니다. 이 같은 것 :

double ParseAndCalc(string input) 
{ 
    string[] sub; 
    double result = 0; 
    if(input.Contains("+")) 
    { 
     sub = input.Split('+'); 
     foreach(string substring in sub) 
     { 
      result += ParseAndCalc(substring); 
     } 
    } 
    else if (input.Contains("-")) 
    { 
     sub = input.Split('-'); 
     foreach(string substring in sub) 
     { 
      result -= ParseAndCalc(substring); 
     } 
    } 
    else if (input.Contains("*")) 
    { 
     sub = input.Split('*'); 
     foreach(string substring in sub) 
     { 
      result *= ParseAndCalc(substring); 
     } 
    } 
    else if (input.Contains("/")) 
    { 
     sub = input.Split('/'); 
     foreach(string substring in sub) 
     { 
      double parsed = ParseAndCalc(substring); 
      if(parsed != 0) 
      { 
       result /= ParseAndCalc(substring); 
      } 
      else 
      { 
       // Error 
      } 
     } 
    } 
    return result; 
} 
+0

내가 잘못 읽었을 수도 있지만 연산자 우선 순위는 ** 곱하기 전에 덧셈과 뺄셈 **이라고 말하는 것 같습니다. 그것은 12:00 * 00:02 가야하고 (+) 오른쪽 (-) 왼쪽. 예를 들어 올바른 순서를 설명하기 위해 괄호를 사용하십시오 :'10 + (12 * (2/60)) - 10.1833333' –

+0

네 말이 맞아. 나는 실제로 시간을 곱하는 것이 어쨌든 이상한 것처럼 실제 계산에주의를 기울이지 않았다. 개념은 좋지만. – David

+0

흠, 나는 개인적으로 좋은 개념을 말하지 않을 것입니다. Time Machine이나 해킹으로 작업 시간이 길어지면 안됩니다. 나는 시간을 몇 분씩 늘리는 것을 들어 본 적이 없으며, OP를 정교하게 물어 보았습니다. ** 편집 : ** 계산기처럼 좋은 개념을 의미하면 DataTables에 '계산'메소드가 있습니다. 예 :'var eleven = new DataTable(). Compute (2 + 3 * 3); ' –

0

먼저 개발 및 유지 관리 오버 헤드를 고려해야합니다. 표현 파서를 작성하는 것은 Antlr 등을 사용하여 완전히 우습다. 대신 Jurassic이나 다른 .NET 기반의 간단한 JavaScript 엔진과 같은 JavaScript 엔진과 같은 준비된 솔루션을 사용한다. 규칙은 데이터베이스 자체에 저장되어있는 경우

SQL 저장 프로 시저/사용자 정의 함수

또한, 다음, 대신 파서를 만드는, 당신은 구문 분석과 표현을 평가하기 위해 SQL 자체의 기능을 사용할 수 있습니다. SQL 표현식을 동적으로 구성하고 매개 변수를 전달할 수 있습니다. 또는 저장 프로 시저 또는 잘 정의되고 확장 가능하며 데이터베이스 컨텍스트 내에서 유지되는 사용자 정의 함수를 생성하십시오.

오픈 소스 .NET 자바 스크립트 엔진

당신은 여전히 ​​자바 스크립트 형식으로 데이터베이스에 수식을 저장할 수는, 첫째 자바 스크립트를 잘 잘 이해하고 복잡한 표현을 처리 할 수 ​​알려져있다. 풍부한 언어 기능을 제공 할뿐 아니라 수식에서 기존 JavaScript 라이브러리를 계속 사용할 수있는 많은 무료 및 안정적인 JavaScript 엔진이 있습니다. 예를 들어 나중에 Base64가 필요하다면 일부 github에서 Base64를 가져 와서 JavaScript에 넣을 수 있습니다.

C# 컴파일러

CSharpCompilerProvider 클래스는 당신에게 어셈블리로 C#을 소스를 컴파일 할 수있는 방법을 제공하고, 내가 무엇을 할 것이라고하는 것은, 텍스트 서식 파일을 사용하여 소스 파일을 만들 수와 함께 SQL 컴파일 및 저장 조립입니다 Formulat를 호출해야 할 때, 컴파일 된 버전을 가져오고 Assembly.Load으로로드하고 인터페이스가있는 파싱 된 클래스를 만들고 메소드를 호출 할 수 있습니다. .NET이 컴파일되고 데이터베이스에 varbinary(max)으로 저장할 수있는 어셈블리를 제공합니다.

0

여기에 대한 답변은이 방법을 충분히 설명합니다. 이것을 시도하기로 결정했다면 아마 ANTLR 경로를 직접 선택할 것입니다.

그렇다면 나는 왜 당신이 이것을하고 싶은지에 대해 진지하게 생각할 것입니다. 당신은 "규칙 엔진"을 만들고 있다고 언급했습니다.이것에서, 당신은 데이터베이스 또는 당신이 "규칙"으로 비즈니스 로직을 잔뜩 저장하고 "규칙 엔진"이 일부 데이터에 적용이 읽고 싶어 뭔가있어. 이 일환으로, 당신은 어떤 종류의 표현 파서가 특정 종류의 규칙을 구문 분석하고 평가할 수 있기를 원합니다.

이와 같은 디자인을 살펴보면 규칙을 파싱하고 실행하는 데 따르는 문제가 섞이지 않도록주의해야합니다. 규칙을 XML, JSON 또는 좋아하는 콘텐츠 형식으로 인코딩 할 수 있습니다. 그렇게하면 파서를 전혀 작성할 필요가 없습니다. 방금 표현식을 평가합니다.

var myRule = [ 
    { $value: '10:00' }, 
    { $add: '12:00' }, 
    { $multiply: 2 }, 
    { $subtract: '10:11' } 
]