So würde ich anfangen:
Code:
Expr -> Left_Expr '+' Right_Expr
=> "IF Compatible($Left_Expr.Unit,$Right_Expr.Unit)= True
THEN $Expr := Normalize($Left_Expr.Value) + Normalize($Right_Expr.Value)
ELSE Error(UnitsNotCompatible)"
| Factor
Unit
Factor -> <Number>
| '(' Expression ')'
Unit ->
| m
| cm
| g
| kg
Compatible ist ein 2-dimensionales Feld ARRAY[TUnit,TUnit] OF Boolean, der Eintrag [cm,m] wird auf True gesetzt, [g,cm] auf False. Normalize ist ein ARRAY[TUnit,TUnit] OF Real und enthält die Umrechnungsfaktoren in die Darstellungeinheit: [cm,m] = 0.01,[kg,g] = 1000. Die Eingabe "30 knirsch" wird von der kontextfreien Fehlerbehandlung abgewiesen, die Eingabe "30g + 40 cm" von der kontext-sensitiven. Die Hinzunahme weiterer Einheiten bedeutet eine zusätzliche Zeile in der Grammatik und zwei Änderungen in Compatible und Normalize.
Für das Rechnen und Umformen mit abgeleiteten Einheiten bietet sich ein endlicher Automat an, der über dem kompletten Syntaxbaum arbeitet.